Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 11 from a total of 11 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Register Collect... | 10951161 | 4 days ago | IN | 0 APE | 0.00186036 | ||||
Register Collect... | 10951080 | 4 days ago | IN | 0 APE | 0.00186036 | ||||
Register Collect... | 10538520 | 12 days ago | IN | 0 APE | 0.00186036 | ||||
Read | 9796340 | 23 days ago | IN | 0.4 APE | 0.00880407 | ||||
Register Collect... | 9351097 | 31 days ago | IN | 0 APE | 0.00186041 | ||||
Register Collect... | 9350995 | 31 days ago | IN | 0 APE | 0.00186041 | ||||
Set Required Con... | 9348944 | 31 days ago | IN | 0 APE | 0.00122403 | ||||
Set Peer | 9348942 | 31 days ago | IN | 0 APE | 0.00121091 | ||||
Set Required Con... | 9348864 | 31 days ago | IN | 0 APE | 0.00122403 | ||||
Set Peer | 9348860 | 31 days ago | IN | 0 APE | 0.00121091 | ||||
Grant Role | 9348513 | 31 days ago | IN | 0 APE | 0.0013038 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
11257311 | 17 mins ago | 0.25233104 APE | ||||
11257311 | 17 mins ago | 0.25233104 APE | ||||
11251873 | 2 hrs ago | 0.25233104 APE | ||||
11251873 | 2 hrs ago | 0.25233104 APE | ||||
11248384 | 2 hrs ago | 0.25233104 APE | ||||
11248384 | 2 hrs ago | 0.25233104 APE | ||||
11242197 | 4 hrs ago | 0.3407743 APE | ||||
11242197 | 4 hrs ago | 0.3407743 APE | ||||
11242190 | 4 hrs ago | 0.29655267 APE | ||||
11242190 | 4 hrs ago | 0.29655267 APE | ||||
11241248 | 4 hrs ago | 0.25233104 APE | ||||
11241248 | 4 hrs ago | 0.25233104 APE | ||||
11229588 | 9 hrs ago | 0.25233104 APE | ||||
11229588 | 9 hrs ago | 0.25233104 APE | ||||
11229196 | 9 hrs ago | 4.71871559 APE | ||||
11229196 | 9 hrs ago | 4.71871559 APE | ||||
11229147 | 9 hrs ago | 0.25233104 APE | ||||
11229147 | 9 hrs ago | 0.25233104 APE | ||||
11228710 | 10 hrs ago | 0.29655267 APE | ||||
11228710 | 10 hrs ago | 0.29655267 APE | ||||
11228599 | 10 hrs ago | 0.25233104 APE | ||||
11228599 | 10 hrs ago | 0.25233104 APE | ||||
11228475 | 10 hrs ago | 0.47343919 APE | ||||
11228475 | 10 hrs ago | 0.47343919 APE | ||||
11228225 | 10 hrs ago | 0.25233104 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, bytes24 rightsIdentifier) 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, rightsIdentifier ) 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], SHADOW_TOKEN_RIGHTS ) }); } } 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; } } if (newOwner != address(0)) { 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]; } if (multicallDataLength > 0) { 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 multicallDataRaw = new bytes[](tokenIds.length); address nftContractToDelegate = collectionAddress == punkAdapter ? CRYPTOPUNKS721_ADDRESS : collectionAddress; uint256 multicallDataLength = 0; for (uint256 i = 0; i < tokenIds.length; ++i) { uint256 tokenId = tokenIds[i]; address delegatedOwner = delegatedOwners[collectionAddress][tokenId]; if (delegatedOwner == address(0)) continue; multicallDataRaw[i] = abi.encodeWithSelector( IDelegateRegistry.delegateERC721.selector, delegatedOwner, nftContractToDelegate, tokenId, _GLOBAL_RIGHTS_WITH_MAX_EXPIRY, false ); unchecked { ++multicallDataLength; } delegatedOwners[collectionAddress][tokenId] = address(0); } bytes[] memory multicallData = new bytes[](multicallDataLength); for (uint256 i = 0; i < multicallDataLength; ++i) { multicallData[i] = multicallDataRaw[i]; } if (multicallDataLength > 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"},{"internalType":"bytes24","name":"rightsIdentifier","type":"bytes24"}],"name":"unlockedExclusiveOwnerByRights","outputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bool","name":"_isLocked","type":"bool"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6101208060405234610397575f9060a0816156ce803803809161002282856103f9565b8339810103126103975761003581610430565b9061004260208201610430565b9061004f60408201610444565b92610068608061006160608501610430565b9301610430565b604051635e280f1160e01b81526001600160a01b0390921693909190602082600481885afa91821561038c575f926103bd575b5032156103aa575f8054326001600160a01b0319821681178355604051949290916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36001600160a01b039081166080819052911690811561039b57803b15610397576024835f8193819563ca5eb5e160e01b845260048401525af1801561038c57610377575b5063fffff9be63ffffffff85161115610368579160209160049360e052610100526040518281014681528382526101666040836103f9565b905190206001600160401b03191660a052604051635e280f1160e01b815292839182905afa90811561031e578391610329575b5060405163416ecebf60e01b815290602090829060049082906001600160a01b03165afa90811561031e5783916102cb575b60c08290526004805463ffffffff60a01b191660a085901b63ffffffff60a01b161790555f5160206156ae5f395f51905f5260408561020932610455565b50610213326104ed565b5063ffffffff60045460a01c1690818152600160205282309120558151908152306020820152a16040516150ef908161055f823960805181818161077701528181610df101528181611b6701528181613706015281816140ea01526146e0015260a05181818161114401526133b3015260c05181818161065d015281816118f801528181611df501528181611f8f01526133fe015260e0518181816109ee0152612719015261010051818181610f4d0152614d480152f35b90506020813d602011610316575b816102e6602093836103f9565b8101031261031257916040916103095f5160206156ae5f395f51905f5294610444565b919350916101cb565b8280fd5b3d91506102d9565b6040513d85823e3d90fd5b90506020813d602011610360575b81610344602093836103f9565b81010312610312576020610359600492610430565b9150610199565b3d9150610337565b633df6e48d60e21b8552600485fd5b6103849195505f906103f9565b5f935f61012e565b6040513d5f823e3d90fd5b5f80fd5b632d618d8160e21b5f5260045ffd5b631e4fbdf760e01b5f525f60045260245ffd5b9091506020813d6020116103f1575b816103d9602093836103f9565b81010312610397576103ea90610430565b905f61009b565b3d91506103cc565b601f909101601f19168101906001600160401b0382119082101761041c57604052565b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820361039757565b519063ffffffff8216820361039757565b6001600160a01b0381165f9081525f51602061566e5f395f51905f52602052604090205460ff166104e8576001600160a01b03165f8181525f51602061566e5f395f51905f5260205260408120805460ff191660011790553391907f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c905f51602061564e5f395f51905f529080a4600190565b505f90565b6001600160a01b0381165f9081525f51602061568e5f395f51905f52602052604090205460ff166104e8576001600160a01b03165f8181525f51602061568e5f395f51905f5260205260408120805460ff191660011790553391905f51602061564e5f395f51905f528180a460019056fe60806040526004361015610011575f80fd5b5f3560e01c806301a0de05146103b457806301ffc9a7146103af57806304bd49a5146103aa578063066d5910146103a5578063108dcbdd146103a057806313137d651461039b57806317442b70146103965780631d56672114610391578063248a9ca31461038c5780632d69fc48146103875780632f2ff15d146103825780633400288b1461037d5780633530511a1461037857806336568abe1461037357806336b1dd211461036e57806337cb6736146103695780634202fce11461036457806345248a371461035f578063461572f91461035a57806347c1b317146103555780635535d461146103505780635e280f111461034b57806360eddbe4146103465780636a4d8672146103415780636eaa69041461033c5780636fe87dba14610337578063715018a6146103325780637d25a05e1461032d57806382413eac14610328578063864c651514610323578063881ae9f81461031e5780638da5cb5b1461031957806391d1485414610314578063993151601461030f578063a0238f3e1461030a578063a217fddf14610305578063a34ac81b14610300578063ade7142d146102fb578063b33b522d146102f6578063b98bd070146102f1578063bb0b6a53146102ec578063bc70b354146102e7578063c9df8167146102e2578063ca5eb5e1146102dd578063cfac96ce146102d8578063d1e1d0cc146102d3578063d547741f146102ce578063da383b97146102c9578063e052778a146102c4578063e60c287c146102bf578063eba1cf08146102ba578063f0a9e481146102b5578063f1748835146102b0578063f1c418ee146102ab578063f2fde38b146102a6578063fccc4331146102a1578063fe084c8f1461029c5763ff7bd03d14610297575f80fd5b61243b565b612237565b61220f565b612186565b612164565b612121565b6120da565b61207b565b61201c565b611fe2565b611d42565b611d01565b611c68565b611bdc565b611b3f565b611870565b61181c565b6117e3565b6116de565b611671565b6115dc565b611574565b61155a565b611504565b611390565b61133e565b611317565b6112b5565b611243565b6111e5565b6111bf565b611168565b611124565b610f8d565b610f38565b610e20565b610ddc565b610d86565b610ba3565b610b7d565b610b0e565b610add565b610a1d565b6109d9565b610991565b610936565b610905565b6108b1565b61088a565b610857565b61082d565b61080c565b61070e565b610681565b610641565b6104e4565b61041c565b6103ce565b6001600160a01b038116036103ca57565b5f80fd5b346103ca5760403660031901126103ca576004356103eb816103b9565b6001600160a01b039081165f9081526007602090815260408083206024358452825291829020549151919092168152f35b346103ca5760203660031901126103ca5760043563ffffffff60e01b81168091036103ca57602090637965db0b60e01b8114908115610461575b506040519015158152f35b6301ffc9a760e01b1490505f610456565b9181601f840112156103ca578235916001600160401b0383116103ca576020808501948460051b0101116103ca57565b606435906001600160801b03821682036103ca57565b60a435906001600160801b03821682036103ca57565b608435906001600160801b03821682036103ca57565b346103ca5760803660031901126103ca57600435610501816103b9565b6024356001600160401b0381116103ca57610520903690600401610472565b91906044356001600160401b0381116103ca57610541903690600401610472565b9361054a6104a2565b6001600160a01b0385165f90815260056020526040902061056d905b5460601c90565b916001600160a01b038316156106295761059181866105c6995f976105ab9761338f565b946105a560045463ffffffff9060a01c1690565b966129d9565b60405180958192632f1c2cd560e21b83528660048401612554565b0381305afa918215610624576105e3935f93610600575b506136a3565b8051602091820151604080519283529282015290819081015b0390f35b61061d9193503d805f833e6106158183610cc5565b81019061252c565b915f6105dd565b612578565b622dc1c960e71b5f5260045ffd5b5f9103126103ca57565b346103ca575f3660031901126103ca57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346103ca5760203660031901126103ca5760043561069e816103b9565b60018060a01b03165f526005602052602060405f205460601c604051908152f35b60609060031901126103ca57600490565b60609060631901126103ca57606490565b9181601f840112156103ca578235916001600160401b0383116103ca57602083818601950101116103ca57565b60e03660031901126103ca57610723366106bf565b6064356084356001600160401b0381116103ca576107459036906004016106e1565b9060a43592610753846103b9565b60c4356001600160401b0381116103ca576107729036906004016106e1565b5050337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316036107f9578435946107b0866108f7565b6107b98661376a565b9560208201358097036107d357506107d195506137e1565b005b63ffffffff816107e389936108f7565b63309afaf360e21b5f521660045260245260445ffd5b6391ac5e4f60e01b5f523360045260245ffd5b346103ca575f3660031901126103ca57604080516001815260026020820152f35b346103ca5760203660031901126103ca576004355f52600a602052602060405f2054604051908152f35b346103ca5760203660031901126103ca5760206108826004355f526003602052600160405f20015490565b604051908152f35b346103ca575f3660031901126103ca5760206040516c3607fce1ac9e043a86675c5c2f8152f35b346103ca5760403660031901126103ca576107d16024356004356108d4826103b9565b6108f26108ed825f526003602052600160405f20015490565b6139aa565b6139e4565b63ffffffff8116036103ca57565b346103ca5760403660031901126103ca576107d1600435610925816108f7565b60243590610931613a74565b613a9a565b346103ca5760603660031901126103ca57600435610953816103b9565b60443560243567ffffffffffffffff19821682036103ca5761097492612607565b604080516001600160a01b03939093168352901515602083015290f35b346103ca5760403660031901126103ca576004356024356109b1816103b9565b336001600160a01b038216036109ca576107d191613ae0565b63334bd91960e11b5f5260045ffd5b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346103ca5760203660031901126103ca57600435610a3a816103b9565b60018060a01b03165f526009602052602060ff60405f2054166040519015158152f35b60806003198201126103ca57600435610a75816108f7565b91602435610a82816103b9565b91604435906001600160401b0382116103ca57610aa191600401610472565b90916064356001600160801b03811681036103ca5790565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b346103ca576105fc610afa610af136610a5d565b93929092612889565b604051918291602083526020830190610ab9565b346103ca57610b1c36610a5d565b6001600160a01b038085165f9081526005602052604090209195949391610b4290610566565b1615610629576105c6945f926105ab9260405195610b7787610b6985858560208501612958565b03601f198101895288610cc5565b87612889565b346103ca575f3660031901126103ca57602063ffffffff60045460a01c16604051908152f35b346103ca5760603660031901126103ca57600435610bc0816103b9565b6024356001600160401b0381116103ca57610bdf903690600401610472565b909190604435906001600160801b03821682036103ca576105fc93610afa936129d9565b6024359061ffff821682036103ca57565b359061ffff821682036103ca57565b90600182811c92168015610c51575b6020831014610c3d57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610c32565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b03821117610c8a57604052565b610c5b565b60e081019081106001600160401b03821117610c8a57604052565b604081019081106001600160401b03821117610c8a57604052565b90601f801991011681019081106001600160401b03821117610c8a57604052565b9060405191825f825492610cf984610c23565b8084529360018116908115610d645750600114610d20575b50610d1e92500383610cc5565b565b90505f9291925260205f20905f915b818310610d48575050906020610d1e928201015f610d11565b6020919350806001915483858901015201910190918492610d2f565b905060209250610d1e94915060ff191682840152151560051b8201015f610d11565b346103ca5760403660031901126103ca576105fc610afa610dd7600435610dac816108f7565b63ffffffff610db9610c03565b91165f52600260205260405f209061ffff165f5260205260405f2090565b610ce6565b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346103ca5760203660031901126103ca57600435610e3d816103b9565b610e45613a74565b60014603610f29576004546001600160a01b0316610f1a57600480546001600160a01b0319166001600160a01b0383161790556c3607fce1ac9e043a86675c5c2f3b156103ca5760405163a22cb46560e01b81526001600160a01b0382166004820152600160248201525f81604481836c3607fce1ac9e043a86675c5c2f5af1801561062457610f00575b506001600160a01b03167fb835fe32fb60b329ea744c781d0f1f6c73e746d5896560940444554cc0c275b55f80a2005b80610f0e5f610f1493610cc5565b80610637565b5f610ed0565b634dad647560e11b5f5260045ffd5b63057f3fa760e51b5f5260045ffd5b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6001600160401b038116036103ca57565b346103ca576101003660031901126103ca57600435610fab816108f7565b60243590604435610fbb81610f7c565b610fc4366106d0565b9160c43560e4356001600160401b0381116103ca57610fe79036906004016106e1565b909463ffffffff84169563fffff9be87116111155761102e92611020916040519586946304c98a8b60e51b602087015260248601612aa9565b03601f198101835282610cc5565b60405160208101906110468161102046863087612b0d565b51902061108c84611076886110698763ffffffff165f52600860205260405f2090565b905f5260205260405f2090565b906001600160401b03165f5260205260405f2090565b5403611106575f6110b684611076886110696110be9763ffffffff165f52600860205260405f2090565b555a30613ce8565b90156110fe57506040516001600160401b039190911681527f49a5bb7337668613a742dc30346f29d11f0b4d4a2c0745a08afccc9bb6cea3d090602090a3005b805190602001fd5b63a84ab60d60e01b5f5260045ffd5b634d30e69360e11b5f5260045ffd5b346103ca575f3660031901126103ca5760206040516001600160401b03197f0000000000000000000000000000000000000000000000000000000000000000168152f35b346103ca575f3660031901126103ca57611180613a74565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103ca5760403660031901126103ca576111db6004356108f7565b60206040515f8152f35b346103ca5760a03660031901126103ca576111ff366106bf565b506064356001600160401b0381116103ca5761121f9036906004016106e1565b5050602060843561122f816103b9565b6040516001600160a01b0390911630148152f35b346103ca5760403660031901126103ca576107d1600435611263816103b9565b60243590611270826108f7565b611278613a74565b60018060a01b03165f52600560205260405f209063ffffffff60401b82549160401b169063ffffffff60401b1916179055565b801515036103ca57565b346103ca5760203660031901126103ca577f57f2a528edf864f533774c287d06a5278e1a4447ed97923b7bbc251fcbd54f6f60206004356112f5816112ab565b6112fd613a74565b151560ff19600b541660ff821617600b55604051908152a1005b346103ca575f3660031901126103ca575f546040516001600160a01b039091168152602090f35b346103ca5760403660031901126103ca57602060ff611384602435600435611365826103b9565b5f526003845260405f209060018060a01b03165f5260205260405f2090565b54166040519015158152f35b346103ca5760a03660031901126103ca576113aa366106bf565b6064356084356001600160401b0381116103ca576113cc9036906004016106e1565b90923033036114f55763ffffffff63fffff9be91356113ea816108f7565b16111561142d57610708611410611409845f52600a60205260405f2090565b54426137aa565b1161141e576107d192614484565b631a86ecf960e01b5f5260045ffd5b8261143b939250019061431f565b6001600160a01b039283165f8181526005602052604090209093919290911690546114668160601c90565b906001600160a01b038216156106295763ffffffff16460361148c57506107d1926148e8565b5f93508392908390611020906114d5906114b6906001600160a01b03165b6001600160a01b031690565b946040519283916020830196639277283360e01b885260248401614362565b51925af16114e161437a565b506107d157635f0ad7b760e11b5f5260045ffd5b63139f696160e31b5f5260045ffd5b346103ca5760203660031901126103ca57602061ffff61155163ffffffff60043561152e816108f7565b1663ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b16604051908152f35b346103ca575f3660031901126103ca5760206040515f8152f35b346103ca5760203660031901126103ca57600435611591816103b9565b60018060a01b03165f526005602052608060405f20546040519063ffffffff8116825263ffffffff8160201c16602083015263ffffffff8160401c16604083015260601c6060820152f35b346103ca5760403660031901126103ca577fc40a8c1d6db18d083249778a76a84a78429c4fe53001aba75f470c597afaee27604060043561161c816108f7565b61ffff611627610c03565b61162f613a74565b16600c602052631fffffff8260031c165f52825f2060e08360051b168154908382821c1863ffffffff16901b18905563ffffffff8351921682526020820152a1005b346103ca5760603660031901126103ca576116d2600435611691816108f7565b60243563ffffffff604435926116a684610f7c565b165f52600860205260405f20905f5260205260405f20906001600160401b03165f5260205260405f2090565b54604051908152602090f35b346103ca5760203660031901126103ca576004356001600160401b0381116103ca5761170e903690600401610472565b90611717613a74565b61172082612b3b565b9061172e6040519283610cc5565b828252602082019260051b8101903682116103ca5780935b828510611756576107d184613ee5565b84356001600160401b0381116103ca578201906060823603126103ca576040519161178083610c6f565b803561178b816108f7565b835261179960208201610c14565b60208401526040810135906001600160401b0382116103ca57019036601f830112156103ca576020926117d3849336908581359101612b52565b6040820152815201940193611746565b346103ca5760203660031901126103ca5763ffffffff600435611805816108f7565b165f526001602052602060405f2054604051908152f35b346103ca5760603660031901126103ca57600435611839816108f7565b611841610c03565b604435906001600160401b0382116103ca576105fc92611868610afa9336906004016106e1565b929091612bea565b60c03660031901126103ca57600435611888816108f7565b60243590611895826103b9565b6044356001600160401b0381116103ca576118b4903690600401610472565b606492919235906118c4826103b9565b608435916118d1836103b9565b6118d96104b8565b906001600160a01b03811615611b305763ffffffff85169463ffffffff7f00000000000000000000000000000000000000000000000000000000000000001686148015611b23575b611115578315611b14576001600160a01b0388165f9081526005602052604090209261195f61195a611954865460601c90565b9561258d565b613fdf565b15611ae357889291906001600160a01b0385165f5b878110611a6f575050905f6119b56119d0935b888c604051986119af8a6119a185858d8660208601612980565b03601f1981018c528b610cc5565b86612889565b60405180948192632f1c2cd560e21b83528560048401612554565b0381305afa968715610624577f6a0cf129b799c36943cf19ef7755eafb0b597737ba2f970045385de48107886a97611a4e95611a30945f92611a53575b50611a16612480565b3481525f60208201526001600160a01b0390931693614061565b506040516001600160a01b0393841698909316969293849384612cbc565b0390a4005b611a689192503d805f833e6106158183610cc5565b905f611a0d565b909192939450611a8081888c612ca7565b3590823b156103ca576040516323b872dd60e01b815233600482015230602482015260448101929092525f8260648183875af191821561062457600192611acf575b5001908a94939291611974565b80610f0e5f611add93610cc5565b5f611ac2565b9091906001600160a01b0384163303611b055788925f6119b56119d093611987565b6348f5c3ed60e01b5f5260045ffd5b630f59b9ff60e01b5f5260045ffd5b5063fffff9be8611611921565b63d721852160e01b5f5260045ffd5b346103ca575f60203660031901126103ca57600435611b5d816103b9565b611b65613a74565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b156103ca5760405163ca5eb5e160e01b81526001600160a01b039091166004820152905f908290602490829084905af1801561062457611bd0575080f35b6107d191505f90610cc5565b346103ca5760403660031901126103ca577f69bdfca1ae414a7233840909f9c10a21560d38e0ed4fb50ff50b7b4c29ad96fe600435611c1a816103b9565b60243590611c27826112ab565b611c2f613a74565b6001600160a01b03165f81815260096020908152604091829020805460ff191660ff9515159586161790558151928352820192909252a1005b346103ca5760203660031901126103ca57600435611c85816108f7565b611c8d613a74565b63ffffffff81169063fffff9be821115611cf2576004805463ffffffff60a01b191660a09290921b63ffffffff60a01b169190911790556040519081527fd22acca42bfd0ebef8a1ca8347653f46f782b92b553ba57e0f2294426dfe26ac90602090a1005b633df6e48d60e21b5f5260045ffd5b346103ca5760403660031901126103ca576107d1602435600435611d24826103b9565b611d3d6108ed825f526003602052600160405f20015490565b613ae0565b346103ca5760a03660031901126103ca57600435611d5f816103b9565b602435611d6b816108f7565b60443591611d78836103b9565b60643590611d85826108f7565b60843592611d92846108f7565b611d9a61393b565b63ffffffff8116928315610f295763ffffffff8116958615611115576001600160a01b038116958615611fd3576001600160a01b038516958615611fd357627a120063ffffffff831611611fc4574603611f885763ffffffff7f000000000000000000000000000000000000000000000000000000000000000016880361111557868603611f79575b6001600160a01b0382165f908152600560205260409020611e47906114aa90610566565b611f6a5784611ecb611edb92611ebe611ef496611e9a87611e7b611f449c60018060a01b03165f52600660205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611eb1611ea561248f565b63ffffffff909a168a52565b63ffffffff166020890152565b63ffffffff166040870152565b6001600160a01b03166060850152565b6001600160a01b03165f90815260056020526040902090565b8151602080840151604080860151606096870151911b63ffffffff60401b1663ffffffff9094169190921b67ffffffff000000001617919091176001600160601b03199190931b16919091179055565b7f328b68290d8d3a315d25b2476661d7c921ee87029fc767a4916b407e2ee31ede5f80a4005b6341ab882d60e01b5f5260045ffd5b630232505d60e61b5f5260045ffd5b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168803611e2357634d30e69360e11b5f5260045ffd5b634a11e78360e11b5f5260045ffd5b63d92e233d60e01b5f5260045ffd5b346103ca575f3660031901126103ca5760206040517f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c8152f35b346103ca5760403660031901126103ca576004356001600160401b0381116103ca5761204c9036906004016106e1565b602435906001600160401b0382116103ca576105fc92612073610afa9336906004016106e1565b929091612d44565b346103ca5760403660031901126103ca576004356001600160401b0381116103ca576120ab9036906004016106e1565b602435906001600160401b0382116103ca576105fc926120d2610afa933690600401610472565b929091613030565b346103ca5760403660031901126103ca576107d16004356120fa816108f7565b602435612106816112ab565b61210e613a74565b1561211a573090613a9a565b5f90613a9a565b346103ca5760203660031901126103ca5760043561213e816103b9565b60018060a01b03165f526006602052602060018060a01b0360405f205416604051908152f35b346103ca575f3660031901126103ca57602060ff600b54166040519015158152f35b346103ca5760203660031901126103ca576004356121a3816103b9565b6121ab613a74565b6001600160a01b031680156121fc575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b346103ca575f3660031901126103ca576004546040516001600160a01b039091168152602090f35b60a03660031901126103ca5760043561224f816103b9565b6024356001600160401b0381116103ca5761226e903690600401610472565b6044356001600160401b0381116103ca5761228d903690600401610472565b936064359461229b866103b9565b6122a36104ce565b9184158015612433575b611b14576001600160a01b0381165f908152600560205260409020805460601c95908615610629576122e461195a6122e89261258d565b1590565b806123d8575b6123c9576122ff818885888661338f565b9061233e5f61232361231a60045463ffffffff9060a01c1690565b97848c886129d9565b60405180938192632f1c2cd560e21b83528a60048401612554565b0381305afa958615610624576105fc9a7fed0c24299d2da4e3728deedbf20de24c4ff0e754c89f20b3d2532fe63b43b531976123b695612387945f92611a535750611a16612480565b51974261239c8a5f52600a60205260405f2090565b556040516001600160a01b03909416969394859485613267565b0390a36040519081529081906020820190565b634a91ec5f60e01b5f5260045ffd5b50604051637347ebb960e01b81526020816004818a5afa908115610624575f91612404575b50156122ee565b612426915060203d60201161242c575b61241e8183610cc5565b8101906125dd565b5f6123fd565b503d612414565b5081156122ad565b346103ca5760603660031901126103ca576020612457366106bf565b63ffffffff8135612467816108f7565b165f52600182528160405f205491013560405191148152f35b60405190610d1e604083610cc5565b60405190610d1e608083610cc5565b60405190610d1e60e083610cc5565b60405190610d1e60c083610cc5565b60405190610d1e60a083610cc5565b6001600160401b038111610c8a57601f01601f191660200190565b81601f820112156103ca578051906124fd826124cb565b9261250b6040519485610cc5565b828452602083830101116103ca57815f9260208093018386015e8301015290565b906020828203126103ca5781516001600160401b0381116103ca5761255192016124e6565b90565b60609063ffffffff6125519493168152600160208201528160408201520190610ab9565b6040513d5f823e3d90fd5b35612551816108f7565b90604051608081018181106001600160401b03821117610c8a57604052606081935463ffffffff8116835263ffffffff8160201c16602084015263ffffffff8160401c166040840152811c910152565b908160209103126103ca5751612551816112ab565b908160209103126103ca5751612551816103b9565b6001600160a01b03165f90815260056020526040902090919061262e9061258d565b61258d565b9163ffffffff612645602085015163ffffffff1690565b161561287f5761266d606061265e855163ffffffff1690565b9401516001600160a01b031690565b9263ffffffff1646036127ae576040516331a9108f60e11b815260048101829052906020826024816001600160a01b0388165afa5f928161278d575b506126b857505050505f905f90565b6001600160a01b03821630036126d357505050503090600190565b602091935b604051637f63c3dd60e01b81526001600160a01b039091166004820152602481019190915267ffffffffffffffff19909216604483015281806064810103817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa5f918161275c575b506127565750905f90565b915f9150565b61277f91925060203d602011612786575b6127778183610cc5565b8101906125f2565b905f61274b565b503d61276d565b6127a791935060203d602011612786576127778183610cc5565b915f6126a9565b6001600160a01b038316908115801561282e575b156127d257505050505f90600190565b6040516331a9108f60e11b8152600481018290526020928390829060249082905afa5f918161280f575b5061280957505f936126d8565b936126d8565b612827919250843d8611612786576127778183610cc5565b905f6127fc565b50604051635a2d1e0760e11b815260048101829052602081602481865afa908115610624575f91612860575b506127c2565b612879915060203d60201161242c5761241e8183610cc5565b5f61285a565b5050505f90600190565b929150926128c79360018060a01b03165f52600560205263ffffffff60406128b2815f2061258d565b94828060208801511691161494015116613b88565b906128d0613bf0565b91600361ffff6128df856141fd565b1603612915576125519192604051916001600160801b03199060801b16602083015260108252612910603083610cc5565b614249565b61ffff612921846141fd565b633a51740d60e01b5f521660045260245ffd5b81835290916001600160fb1b0383116103ca5760209260051b809284830137010190565b6001600160a01b0390911681525f602082015260606040820181905261255193910191612934565b6001600160a01b0391821681529116602082015260606040820181905261255193910191612934565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff1660e0019063ffffffff82116129d457565b6129a9565b612a309293915060018060a01b03165f5260056020526001600160801b0363ffffffff612a0860405f2061258d565b51164614805f14612a7f576201adb0905b15612a7657816206390e5b81871602160116613b68565b90627a12006001600160801b03831611611fc45763ffffffff166060029063ffffffff82169182036129d457612a68612551926129bd565b90612a71613bf0565b613c0c565b8161c350612a24565b6201b7d890612a19565b908060209392818452848401375f828201840152601f01601f1916010190565b61255194926001600160401b03604060a09463ffffffff8135612acb816108f7565b168552602081013560208601520135612ae381610f7c565b16604083015260608201528160808201520191612a89565b805191908290602001825e015f815290565b91601460209493612b34936bffffffffffffffffffffffff199060601b1681520190612afb565b9081520190565b6001600160401b038111610c8a5760051b60200190565b929192612b5e826124cb565b91612b6c6040519384610cc5565b8294818452818301116103ca578281602093845f960137010152565b90606e116103ca57602e0190604090565b906054116103ca5760400190601490565b612bc49392610d1e92816040519687946020860190612afb565b918237015f815203601f198101845283610cc5565b916020612551938181520191612a89565b612c189163ffffffff610dd79296949596165f52600260205260405f209061ffff165f5260205260405f2090565b805115612c85578315612c7f576002841015612c50575050612c4c604051928392639a6d49cd60e01b845260048401612bd9565b0390fd5b9092612c65612c60368386612b52565b613fa7565b806002116103ca5760026125519301906001190191612baa565b92509050565b509190612551913691612b52565b634e487b7160e01b5f52603260045260245ffd5b9190811015612cb75760051b0190565b612c93565b91602091612cd591959495604085526040850191612934565b6001600160a01b03909416910152565b91908260409103126103ca5760208235612cfe816103b9565b92013590565b91908260409103126103ca5760208235612d1d816103b9565b920135612551816112ab565b60405190612d38602083610cc5565b5f808352366020840137565b612d57612d7492612d5f92959495612b88565b810190612ce5565b936001600160a01b0390911692810190612d04565b612e8e578183612d9a6126296125519560018060a01b03165f52600560205260405f2090565b91612da483613fdf565b15612e10576001600160a01b03165f9081526007602052604090206110209250612dde91612dd191611069565b546001600160a01b031690565b935b604080516001600160a01b0396871660208201529590931692850192909252606084019190915282906080820190565b505060600151612e2a906114aa906001600160a01b031681565b6040516331a9108f60e11b81526004810185905290602090829060249082905afa5f9181612e6d575b50612e6357506110205f93612de0565b6110209093612de0565b612e8791925060203d602011612786576127778183610cc5565b905f612e53565b505050612551612d29565b356001600160601b0319811692919060148210612eb4575050565b6001600160601b031960149290920360031b82901b16169150565b90612ed982612b3b565b612ee66040519182610cc5565b8281528092612ef7601f1991612b3b565b0190602036910137565b9190811015612cb75760051b81013590601e19813603018212156103ca5701908135916001600160401b0383116103ca5760200182360381136103ca579190565b908160609103126103ca578035612f58816103b9565b9160406020830135612cfe816103b9565b8051821015612cb75760209160051b010190565b90602080835192838152019201905f5b818110612f9a5750505090565b82516001600160a01b0316845260209384019390920191600101612f8d565b90602080835192838152019201905f5b818110612fd65750505090565b8251845260209384019390920191600101612fc9565b9261301461255195936130229360018060a01b03168652608060208701526080860190612f7d565b908482036040860152612f7d565b916060818403910152612fb9565b61305b612629611edb61305561304f613069966060969a99989a612b99565b90612e99565b60601c90565b01516001600160a01b031690565b61307282612ecf565b9161307c81612ecf565b9461308682612ecf565b915f915f5b82811061316f57505050815181106130b757506110209061255193949560405195869460208601612fec565b92906130c284612ecf565b936130cc81612ecf565b916130d682612ecf565b935f5b8381106130ff575050505061255193949550906110209160405195869460208601612fec565b80613153613149613122838e6131448e6131358461312f61312260019c8e612f69565b516001600160a01b031690565b92612f69565b6001600160a01b039091169052565b612f69565b6131358389612f69565b61315d8185612f69565b516131688289612f69565b52016130d9565b61317a818484612f01565b90501561325f576131d4816131c18b613135838a6131b16131a761319f848d8d612f01565b810190612f42565b9291989093612f69565b526001600160a01b031692612f69565b6001600160a01b0316613135838a612f69565b6131e16131228289612f69565b6131f16114aa613122848d612f69565b6001600160a01b039091160361320c575b6001905b0161308b565b926001809161321b8688612f69565b516132268289612f69565b52613241613237613122888c612f69565b613135838c612f69565b6132568b6131358361312f6131228b85612f69565b01939050613202565b600190613206565b949391949290928560408201604083525260608101935f965b80881061329c5750506125519495506020818503910152612934565b909460208060019263ffffffff89356132b4816108f7565b16815201960197019690613280565b908160011b91808304600214901517156129d457565b818102929181159184041417156129d457565b906132f682612b3b565b6133036040519182610cc5565b8281528092613314601f1991612b3b565b01905f5b82811061332457505050565b60209060405161333381610c8f565b5f81525f838201525f60408201525f60608201525f60808201525f60a0820152606060c082015282828501015201613318565b90600182018092116129d457565b90602382018092116129d457565b919082018092116129d457565b9291926133a461339f85876132d9565b6132ec565b935f6001600160401b034216967f0000000000000000000000000000000000000000000000000000000000000000915b81811061344a575050505050505090612551916134396133f26124ad565b600281529263ffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208501525f60408501526001600160401b03166060840152565b5f60808301523060a083015261415d565b5f5b84811061345c57506001016133d4565b6134a061347e61347561347084898c612ca7565b612583565b63ffffffff1690565b63ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b63ffffffff8116156111155784846134b785613366565b6134c182866132d9565b6134ca91613382565b61ffff1692888c878d886134df818684612ca7565b6134e890612583565b946134f292612ca7565b6134fb90612583565b6135049061376a565b6001600160a01b03169461351792612ca7565b604051631a98288d60e11b60208201526001600160a01b038d1660248201529035604482015267ffffffffffffffff19949094166064808601919091528452613561608485610cc5565b61356961249e565b61ffff909516855263ffffffff1660208501525f60408501526001600160401b038e16606085015261ffff1660808401526001600160a01b031660a083015260c0820152816135b887856132d9565b906135c291613382565b906135cd828c612f69565b526135d8908a612f69565b5060010161344c565b604051906135ee82610caa565b5f6020838281520152565b91908260409103126103ca5760405161361181610caa565b6020808294805184520151910152565b906040828203126103ca57612551916135f9565b906020909392936040835263ffffffff81511660408401528181015160608401526080613689613673604084015160a08488015260e0870190610ab9565b6060840151868203603f190160a0880152610ab9565b910151151560c08401526001600160a01b03909416910152565b613702926040926136b26135e1565b506136bc8361376a565b6136d36136c76124bc565b63ffffffff9095168552565b60208401528383015260608201525f6080820152815180938192631bb8518b60e31b8352309060048401613635565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610624575f91613741575090565b612551915060403d604011613763575b61375b8183610cc5565b810190613621565b503d613751565b63ffffffff16805f52600160205260405f2054908115613788575090565b63f6ff4fb760e01b5f5260045260245ffd5b61c34f198101919082116129d457565b919082039182116129d457565b3561255181610f7c565b6040906001600160401b0361255194931681528160208201520190610ab9565b939291926137f1600b5460ff1690565b9081613919575b5061390a57611020613821926040519485936304c98a8b60e51b60208601528760248601612aa9565b6138348161382e5a61379a565b30613ce8565b91901561384057505050565b63ffffffff7fd191660d5fb7fa40de3038f810fa899670f44a26d29f0609702b778de1c4e5f69160405161387f81611020602082019446903087612b0d565b5190206139056138f66138f06138ab61389789612583565b63ffffffff165f52600860205260405f2090565b976138c36020820135809a905f5260205260405f2090565b946138ea60408301966138d5886137b7565b6001600160401b03165f5260205260405f2090565b55612583565b926137b7565b946040519384931695836137c1565b0390a3565b6341c8302160e11b5f5260045ffd5b6001600160a01b03165f9081526009602052604081205460ff161591506137f8565b335f9081527f460e1c17541eb4600da639136d22ecdece50dfd5504d40fe2d419370e887d378602052604090205460ff161561397357565b63e2517d3f60e01b5f52336004527f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c60245260445ffd5b5f81815260036020908152604080832033845290915290205460ff16156139ce5750565b63e2517d3f60e01b5f523360045260245260445ffd5b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff16613a6e575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916600117905533916001600160a01b0316907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b5f546001600160a01b03163303613a8757565b63118cdaa760e01b5f523360045260245ffd5b7f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9163ffffffff6040921690815f52600160205280835f205582519182526020820152a1565b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff1615613a6e575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916905533916001600160a01b0316907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b906001600160801b03809116911601906001600160801b0382116129d457565b916001600160801b03613bc0948193948180613be5575b15613bdb57905b15613bd65762031c870181165b16026201adb00116613b68565b90627a12006001600160801b03831611611fc457565b613bb3565b5061c35090613ba6565b508281161515613b9f565b604051600360f01b602082015260028152612551602282610cc5565b91600361ffff613c1b856141fd565b16036129155760405160809290921b6fffffffffffffffffffffffffffffffff1916602083015260e01b6001600160e01b031916603082015260148152613c63603482610cc5565b600361ffff613c71846141fd565b1603613cdc57600161ffff613c8683516148c1565b16019161ffff83116129d457611020612551926004613caf956040519687956020870190612afb565b600160f81b815260f09190911b6001600160f01b0319166001820152600560f81b60038201520190612afb565b61ffff612921836141fd565b92915f9190829182613cfa60046124cb565b96613d086040519889610cc5565b60048852601f19613d1960046124cb565b013660208a013760208451940192f13d60048111613d3f575b8084525f602085013e9190565b506004613d32565b601f8211613d5457505050565b5f5260205f20906020601f840160051c83019310613d8c575b601f0160051c01905b818110613d81575050565b5f8155600101613d76565b9091508190613d6d565b91909182516001600160401b038111610c8a57613dbd81613db78454610c23565b84613d47565b6020601f8211600114613dfc578190613ded9394955f92613df1575b50508160011b915f199060031b1c19161790565b9055565b015190505f80613dd9565b601f19821690613e0f845f5260205f2090565b915f5b818110613e4957509583600195969710613e31575b505050811b019055565b01515f1960f88460031b161c191690555f8080613e27565b9192602060018192868b015181550194019201613e12565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310613e9357505050505090565b9091929394602080613ed6600193603f19868203018752606060408b5163ffffffff815116845261ffff8682015116868501520151918160408201520190610ab9565b97019301930191939290613e84565b5f5b8151811015613f705780613f0a6040613f0260019486612f69565b510151613fa7565b613f6a6040613f198386612f69565b51015163ffffffff613f2b8487612f69565b5151165f526002602052613f6560405f20613f556020613f4b878a612f69565b51015161ffff1690565b61ffff165f5260205260405f2090565b613d96565b01613ee7565b50613fa27fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6749160405191829182613e61565b0390a1565b600361ffff60028301511603613fba5750565b604051639a6d49cd60e01b815260206004820152908190612c4c906024830190610ab9565b63ffffffff815116156106295763ffffffff905116461490565b6040519061400682610c6f565b815f81525f6020820152604061401a6135e1565b910152565b906080828203126103ca5761405990604080519361403c85610c6f565b80518552602081015161404e81610f7c565b6020860152016135f9565b604082015290565b6140ca608094926140e69694614075613ff9565b50602061408286516146b4565b95019182518061414e575b506140978561376a565b92511515926140b36140a76124bc565b63ffffffff9097168752565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b845260048401613635565b03917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1908115610624575f91614125575090565b612551915060803d608011614147575b61413f8183610cc5565b81019061401f565b503d614135565b614157906146d1565b5f61408d565b91909161416a81516148c1565b604051600160f01b60208201525f602282015260f09190911b6001600160f01b0319166024820152600681526141a1602682610cc5565b915f925b82518410156141cd576141c56001916141be8686612f69565b5190614e7d565b9301926141a5565b92509290508163ffffffff6141e9602084015163ffffffff1690565b166141f357505090565b61255192506147d9565b600281511061420d576002015190565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606490fd5b90600361ffff614258846141fd565b1603613cdc57600161ffff61426d83516148c1565b16019161ffff83116129d457611020612551926004614296956040519687956020870190612afb565b600160f81b80825260f09290921b6001600160f01b031916600182015260038101919091520190612afb565b9080601f830112156103ca5781356142d981612b3b565b926142e76040519485610cc5565b81845260208085019260051b8201019283116103ca57602001905b82821061430f5750505090565b8135815260209182019101614302565b916060838303126103ca578235614335816103b9565b926020810135614344816103b9565b9260408201356001600160401b0381116103ca5761255192016142c2565b90612cd5602091949394604084526040840190612fb9565b3d156143a4573d9061438b826124cb565b916143996040519384610cc5565b82523d5f602084013e565b606090565b9080601f830112156103ca5781356143c081612b3b565b926143ce6040519485610cc5565b81845260208085019260051b8201019283116103ca57602001905b8282106143f65750505090565b602080918335614405816103b9565b8152019101906143e9565b906080828203126103ca578135614426816103b9565b9260208301356001600160401b0381116103ca57826144469185016143a9565b9260408101356001600160401b0381116103ca57836144669183016143a9565b9260608201356001600160401b0381116103ca5761255192016142c2565b61449391939293810190614410565b6001600160a01b039093165f8181526006602052604090209192916144b790612dd1565b916144d861195a6126298560018060a01b03165f52600560205260405f2090565b156144ea575050610d1e939450614ac2565b9150935f5b8451811015614669575f806145076131228487612f69565b6145146131228589612f69565b9061451f858a612f69565b51906001600160a01b03811615841461459657506040516340c10f1960e01b602082019081526001600160a01b039093166024820152604481019190915261456a8160648101611020565b5190828a5af161457861437a565b5015614588576001905b016144ef565b62ec6f7b60e31b5f5260045ffd5b916001600160a01b0381161584146145fe5750604051630852cd8d60e31b6020820190815260248201929092529091506145d38160448101611020565b5190828a5af16145e161437a565b50156145ef57600190614582565b631bc5aabf60e21b5f5260045ffd5b6040516323b872dd60e01b602082019081526001600160a01b039485166024830152939091166044820152606481019190915261463e8160848101611020565b5190828a5af161464c61437a565b501561465a57600190614582565b6312171d8360e31b5f5260045ffd5b50949392505050803b156103ca5760405163163b5cc360e31b815260048101929092525f908290602490829084905af18015610624576146a65750565b80610f0e5f610d1e93610cc5565b8034036146be5790565b6304fb820960e51b5f523460045260245ffd5b60405163393f876560e21b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690602081600481855afa908115610624575f916147ba575b506001600160a01b03169182156147ab576040516323b872dd60e01b60208281019182523360248401526001600160a01b03909416604483015260648201929092525f91906147728160848101611020565b519082855af115612578575f513d6147a25750803b155b6147905750565b635274afe760e01b5f5260045260245ffd5b60011415614789565b6329b99a9560e11b5f5260045ffd5b6147d3915060203d602011612786576127778183610cc5565b5f614720565b612551906027614835936148b260ff8251169163ffffffff60208201511690604081015115156001600160401b036060830151169061ffff6080840151169260a0600180821b0391015116936040519a8b9960208b0190612afb565b600160f81b8152600160f01b600182015260f897881b6001600160f81b031916600382015260e09190911b6001600160e01b031916600482015290151590951b600886015260c01b6001600160c01b031916600985015260f01b6001600160f01b031916601184015260601b6001600160601b0319166013830152565b0103601f198101835282610cc5565b61ffff81116148d15761ffff1690565b6306dfcc6560e41b5f52601060045260245260445ffd5b5f5b8351811015614974576001600160a01b0382166149078286612f69565b5190803b156103ca576040516323b872dd60e01b81523060048201526001600160a01b038616602482015260448101929092525f908290606490829084905af180156106245761495b575b506001016148ea565b806149675f8093610cc5565b8003126103ca575f614952565b50610d1e929150614f2b565b9061498a82612b3b565b6149976040519182610cc5565b82815280926149a8601f1991612b3b565b01905f5b8281106149b857505050565b8060606020809385010152016149ac565b6020818303126103ca578051906001600160401b0382116103ca57019080601f830112156103ca5781516149fc81612b3b565b92614a0a6040519485610cc5565b81845260208085019260051b820101918383116103ca5760208201905b838210614a3657505050505090565b81516001600160401b0381116103ca57602091614a58878480948801016124e6565b815201910190614a27565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310614a9557505050505090565b9091929394602080614ab3600193603f198682030187528951610ab9565b97019301930191939290614a86565b9291614ad6614ad182516132c3565b614980565b60045490945f91614aef906001600160a01b03166114aa565b6001600160a01b03821696908703614dc7576c3607fce1ac9e043a86675c5c2f945b5f5b8551811015614cff57614b296131228284612f69565b614b338288612f69565b5190614b56612dd1836110698960018060a01b03165f52600760205260405f2090565b6040516331a9108f60e11b8152600481018490526020818e81806024810103915afa908115610624575f91614ce1575b50306001600160a01b0390911603614cd25789906001600160a01b038116614c62575b506001600160a01b038216614bc4575b505050600101614b13565b60405163b18e2bbb60e01b60208201526001600160a01b03808416602483015290911660448201526064810183905264ffffffffff6084820152600160a482018190529297929392614c5a9291611e7b918691614c248160c48101611020565b614c2e828b612f69565b52614c39818a612f69565b506001600160a01b038a165f90815260076020526040902091019990611069565b905f88614bb9565b60405163b18e2bbb60e01b60208201526001600160a01b039182166024820152911660448201526064810183905264ffffffffff60848201525f60a48201529096600191614cb38160c48101611020565b614cbd8288612f69565b52614cc88187612f69565b500195885f614ba9565b6349e27cff60e01b5f5260045ffd5b614cf9915060203d8111612786576127778183610cc5565b5f614b86565b505094955050915050614d1181614980565b915f5b828110614d9d575050614d245750565b5f614d439160405180938192631592ca1b60e31b835260048301614a63565b0381837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1801561062457614d7f5750565b614d9a903d805f833e614d928183610cc5565b8101906149c9565b50565b80614daa60019284612f69565b51614db58287612f69565b52614dc08186612f69565b5001614d14565b8194614b11565b614ddd90600b95939492612afb565b600160f81b815260f093841b6001600160f01b03199081166001830152600160f01b60038301529190931b16600583015260e01b6001600160e01b03191660078201520190565b92614e3861255197969394601f9693612afb565b93151560f81b845260c01b6001600160c01b031916600184015260f01b6001600160f01b031916600983015260601b6001600160601b031916600b8201520190612afb565b9061255190611020614e91825161ffff1690565b91614ed960c0820195614ecb614eb0614eab895151613374565b6148c1565b602085015163ffffffff169060405197889460208601614dce565b03601f198101855284610cc5565b6040810151151594614ef560608301516001600160401b031690565b91614f1960a0614f0a608084015161ffff1690565b9201516001600160a01b031690565b91519260405197889660208801614e24565b9190614f378151614980565b600454614f4c906001600160a01b03166114aa565b6001600160a01b038516036150b3576c3607fce1ac9e043a86675c5c2f935b5f925f5b815181101561506757614f828183612f69565b519487614fa6612dd1886110698860018060a01b03165f52600760205260405f2090565b6001600160a01b0381161561505b5760405163b18e2bbb60e01b60208201526001600160a01b039182166024820152911660448201526064810187905264ffffffffff60848201525f60a4820152600192916150559161504591859161500f8160c48101611020565b615019868b612f69565b52615024858a612f69565b506001600160a01b0388165f90815260076020526040902091019890611069565b80546001600160a01b0319169055565b01614f6f565b50509450600190615055565b50505091925061507681614980565b915f5b828110615089575050614d245750565b8061509660019284612f69565b516150a18287612f69565b526150ac8186612f69565b5001615079565b83614f6b56fea2646970667358221220b6ee7d3d94ce99462617ed99493a6ec9a7f4dfb5fc14f459b5c15d181346632b64736f6c634300081c00332f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d460e1c17541eb4600da639136d22ecdece50dfd5504d40fe2d419370e887d3783617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b000000000000000000000000000000000000506aa8bc5da44f9b3329b8c6f7e000000000000000000000000058a766b3210cee94ca150f767d842eb87a8d7ae800000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000447e69651d841bd8d104bed4930000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a02
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c806301a0de05146103b457806301ffc9a7146103af57806304bd49a5146103aa578063066d5910146103a5578063108dcbdd146103a057806313137d651461039b57806317442b70146103965780631d56672114610391578063248a9ca31461038c5780632d69fc48146103875780632f2ff15d146103825780633400288b1461037d5780633530511a1461037857806336568abe1461037357806336b1dd211461036e57806337cb6736146103695780634202fce11461036457806345248a371461035f578063461572f91461035a57806347c1b317146103555780635535d461146103505780635e280f111461034b57806360eddbe4146103465780636a4d8672146103415780636eaa69041461033c5780636fe87dba14610337578063715018a6146103325780637d25a05e1461032d57806382413eac14610328578063864c651514610323578063881ae9f81461031e5780638da5cb5b1461031957806391d1485414610314578063993151601461030f578063a0238f3e1461030a578063a217fddf14610305578063a34ac81b14610300578063ade7142d146102fb578063b33b522d146102f6578063b98bd070146102f1578063bb0b6a53146102ec578063bc70b354146102e7578063c9df8167146102e2578063ca5eb5e1146102dd578063cfac96ce146102d8578063d1e1d0cc146102d3578063d547741f146102ce578063da383b97146102c9578063e052778a146102c4578063e60c287c146102bf578063eba1cf08146102ba578063f0a9e481146102b5578063f1748835146102b0578063f1c418ee146102ab578063f2fde38b146102a6578063fccc4331146102a1578063fe084c8f1461029c5763ff7bd03d14610297575f80fd5b61243b565b612237565b61220f565b612186565b612164565b612121565b6120da565b61207b565b61201c565b611fe2565b611d42565b611d01565b611c68565b611bdc565b611b3f565b611870565b61181c565b6117e3565b6116de565b611671565b6115dc565b611574565b61155a565b611504565b611390565b61133e565b611317565b6112b5565b611243565b6111e5565b6111bf565b611168565b611124565b610f8d565b610f38565b610e20565b610ddc565b610d86565b610ba3565b610b7d565b610b0e565b610add565b610a1d565b6109d9565b610991565b610936565b610905565b6108b1565b61088a565b610857565b61082d565b61080c565b61070e565b610681565b610641565b6104e4565b61041c565b6103ce565b6001600160a01b038116036103ca57565b5f80fd5b346103ca5760403660031901126103ca576004356103eb816103b9565b6001600160a01b039081165f9081526007602090815260408083206024358452825291829020549151919092168152f35b346103ca5760203660031901126103ca5760043563ffffffff60e01b81168091036103ca57602090637965db0b60e01b8114908115610461575b506040519015158152f35b6301ffc9a760e01b1490505f610456565b9181601f840112156103ca578235916001600160401b0383116103ca576020808501948460051b0101116103ca57565b606435906001600160801b03821682036103ca57565b60a435906001600160801b03821682036103ca57565b608435906001600160801b03821682036103ca57565b346103ca5760803660031901126103ca57600435610501816103b9565b6024356001600160401b0381116103ca57610520903690600401610472565b91906044356001600160401b0381116103ca57610541903690600401610472565b9361054a6104a2565b6001600160a01b0385165f90815260056020526040902061056d905b5460601c90565b916001600160a01b038316156106295761059181866105c6995f976105ab9761338f565b946105a560045463ffffffff9060a01c1690565b966129d9565b60405180958192632f1c2cd560e21b83528660048401612554565b0381305afa918215610624576105e3935f93610600575b506136a3565b8051602091820151604080519283529282015290819081015b0390f35b61061d9193503d805f833e6106158183610cc5565b81019061252c565b915f6105dd565b612578565b622dc1c960e71b5f5260045ffd5b5f9103126103ca57565b346103ca575f3660031901126103ca57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000007668168152f35b346103ca5760203660031901126103ca5760043561069e816103b9565b60018060a01b03165f526005602052602060405f205460601c604051908152f35b60609060031901126103ca57600490565b60609060631901126103ca57606490565b9181601f840112156103ca578235916001600160401b0383116103ca57602083818601950101116103ca57565b60e03660031901126103ca57610723366106bf565b6064356084356001600160401b0381116103ca576107459036906004016106e1565b9060a43592610753846103b9565b60c4356001600160401b0381116103ca576107729036906004016106e1565b5050337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316036107f9578435946107b0866108f7565b6107b98661376a565b9560208201358097036107d357506107d195506137e1565b005b63ffffffff816107e389936108f7565b63309afaf360e21b5f521660045260245260445ffd5b6391ac5e4f60e01b5f523360045260245ffd5b346103ca575f3660031901126103ca57604080516001815260026020820152f35b346103ca5760203660031901126103ca576004355f52600a602052602060405f2054604051908152f35b346103ca5760203660031901126103ca5760206108826004355f526003602052600160405f20015490565b604051908152f35b346103ca575f3660031901126103ca5760206040516c3607fce1ac9e043a86675c5c2f8152f35b346103ca5760403660031901126103ca576107d16024356004356108d4826103b9565b6108f26108ed825f526003602052600160405f20015490565b6139aa565b6139e4565b63ffffffff8116036103ca57565b346103ca5760403660031901126103ca576107d1600435610925816108f7565b60243590610931613a74565b613a9a565b346103ca5760603660031901126103ca57600435610953816103b9565b60443560243567ffffffffffffffff19821682036103ca5761097492612607565b604080516001600160a01b03939093168352901515602083015290f35b346103ca5760403660031901126103ca576004356024356109b1816103b9565b336001600160a01b038216036109ca576107d191613ae0565b63334bd91960e11b5f5260045ffd5b346103ca575f3660031901126103ca576040517f0000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a026001600160a01b03168152602090f35b346103ca5760203660031901126103ca57600435610a3a816103b9565b60018060a01b03165f526009602052602060ff60405f2054166040519015158152f35b60806003198201126103ca57600435610a75816108f7565b91602435610a82816103b9565b91604435906001600160401b0382116103ca57610aa191600401610472565b90916064356001600160801b03811681036103ca5790565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b346103ca576105fc610afa610af136610a5d565b93929092612889565b604051918291602083526020830190610ab9565b346103ca57610b1c36610a5d565b6001600160a01b038085165f9081526005602052604090209195949391610b4290610566565b1615610629576105c6945f926105ab9260405195610b7787610b6985858560208501612958565b03601f198101895288610cc5565b87612889565b346103ca575f3660031901126103ca57602063ffffffff60045460a01c16604051908152f35b346103ca5760603660031901126103ca57600435610bc0816103b9565b6024356001600160401b0381116103ca57610bdf903690600401610472565b909190604435906001600160801b03821682036103ca576105fc93610afa936129d9565b6024359061ffff821682036103ca57565b359061ffff821682036103ca57565b90600182811c92168015610c51575b6020831014610c3d57565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610c32565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b03821117610c8a57604052565b610c5b565b60e081019081106001600160401b03821117610c8a57604052565b604081019081106001600160401b03821117610c8a57604052565b90601f801991011681019081106001600160401b03821117610c8a57604052565b9060405191825f825492610cf984610c23565b8084529360018116908115610d645750600114610d20575b50610d1e92500383610cc5565b565b90505f9291925260205f20905f915b818310610d48575050906020610d1e928201015f610d11565b6020919350806001915483858901015201910190918492610d2f565b905060209250610d1e94915060ff191682840152151560051b8201015f610d11565b346103ca5760403660031901126103ca576105fc610afa610dd7600435610dac816108f7565b63ffffffff610db9610c03565b91165f52600260205260405f209061ffff165f5260205260405f2090565b610ce6565b346103ca575f3660031901126103ca576040517f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03168152602090f35b346103ca5760203660031901126103ca57600435610e3d816103b9565b610e45613a74565b60014603610f29576004546001600160a01b0316610f1a57600480546001600160a01b0319166001600160a01b0383161790556c3607fce1ac9e043a86675c5c2f3b156103ca5760405163a22cb46560e01b81526001600160a01b0382166004820152600160248201525f81604481836c3607fce1ac9e043a86675c5c2f5af1801561062457610f00575b506001600160a01b03167fb835fe32fb60b329ea744c781d0f1f6c73e746d5896560940444554cc0c275b55f80a2005b80610f0e5f610f1493610cc5565b80610637565b5f610ed0565b634dad647560e11b5f5260045ffd5b63057f3fa760e51b5f5260045ffd5b346103ca575f3660031901126103ca576040517f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03168152602090f35b6001600160401b038116036103ca57565b346103ca576101003660031901126103ca57600435610fab816108f7565b60243590604435610fbb81610f7c565b610fc4366106d0565b9160c43560e4356001600160401b0381116103ca57610fe79036906004016106e1565b909463ffffffff84169563fffff9be87116111155761102e92611020916040519586946304c98a8b60e51b602087015260248601612aa9565b03601f198101835282610cc5565b60405160208101906110468161102046863087612b0d565b51902061108c84611076886110698763ffffffff165f52600860205260405f2090565b905f5260205260405f2090565b906001600160401b03165f5260205260405f2090565b5403611106575f6110b684611076886110696110be9763ffffffff165f52600860205260405f2090565b555a30613ce8565b90156110fe57506040516001600160401b039190911681527f49a5bb7337668613a742dc30346f29d11f0b4d4a2c0745a08afccc9bb6cea3d090602090a3005b805190602001fd5b63a84ab60d60e01b5f5260045ffd5b634d30e69360e11b5f5260045ffd5b346103ca575f3660031901126103ca5760206040516001600160401b03197f502693d518cccccc945699ac6b0be7c02aef951c921558ec0000000000000000168152f35b346103ca575f3660031901126103ca57611180613a74565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103ca5760403660031901126103ca576111db6004356108f7565b60206040515f8152f35b346103ca5760a03660031901126103ca576111ff366106bf565b506064356001600160401b0381116103ca5761121f9036906004016106e1565b5050602060843561122f816103b9565b6040516001600160a01b0390911630148152f35b346103ca5760403660031901126103ca576107d1600435611263816103b9565b60243590611270826108f7565b611278613a74565b60018060a01b03165f52600560205260405f209063ffffffff60401b82549160401b169063ffffffff60401b1916179055565b801515036103ca57565b346103ca5760203660031901126103ca577f57f2a528edf864f533774c287d06a5278e1a4447ed97923b7bbc251fcbd54f6f60206004356112f5816112ab565b6112fd613a74565b151560ff19600b541660ff821617600b55604051908152a1005b346103ca575f3660031901126103ca575f546040516001600160a01b039091168152602090f35b346103ca5760403660031901126103ca57602060ff611384602435600435611365826103b9565b5f526003845260405f209060018060a01b03165f5260205260405f2090565b54166040519015158152f35b346103ca5760a03660031901126103ca576113aa366106bf565b6064356084356001600160401b0381116103ca576113cc9036906004016106e1565b90923033036114f55763ffffffff63fffff9be91356113ea816108f7565b16111561142d57610708611410611409845f52600a60205260405f2090565b54426137aa565b1161141e576107d192614484565b631a86ecf960e01b5f5260045ffd5b8261143b939250019061431f565b6001600160a01b039283165f8181526005602052604090209093919290911690546114668160601c90565b906001600160a01b038216156106295763ffffffff16460361148c57506107d1926148e8565b5f93508392908390611020906114d5906114b6906001600160a01b03165b6001600160a01b031690565b946040519283916020830196639277283360e01b885260248401614362565b51925af16114e161437a565b506107d157635f0ad7b760e11b5f5260045ffd5b63139f696160e31b5f5260045ffd5b346103ca5760203660031901126103ca57602061ffff61155163ffffffff60043561152e816108f7565b1663ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b16604051908152f35b346103ca575f3660031901126103ca5760206040515f8152f35b346103ca5760203660031901126103ca57600435611591816103b9565b60018060a01b03165f526005602052608060405f20546040519063ffffffff8116825263ffffffff8160201c16602083015263ffffffff8160401c16604083015260601c6060820152f35b346103ca5760403660031901126103ca577fc40a8c1d6db18d083249778a76a84a78429c4fe53001aba75f470c597afaee27604060043561161c816108f7565b61ffff611627610c03565b61162f613a74565b16600c602052631fffffff8260031c165f52825f2060e08360051b168154908382821c1863ffffffff16901b18905563ffffffff8351921682526020820152a1005b346103ca5760603660031901126103ca576116d2600435611691816108f7565b60243563ffffffff604435926116a684610f7c565b165f52600860205260405f20905f5260205260405f20906001600160401b03165f5260205260405f2090565b54604051908152602090f35b346103ca5760203660031901126103ca576004356001600160401b0381116103ca5761170e903690600401610472565b90611717613a74565b61172082612b3b565b9061172e6040519283610cc5565b828252602082019260051b8101903682116103ca5780935b828510611756576107d184613ee5565b84356001600160401b0381116103ca578201906060823603126103ca576040519161178083610c6f565b803561178b816108f7565b835261179960208201610c14565b60208401526040810135906001600160401b0382116103ca57019036601f830112156103ca576020926117d3849336908581359101612b52565b6040820152815201940193611746565b346103ca5760203660031901126103ca5763ffffffff600435611805816108f7565b165f526001602052602060405f2054604051908152f35b346103ca5760603660031901126103ca57600435611839816108f7565b611841610c03565b604435906001600160401b0382116103ca576105fc92611868610afa9336906004016106e1565b929091612bea565b60c03660031901126103ca57600435611888816108f7565b60243590611895826103b9565b6044356001600160401b0381116103ca576118b4903690600401610472565b606492919235906118c4826103b9565b608435916118d1836103b9565b6118d96104b8565b906001600160a01b03811615611b305763ffffffff85169463ffffffff7f00000000000000000000000000000000000000000000000000000000000076681686148015611b23575b611115578315611b14576001600160a01b0388165f9081526005602052604090209261195f61195a611954865460601c90565b9561258d565b613fdf565b15611ae357889291906001600160a01b0385165f5b878110611a6f575050905f6119b56119d0935b888c604051986119af8a6119a185858d8660208601612980565b03601f1981018c528b610cc5565b86612889565b60405180948192632f1c2cd560e21b83528560048401612554565b0381305afa968715610624577f6a0cf129b799c36943cf19ef7755eafb0b597737ba2f970045385de48107886a97611a4e95611a30945f92611a53575b50611a16612480565b3481525f60208201526001600160a01b0390931693614061565b506040516001600160a01b0393841698909316969293849384612cbc565b0390a4005b611a689192503d805f833e6106158183610cc5565b905f611a0d565b909192939450611a8081888c612ca7565b3590823b156103ca576040516323b872dd60e01b815233600482015230602482015260448101929092525f8260648183875af191821561062457600192611acf575b5001908a94939291611974565b80610f0e5f611add93610cc5565b5f611ac2565b9091906001600160a01b0384163303611b055788925f6119b56119d093611987565b6348f5c3ed60e01b5f5260045ffd5b630f59b9ff60e01b5f5260045ffd5b5063fffff9be8611611921565b63d721852160e01b5f5260045ffd5b346103ca575f60203660031901126103ca57600435611b5d816103b9565b611b65613a74565b7f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031690813b156103ca5760405163ca5eb5e160e01b81526001600160a01b039091166004820152905f908290602490829084905af1801561062457611bd0575080f35b6107d191505f90610cc5565b346103ca5760403660031901126103ca577f69bdfca1ae414a7233840909f9c10a21560d38e0ed4fb50ff50b7b4c29ad96fe600435611c1a816103b9565b60243590611c27826112ab565b611c2f613a74565b6001600160a01b03165f81815260096020908152604091829020805460ff191660ff9515159586161790558151928352820192909252a1005b346103ca5760203660031901126103ca57600435611c85816108f7565b611c8d613a74565b63ffffffff81169063fffff9be821115611cf2576004805463ffffffff60a01b191660a09290921b63ffffffff60a01b169190911790556040519081527fd22acca42bfd0ebef8a1ca8347653f46f782b92b553ba57e0f2294426dfe26ac90602090a1005b633df6e48d60e21b5f5260045ffd5b346103ca5760403660031901126103ca576107d1602435600435611d24826103b9565b611d3d6108ed825f526003602052600160405f20015490565b613ae0565b346103ca5760a03660031901126103ca57600435611d5f816103b9565b602435611d6b816108f7565b60443591611d78836103b9565b60643590611d85826108f7565b60843592611d92846108f7565b611d9a61393b565b63ffffffff8116928315610f295763ffffffff8116958615611115576001600160a01b038116958615611fd3576001600160a01b038516958615611fd357627a120063ffffffff831611611fc4574603611f885763ffffffff7f000000000000000000000000000000000000000000000000000000000000766816880361111557868603611f79575b6001600160a01b0382165f908152600560205260409020611e47906114aa90610566565b611f6a5784611ecb611edb92611ebe611ef496611e9a87611e7b611f449c60018060a01b03165f52600660205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611eb1611ea561248f565b63ffffffff909a168a52565b63ffffffff166020890152565b63ffffffff166040870152565b6001600160a01b03166060850152565b6001600160a01b03165f90815260056020526040902090565b8151602080840151604080860151606096870151911b63ffffffff60401b1663ffffffff9094169190921b67ffffffff000000001617919091176001600160601b03199190931b16919091179055565b7f328b68290d8d3a315d25b2476661d7c921ee87029fc767a4916b407e2ee31ede5f80a4005b6341ab882d60e01b5f5260045ffd5b630232505d60e61b5f5260045ffd5b63ffffffff7f0000000000000000000000000000000000000000000000000000000000007668168803611e2357634d30e69360e11b5f5260045ffd5b634a11e78360e11b5f5260045ffd5b63d92e233d60e01b5f5260045ffd5b346103ca575f3660031901126103ca5760206040517f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c8152f35b346103ca5760403660031901126103ca576004356001600160401b0381116103ca5761204c9036906004016106e1565b602435906001600160401b0382116103ca576105fc92612073610afa9336906004016106e1565b929091612d44565b346103ca5760403660031901126103ca576004356001600160401b0381116103ca576120ab9036906004016106e1565b602435906001600160401b0382116103ca576105fc926120d2610afa933690600401610472565b929091613030565b346103ca5760403660031901126103ca576107d16004356120fa816108f7565b602435612106816112ab565b61210e613a74565b1561211a573090613a9a565b5f90613a9a565b346103ca5760203660031901126103ca5760043561213e816103b9565b60018060a01b03165f526006602052602060018060a01b0360405f205416604051908152f35b346103ca575f3660031901126103ca57602060ff600b54166040519015158152f35b346103ca5760203660031901126103ca576004356121a3816103b9565b6121ab613a74565b6001600160a01b031680156121fc575f80546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b5f525f60045260245ffd5b346103ca575f3660031901126103ca576004546040516001600160a01b039091168152602090f35b60a03660031901126103ca5760043561224f816103b9565b6024356001600160401b0381116103ca5761226e903690600401610472565b6044356001600160401b0381116103ca5761228d903690600401610472565b936064359461229b866103b9565b6122a36104ce565b9184158015612433575b611b14576001600160a01b0381165f908152600560205260409020805460601c95908615610629576122e461195a6122e89261258d565b1590565b806123d8575b6123c9576122ff818885888661338f565b9061233e5f61232361231a60045463ffffffff9060a01c1690565b97848c886129d9565b60405180938192632f1c2cd560e21b83528a60048401612554565b0381305afa958615610624576105fc9a7fed0c24299d2da4e3728deedbf20de24c4ff0e754c89f20b3d2532fe63b43b531976123b695612387945f92611a535750611a16612480565b51974261239c8a5f52600a60205260405f2090565b556040516001600160a01b03909416969394859485613267565b0390a36040519081529081906020820190565b634a91ec5f60e01b5f5260045ffd5b50604051637347ebb960e01b81526020816004818a5afa908115610624575f91612404575b50156122ee565b612426915060203d60201161242c575b61241e8183610cc5565b8101906125dd565b5f6123fd565b503d612414565b5081156122ad565b346103ca5760603660031901126103ca576020612457366106bf565b63ffffffff8135612467816108f7565b165f52600182528160405f205491013560405191148152f35b60405190610d1e604083610cc5565b60405190610d1e608083610cc5565b60405190610d1e60e083610cc5565b60405190610d1e60c083610cc5565b60405190610d1e60a083610cc5565b6001600160401b038111610c8a57601f01601f191660200190565b81601f820112156103ca578051906124fd826124cb565b9261250b6040519485610cc5565b828452602083830101116103ca57815f9260208093018386015e8301015290565b906020828203126103ca5781516001600160401b0381116103ca5761255192016124e6565b90565b60609063ffffffff6125519493168152600160208201528160408201520190610ab9565b6040513d5f823e3d90fd5b35612551816108f7565b90604051608081018181106001600160401b03821117610c8a57604052606081935463ffffffff8116835263ffffffff8160201c16602084015263ffffffff8160401c166040840152811c910152565b908160209103126103ca5751612551816112ab565b908160209103126103ca5751612551816103b9565b6001600160a01b03165f90815260056020526040902090919061262e9061258d565b61258d565b9163ffffffff612645602085015163ffffffff1690565b161561287f5761266d606061265e855163ffffffff1690565b9401516001600160a01b031690565b9263ffffffff1646036127ae576040516331a9108f60e11b815260048101829052906020826024816001600160a01b0388165afa5f928161278d575b506126b857505050505f905f90565b6001600160a01b03821630036126d357505050503090600190565b602091935b604051637f63c3dd60e01b81526001600160a01b039091166004820152602481019190915267ffffffffffffffff19909216604483015281806064810103817f0000000000000000000000000000000000007129af73c46c9f01a3fb4ff61a026001600160a01b03165afa5f918161275c575b506127565750905f90565b915f9150565b61277f91925060203d602011612786575b6127778183610cc5565b8101906125f2565b905f61274b565b503d61276d565b6127a791935060203d602011612786576127778183610cc5565b915f6126a9565b6001600160a01b038316908115801561282e575b156127d257505050505f90600190565b6040516331a9108f60e11b8152600481018290526020928390829060249082905afa5f918161280f575b5061280957505f936126d8565b936126d8565b612827919250843d8611612786576127778183610cc5565b905f6127fc565b50604051635a2d1e0760e11b815260048101829052602081602481865afa908115610624575f91612860575b506127c2565b612879915060203d60201161242c5761241e8183610cc5565b5f61285a565b5050505f90600190565b929150926128c79360018060a01b03165f52600560205263ffffffff60406128b2815f2061258d565b94828060208801511691161494015116613b88565b906128d0613bf0565b91600361ffff6128df856141fd565b1603612915576125519192604051916001600160801b03199060801b16602083015260108252612910603083610cc5565b614249565b61ffff612921846141fd565b633a51740d60e01b5f521660045260245ffd5b81835290916001600160fb1b0383116103ca5760209260051b809284830137010190565b6001600160a01b0390911681525f602082015260606040820181905261255193910191612934565b6001600160a01b0391821681529116602082015260606040820181905261255193910191612934565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff1660e0019063ffffffff82116129d457565b6129a9565b612a309293915060018060a01b03165f5260056020526001600160801b0363ffffffff612a0860405f2061258d565b51164614805f14612a7f576201adb0905b15612a7657816206390e5b81871602160116613b68565b90627a12006001600160801b03831611611fc45763ffffffff166060029063ffffffff82169182036129d457612a68612551926129bd565b90612a71613bf0565b613c0c565b8161c350612a24565b6201b7d890612a19565b908060209392818452848401375f828201840152601f01601f1916010190565b61255194926001600160401b03604060a09463ffffffff8135612acb816108f7565b168552602081013560208601520135612ae381610f7c565b16604083015260608201528160808201520191612a89565b805191908290602001825e015f815290565b91601460209493612b34936bffffffffffffffffffffffff199060601b1681520190612afb565b9081520190565b6001600160401b038111610c8a5760051b60200190565b929192612b5e826124cb565b91612b6c6040519384610cc5565b8294818452818301116103ca578281602093845f960137010152565b90606e116103ca57602e0190604090565b906054116103ca5760400190601490565b612bc49392610d1e92816040519687946020860190612afb565b918237015f815203601f198101845283610cc5565b916020612551938181520191612a89565b612c189163ffffffff610dd79296949596165f52600260205260405f209061ffff165f5260205260405f2090565b805115612c85578315612c7f576002841015612c50575050612c4c604051928392639a6d49cd60e01b845260048401612bd9565b0390fd5b9092612c65612c60368386612b52565b613fa7565b806002116103ca5760026125519301906001190191612baa565b92509050565b509190612551913691612b52565b634e487b7160e01b5f52603260045260245ffd5b9190811015612cb75760051b0190565b612c93565b91602091612cd591959495604085526040850191612934565b6001600160a01b03909416910152565b91908260409103126103ca5760208235612cfe816103b9565b92013590565b91908260409103126103ca5760208235612d1d816103b9565b920135612551816112ab565b60405190612d38602083610cc5565b5f808352366020840137565b612d57612d7492612d5f92959495612b88565b810190612ce5565b936001600160a01b0390911692810190612d04565b612e8e578183612d9a6126296125519560018060a01b03165f52600560205260405f2090565b91612da483613fdf565b15612e10576001600160a01b03165f9081526007602052604090206110209250612dde91612dd191611069565b546001600160a01b031690565b935b604080516001600160a01b0396871660208201529590931692850192909252606084019190915282906080820190565b505060600151612e2a906114aa906001600160a01b031681565b6040516331a9108f60e11b81526004810185905290602090829060249082905afa5f9181612e6d575b50612e6357506110205f93612de0565b6110209093612de0565b612e8791925060203d602011612786576127778183610cc5565b905f612e53565b505050612551612d29565b356001600160601b0319811692919060148210612eb4575050565b6001600160601b031960149290920360031b82901b16169150565b90612ed982612b3b565b612ee66040519182610cc5565b8281528092612ef7601f1991612b3b565b0190602036910137565b9190811015612cb75760051b81013590601e19813603018212156103ca5701908135916001600160401b0383116103ca5760200182360381136103ca579190565b908160609103126103ca578035612f58816103b9565b9160406020830135612cfe816103b9565b8051821015612cb75760209160051b010190565b90602080835192838152019201905f5b818110612f9a5750505090565b82516001600160a01b0316845260209384019390920191600101612f8d565b90602080835192838152019201905f5b818110612fd65750505090565b8251845260209384019390920191600101612fc9565b9261301461255195936130229360018060a01b03168652608060208701526080860190612f7d565b908482036040860152612f7d565b916060818403910152612fb9565b61305b612629611edb61305561304f613069966060969a99989a612b99565b90612e99565b60601c90565b01516001600160a01b031690565b61307282612ecf565b9161307c81612ecf565b9461308682612ecf565b915f915f5b82811061316f57505050815181106130b757506110209061255193949560405195869460208601612fec565b92906130c284612ecf565b936130cc81612ecf565b916130d682612ecf565b935f5b8381106130ff575050505061255193949550906110209160405195869460208601612fec565b80613153613149613122838e6131448e6131358461312f61312260019c8e612f69565b516001600160a01b031690565b92612f69565b6001600160a01b039091169052565b612f69565b6131358389612f69565b61315d8185612f69565b516131688289612f69565b52016130d9565b61317a818484612f01565b90501561325f576131d4816131c18b613135838a6131b16131a761319f848d8d612f01565b810190612f42565b9291989093612f69565b526001600160a01b031692612f69565b6001600160a01b0316613135838a612f69565b6131e16131228289612f69565b6131f16114aa613122848d612f69565b6001600160a01b039091160361320c575b6001905b0161308b565b926001809161321b8688612f69565b516132268289612f69565b52613241613237613122888c612f69565b613135838c612f69565b6132568b6131358361312f6131228b85612f69565b01939050613202565b600190613206565b949391949290928560408201604083525260608101935f965b80881061329c5750506125519495506020818503910152612934565b909460208060019263ffffffff89356132b4816108f7565b16815201960197019690613280565b908160011b91808304600214901517156129d457565b818102929181159184041417156129d457565b906132f682612b3b565b6133036040519182610cc5565b8281528092613314601f1991612b3b565b01905f5b82811061332457505050565b60209060405161333381610c8f565b5f81525f838201525f60408201525f60608201525f60808201525f60a0820152606060c082015282828501015201613318565b90600182018092116129d457565b90602382018092116129d457565b919082018092116129d457565b9291926133a461339f85876132d9565b6132ec565b935f6001600160401b034216967f502693d518cccccc945699ac6b0be7c02aef951c921558ec0000000000000000915b81811061344a575050505050505090612551916134396133f26124ad565b600281529263ffffffff7f00000000000000000000000000000000000000000000000000000000000076681660208501525f60408501526001600160401b03166060840152565b5f60808301523060a083015261415d565b5f5b84811061345c57506001016133d4565b6134a061347e61347561347084898c612ca7565b612583565b63ffffffff1690565b63ffffffff908060031c5f52600c60205260e060405f20549160051b161c1690565b63ffffffff8116156111155784846134b785613366565b6134c182866132d9565b6134ca91613382565b61ffff1692888c878d886134df818684612ca7565b6134e890612583565b946134f292612ca7565b6134fb90612583565b6135049061376a565b6001600160a01b03169461351792612ca7565b604051631a98288d60e11b60208201526001600160a01b038d1660248201529035604482015267ffffffffffffffff19949094166064808601919091528452613561608485610cc5565b61356961249e565b61ffff909516855263ffffffff1660208501525f60408501526001600160401b038e16606085015261ffff1660808401526001600160a01b031660a083015260c0820152816135b887856132d9565b906135c291613382565b906135cd828c612f69565b526135d8908a612f69565b5060010161344c565b604051906135ee82610caa565b5f6020838281520152565b91908260409103126103ca5760405161361181610caa565b6020808294805184520151910152565b906040828203126103ca57612551916135f9565b906020909392936040835263ffffffff81511660408401528181015160608401526080613689613673604084015160a08488015260e0870190610ab9565b6060840151868203603f190160a0880152610ab9565b910151151560c08401526001600160a01b03909416910152565b613702926040926136b26135e1565b506136bc8361376a565b6136d36136c76124bc565b63ffffffff9095168552565b60208401528383015260608201525f6080820152815180938192631bb8518b60e31b8352309060048401613635565b03817f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03165afa908115610624575f91613741575090565b612551915060403d604011613763575b61375b8183610cc5565b810190613621565b503d613751565b63ffffffff16805f52600160205260405f2054908115613788575090565b63f6ff4fb760e01b5f5260045260245ffd5b61c34f198101919082116129d457565b919082039182116129d457565b3561255181610f7c565b6040906001600160401b0361255194931681528160208201520190610ab9565b939291926137f1600b5460ff1690565b9081613919575b5061390a57611020613821926040519485936304c98a8b60e51b60208601528760248601612aa9565b6138348161382e5a61379a565b30613ce8565b91901561384057505050565b63ffffffff7fd191660d5fb7fa40de3038f810fa899670f44a26d29f0609702b778de1c4e5f69160405161387f81611020602082019446903087612b0d565b5190206139056138f66138f06138ab61389789612583565b63ffffffff165f52600860205260405f2090565b976138c36020820135809a905f5260205260405f2090565b946138ea60408301966138d5886137b7565b6001600160401b03165f5260205260405f2090565b55612583565b926137b7565b946040519384931695836137c1565b0390a3565b6341c8302160e11b5f5260045ffd5b6001600160a01b03165f9081526009602052604081205460ff161591506137f8565b335f9081527f460e1c17541eb4600da639136d22ecdece50dfd5504d40fe2d419370e887d378602052604090205460ff161561397357565b63e2517d3f60e01b5f52336004527f8970ff45bc1804c7a79662cce9df9b0403588be8e486c6f5a410a2814caa892c60245260445ffd5b5f81815260036020908152604080832033845290915290205460ff16156139ce5750565b63e2517d3f60e01b5f523360045260245260445ffd5b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff16613a6e575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916600117905533916001600160a01b0316907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d5f80a4600190565b50505f90565b5f546001600160a01b03163303613a8757565b63118cdaa760e01b5f523360045260245ffd5b7f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b9163ffffffff6040921690815f52600160205280835f205582519182526020820152a1565b5f8181526003602090815260408083206001600160a01b038616845290915290205460ff1615613a6e575f8181526003602090815260408083206001600160a01b03861684529091529020805460ff1916905533916001600160a01b0316907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b5f80a4600190565b906001600160801b03809116911601906001600160801b0382116129d457565b916001600160801b03613bc0948193948180613be5575b15613bdb57905b15613bd65762031c870181165b16026201adb00116613b68565b90627a12006001600160801b03831611611fc457565b613bb3565b5061c35090613ba6565b508281161515613b9f565b604051600360f01b602082015260028152612551602282610cc5565b91600361ffff613c1b856141fd565b16036129155760405160809290921b6fffffffffffffffffffffffffffffffff1916602083015260e01b6001600160e01b031916603082015260148152613c63603482610cc5565b600361ffff613c71846141fd565b1603613cdc57600161ffff613c8683516148c1565b16019161ffff83116129d457611020612551926004613caf956040519687956020870190612afb565b600160f81b815260f09190911b6001600160f01b0319166001820152600560f81b60038201520190612afb565b61ffff612921836141fd565b92915f9190829182613cfa60046124cb565b96613d086040519889610cc5565b60048852601f19613d1960046124cb565b013660208a013760208451940192f13d60048111613d3f575b8084525f602085013e9190565b506004613d32565b601f8211613d5457505050565b5f5260205f20906020601f840160051c83019310613d8c575b601f0160051c01905b818110613d81575050565b5f8155600101613d76565b9091508190613d6d565b91909182516001600160401b038111610c8a57613dbd81613db78454610c23565b84613d47565b6020601f8211600114613dfc578190613ded9394955f92613df1575b50508160011b915f199060031b1c19161790565b9055565b015190505f80613dd9565b601f19821690613e0f845f5260205f2090565b915f5b818110613e4957509583600195969710613e31575b505050811b019055565b01515f1960f88460031b161c191690555f8080613e27565b9192602060018192868b015181550194019201613e12565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310613e9357505050505090565b9091929394602080613ed6600193603f19868203018752606060408b5163ffffffff815116845261ffff8682015116868501520151918160408201520190610ab9565b97019301930191939290613e84565b5f5b8151811015613f705780613f0a6040613f0260019486612f69565b510151613fa7565b613f6a6040613f198386612f69565b51015163ffffffff613f2b8487612f69565b5151165f526002602052613f6560405f20613f556020613f4b878a612f69565b51015161ffff1690565b61ffff165f5260205260405f2090565b613d96565b01613ee7565b50613fa27fbe4864a8e820971c0247f5992e2da559595f7bf076a21cb5928d443d2a13b6749160405191829182613e61565b0390a1565b600361ffff60028301511603613fba5750565b604051639a6d49cd60e01b815260206004820152908190612c4c906024830190610ab9565b63ffffffff815116156106295763ffffffff905116461490565b6040519061400682610c6f565b815f81525f6020820152604061401a6135e1565b910152565b906080828203126103ca5761405990604080519361403c85610c6f565b80518552602081015161404e81610f7c565b6020860152016135f9565b604082015290565b6140ca608094926140e69694614075613ff9565b50602061408286516146b4565b95019182518061414e575b506140978561376a565b92511515926140b36140a76124bc565b63ffffffff9097168752565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b845260048401613635565b03917f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03165af1908115610624575f91614125575090565b612551915060803d608011614147575b61413f8183610cc5565b81019061401f565b503d614135565b614157906146d1565b5f61408d565b91909161416a81516148c1565b604051600160f01b60208201525f602282015260f09190911b6001600160f01b0319166024820152600681526141a1602682610cc5565b915f925b82518410156141cd576141c56001916141be8686612f69565b5190614e7d565b9301926141a5565b92509290508163ffffffff6141e9602084015163ffffffff1690565b166141f357505090565b61255192506147d9565b600281511061420d576002015190565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606490fd5b90600361ffff614258846141fd565b1603613cdc57600161ffff61426d83516148c1565b16019161ffff83116129d457611020612551926004614296956040519687956020870190612afb565b600160f81b80825260f09290921b6001600160f01b031916600182015260038101919091520190612afb565b9080601f830112156103ca5781356142d981612b3b565b926142e76040519485610cc5565b81845260208085019260051b8201019283116103ca57602001905b82821061430f5750505090565b8135815260209182019101614302565b916060838303126103ca578235614335816103b9565b926020810135614344816103b9565b9260408201356001600160401b0381116103ca5761255192016142c2565b90612cd5602091949394604084526040840190612fb9565b3d156143a4573d9061438b826124cb565b916143996040519384610cc5565b82523d5f602084013e565b606090565b9080601f830112156103ca5781356143c081612b3b565b926143ce6040519485610cc5565b81845260208085019260051b8201019283116103ca57602001905b8282106143f65750505090565b602080918335614405816103b9565b8152019101906143e9565b906080828203126103ca578135614426816103b9565b9260208301356001600160401b0381116103ca57826144469185016143a9565b9260408101356001600160401b0381116103ca57836144669183016143a9565b9260608201356001600160401b0381116103ca5761255192016142c2565b61449391939293810190614410565b6001600160a01b039093165f8181526006602052604090209192916144b790612dd1565b916144d861195a6126298560018060a01b03165f52600560205260405f2090565b156144ea575050610d1e939450614ac2565b9150935f5b8451811015614669575f806145076131228487612f69565b6145146131228589612f69565b9061451f858a612f69565b51906001600160a01b03811615841461459657506040516340c10f1960e01b602082019081526001600160a01b039093166024820152604481019190915261456a8160648101611020565b5190828a5af161457861437a565b5015614588576001905b016144ef565b62ec6f7b60e31b5f5260045ffd5b916001600160a01b0381161584146145fe5750604051630852cd8d60e31b6020820190815260248201929092529091506145d38160448101611020565b5190828a5af16145e161437a565b50156145ef57600190614582565b631bc5aabf60e21b5f5260045ffd5b6040516323b872dd60e01b602082019081526001600160a01b039485166024830152939091166044820152606481019190915261463e8160848101611020565b5190828a5af161464c61437a565b501561465a57600190614582565b6312171d8360e31b5f5260045ffd5b50949392505050803b156103ca5760405163163b5cc360e31b815260048101929092525f908290602490829084905af18015610624576146a65750565b80610f0e5f610d1e93610cc5565b8034036146be5790565b6304fb820960e51b5f523460045260245ffd5b60405163393f876560e21b81527f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b031690602081600481855afa908115610624575f916147ba575b506001600160a01b03169182156147ab576040516323b872dd60e01b60208281019182523360248401526001600160a01b03909416604483015260648201929092525f91906147728160848101611020565b519082855af115612578575f513d6147a25750803b155b6147905750565b635274afe760e01b5f5260045260245ffd5b60011415614789565b6329b99a9560e11b5f5260045ffd5b6147d3915060203d602011612786576127778183610cc5565b5f614720565b612551906027614835936148b260ff8251169163ffffffff60208201511690604081015115156001600160401b036060830151169061ffff6080840151169260a0600180821b0391015116936040519a8b9960208b0190612afb565b600160f81b8152600160f01b600182015260f897881b6001600160f81b031916600382015260e09190911b6001600160e01b031916600482015290151590951b600886015260c01b6001600160c01b031916600985015260f01b6001600160f01b031916601184015260601b6001600160601b0319166013830152565b0103601f198101835282610cc5565b61ffff81116148d15761ffff1690565b6306dfcc6560e41b5f52601060045260245260445ffd5b5f5b8351811015614974576001600160a01b0382166149078286612f69565b5190803b156103ca576040516323b872dd60e01b81523060048201526001600160a01b038616602482015260448101929092525f908290606490829084905af180156106245761495b575b506001016148ea565b806149675f8093610cc5565b8003126103ca575f614952565b50610d1e929150614f2b565b9061498a82612b3b565b6149976040519182610cc5565b82815280926149a8601f1991612b3b565b01905f5b8281106149b857505050565b8060606020809385010152016149ac565b6020818303126103ca578051906001600160401b0382116103ca57019080601f830112156103ca5781516149fc81612b3b565b92614a0a6040519485610cc5565b81845260208085019260051b820101918383116103ca5760208201905b838210614a3657505050505090565b81516001600160401b0381116103ca57602091614a58878480948801016124e6565b815201910190614a27565b602081016020825282518091526040820191602060408360051b8301019401925f915b838310614a9557505050505090565b9091929394602080614ab3600193603f198682030187528951610ab9565b97019301930191939290614a86565b9291614ad6614ad182516132c3565b614980565b60045490945f91614aef906001600160a01b03166114aa565b6001600160a01b03821696908703614dc7576c3607fce1ac9e043a86675c5c2f945b5f5b8551811015614cff57614b296131228284612f69565b614b338288612f69565b5190614b56612dd1836110698960018060a01b03165f52600760205260405f2090565b6040516331a9108f60e11b8152600481018490526020818e81806024810103915afa908115610624575f91614ce1575b50306001600160a01b0390911603614cd25789906001600160a01b038116614c62575b506001600160a01b038216614bc4575b505050600101614b13565b60405163b18e2bbb60e01b60208201526001600160a01b03808416602483015290911660448201526064810183905264ffffffffff6084820152600160a482018190529297929392614c5a9291611e7b918691614c248160c48101611020565b614c2e828b612f69565b52614c39818a612f69565b506001600160a01b038a165f90815260076020526040902091019990611069565b905f88614bb9565b60405163b18e2bbb60e01b60208201526001600160a01b039182166024820152911660448201526064810183905264ffffffffff60848201525f60a48201529096600191614cb38160c48101611020565b614cbd8288612f69565b52614cc88187612f69565b500195885f614ba9565b6349e27cff60e01b5f5260045ffd5b614cf9915060203d8111612786576127778183610cc5565b5f614b86565b505094955050915050614d1181614980565b915f5b828110614d9d575050614d245750565b5f614d439160405180938192631592ca1b60e31b835260048301614a63565b0381837f00000000000000000000000000000000000000447e69651d841bd8d104bed4936001600160a01b03165af1801561062457614d7f5750565b614d9a903d805f833e614d928183610cc5565b8101906149c9565b50565b80614daa60019284612f69565b51614db58287612f69565b52614dc08186612f69565b5001614d14565b8194614b11565b614ddd90600b95939492612afb565b600160f81b815260f093841b6001600160f01b03199081166001830152600160f01b60038301529190931b16600583015260e01b6001600160e01b03191660078201520190565b92614e3861255197969394601f9693612afb565b93151560f81b845260c01b6001600160c01b031916600184015260f01b6001600160f01b031916600983015260601b6001600160601b031916600b8201520190612afb565b9061255190611020614e91825161ffff1690565b91614ed960c0820195614ecb614eb0614eab895151613374565b6148c1565b602085015163ffffffff169060405197889460208601614dce565b03601f198101855284610cc5565b6040810151151594614ef560608301516001600160401b031690565b91614f1960a0614f0a608084015161ffff1690565b9201516001600160a01b031690565b91519260405197889660208801614e24565b9190614f378151614980565b600454614f4c906001600160a01b03166114aa565b6001600160a01b038516036150b3576c3607fce1ac9e043a86675c5c2f935b5f925f5b815181101561506757614f828183612f69565b519487614fa6612dd1886110698860018060a01b03165f52600760205260405f2090565b6001600160a01b0381161561505b5760405163b18e2bbb60e01b60208201526001600160a01b039182166024820152911660448201526064810187905264ffffffffff60848201525f60a4820152600192916150559161504591859161500f8160c48101611020565b615019868b612f69565b52615024858a612f69565b506001600160a01b0388165f90815260076020526040902091019890611069565b80546001600160a01b0319169055565b01614f6f565b50509450600190615055565b50505091925061507681614980565b915f5b828110615089575050614d245750565b8061509660019284612f69565b516150a18287612f69565b526150ac8186612f69565b5001615079565b83614f6b56fea2646970667358221220b6ee7d3d94ce99462617ed99493a6ec9a7f4dfb5fc14f459b5c15d181346632b64736f6c634300081c0033
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:44756: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:44756:41;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;-1:-1:-1;1835:44756:41;;;7564:104;1835:44756;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;;;;;;;;;-1:-1:-1;;;2673:47:25;;;:87;;;;1835:44756:41;;;;;;;;;;2673:87:25;-1:-1:-1;;;862:40:37;;-1:-1:-1;2673:87:25;;;1835:44756:41;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;20394:17;1835:44756;;;;;;;20394:40;1835:44756;;;;;;;-1:-1:-1;;;;;1835:44756:41;;20512:37;20508:73;;20611:53;;;20697:136;20611:53;-1:-1:-1;20611:53:41;20754:69;20611:53;;:::i;:::-;1835:44756;;;;;;;;;;;;20754:69;;:::i;:::-;1835:44756;;8277:1;;;;;;;20697:136;;;1835:44756;20697:136;;;:::i;:::-;;:4;;:136;;;;;;;20870:40;20697:136;-1:-1:-1;20697:136:41;;;1835:44756;20870:40;;:::i;:::-;8277:1;;1835:44756;20943:14;;;8277:1;1835:44756;;;;;;;;;;;;;;;;;;;20697:136;;;;;;;-1:-1:-1;20697:136:41;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;:::i;20508:73::-;20558:23;;;-1:-1:-1;20558:23:41;1835:44756;-1:-1:-1;20558:23:41;1835:44756;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;6832:41;1835:44756;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44756:41;19453:17;1835:44756;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;1835:44756:41;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;-1:-1:-1;;4694:10:15;4681:8;-1:-1:-1;;;;;1835:44756:41;4673:31:15;4669:68;;1835:44756:41;;;;;;:::i;:::-;4837:32:15;;;:::i;:::-;4873:14;;;;1835:44756:41;4837:50:15;;;4833:103;;1835:44756:41;;;;;:::i;:::-;;4833:103:15;1835:44756:41;;;;;;:::i;:::-;4896:40:15;;;-1:-1:-1;4896:40:15;1835:44756:41;;;;;;-1:-1:-1;4896:40:15;4669:68;4713:24;;;-1:-1:-1;4713:24:15;4694:10;1835:44756:41;;;-1:-1:-1;4713:24:15;1835:44756:41;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;843:1:16;1835:44756:41;;678:1:15;1835:44756:41;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;-1:-1:-1;1835:44756:41;8027:64;1835:44756;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;-1:-1:-1;1835:44756:41;3901:6:25;1835:44756:41;;3901:22:25;1835:44756:41;-1:-1:-1;1835:44756:41;3901:22:25;1835:44756:41;3810:120:25;;1835:44756:41;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;6394:42;1835:44756;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;4330:25:25;1835:44756:41;;;;;;;:::i;:::-;2475:4:25;4300:18;;-1:-1:-1;1835:44756:41;3901:6:25;1835:44756:41;;3901:22:25;1835:44756:41;-1:-1:-1;1835:44756:41;3901:22:25;1835:44756:41;3810:120:25;;4300:18;2475:4;:::i;:::-;4330:25;:::i;1835:44756:41:-;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;1819:5:13;1835:44756:41;;;;;:::i;:::-;;;1500:62:27;;;:::i;:::-;1819:5:13;:::i;1835:44756:41:-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;;:::i;:::-;735:10:35;-1:-1:-1;;;;;1835:44756:41;;5421:34:25;5417:102;;5529:37;;;:::i;5417:102::-;5478:30;;;-1:-1:-1;5478:30:25;1835:44756:41;-1:-1:-1;5478:30:25;1835:44756:41;;;;;;-1:-1:-1;;1835:44756:41;;;;;;6934:60;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44756:41;7899:65;1835:44756;;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;1835:44756:41;;;;;;;;-1:-1:-1;;1835:44756:41;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;;20394:17;1835:44756;;;;;;;;;;;;21748:40;1835:44756;;;21866:37;21862:73;;22058:139;1835:44756;-1:-1:-1;1835:44756:41;22110:77;1835:44756;;;21969:55;;;;;;;;;;;:::i;:::-;;1835:44756;;21969:55;;;;;;:::i;:::-;22110:77;;:::i;1835:44756::-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;:::o;:::-;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;:::o;:::-;;;;;;-1:-1:-1;1835:44756:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:::o;:::-;;;-1:-1:-1;1835:44756:41;;;;;-1:-1:-1;1835:44756:41;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;538:93:22;1835:44756:41;;;;;:::i;:::-;;;;:::i;:::-;;;-1:-1:-1;1835:44756:41;538:93:22;1835:44756:41;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;538:93:22;1835:44756:41;:::i;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;446:46:13;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;11677:1:41;11660:13;:18;11656:45;;1835:44756;;-1:-1:-1;;;;;1835:44756:41;11711:61;;1835:44756;;;-1:-1:-1;;;;;;1835:44756:41;-1:-1:-1;;;;;1835:44756:41;;;;;6394:42;11875:69;;;;1835:44756;;-1:-1:-1;;;11875:69:41;;-1:-1:-1;;;;;1835:44756:41;;;11875:69;;1835:44756;11677:1;1835:44756;;;;-1:-1:-1;1835:44756:41;;;-1:-1:-1;6394:42:41;11875:69;;;;;;;;1835:44756;-1:-1:-1;;;;;;1835:44756:41;11960:28;-1:-1:-1;;11960:28:41;1835:44756;11875:69;;;-1:-1:-1;11875:69:41;;;:::i;:::-;;;:::i;:::-;;;;11711:61;11749:23;;;-1:-1:-1;11749:23:41;1835:44756;-1:-1:-1;11749:23:41;11656:45;11687:14;;;-1:-1:-1;11687:14:41;1835:44756;-1:-1:-1;11687:14:41;1835:44756;;;;;;-1:-1:-1;;1835:44756:41;;;;;;7045:50;-1:-1:-1;;;;;1835:44756:41;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;;32795:36;8338:10;32795:36;;32791:61;;32931:75;1835:44756;32931:75;1835:44756;;;8277:1;;;;;;1835:44756;32931:75;;;1835:44756;32931:75;;;:::i;:::-;;1835:44756;;32931:75;;;;;;:::i;:::-;1835:44756;;;33048:56;;33090:13;33048:56;33090:13;33048:56;33090:13;33073:4;;33048:56;;:::i;:::-;1835:44756;33038:67;;33120:36;:21;:29;:21;;;1835:44756;;;;33120:13;1835:44756;;;;;;;33120:21;1835:44756;;;;;;;;;;33120:29;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;33120:36;1835:44756;33120:51;33116:84;;33251:43;33258:36;:21;:29;:21;;33500:49;33258:21;1835:44756;;;;33120:13;1835:44756;;;;;;;33258:36;8338:10;33523:9;33073:4;33500:49;:::i;:::-;33564:8;;33560:171;;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;;;1835:44756:41;;;;;;33746:44;;1835:44756;;33746:44;1835:44756;33560:171;33642:79;;;1835:44756;33642:79;;33116:84;33180:20;;;-1:-1:-1;33180:20:41;1835:44756;-1:-1:-1;33180:20:41;32791:61;32840:12;;;-1:-1:-1;32840:12:41;1835:44756;-1:-1:-1;32840:12:41;1835:44756;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;-1:-1:-1;;;;;1835:44756:41;6741:44;1835:44756;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;1500:62:27;;:::i;:::-;1835:44756:41;;;-1:-1:-1;;;;;;1835:44756:41;;;;-1:-1:-1;;;;;1835:44756:41;3052:40:27;1835:44756:41;;3052:40:27;1835:44756:41;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;:::i;:::-;;;;-1:-1:-1;1835:44756:41;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;2217:4:15;2198:24;1835:44756:41;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;17919:87;1835:44756;;;;;:::i;:::-;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44756:41;;;;;;-1:-1:-1;1835:44756:41;17919:17;1835:44756;;;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;1835:44756:41;;;;;;;-1:-1:-1;;;1835:44756:41;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;16698:38;1835:44756;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44756:41;;;;16646:36;1835:44756;;;;;;16646:36;1835:44756;;;;;;16698:38;1835:44756;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;2954:29:25;1835:44756:41;;;;;;;:::i;:::-;-1:-1:-1;1835:44756:41;2954:6:25;1835:44756:41;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;;2954:29:25;1835:44756:41;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;16341:4;;;16319:10;:27;16315:59;;1835:44756;8338:10;1835:44756;;;;;:::i;:::-;;33915:44;8338:10;;;6143;33979:38;33997:20;;1835:44756;;33997:14;1835:44756;;;;;;;33997:20;1835:44756;33979:15;:38;:::i;:::-;:54;33975:85;;34141:4;;;:::i;33975:85::-;34042:18;;;-1:-1:-1;34042:18:41;1835:44756;-1:-1:-1;34042:18:41;33911:354;36294:51;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;;20394:17;1835:44756;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;36440:34;36436:70;;1835:44756;;36565:13;36533:45;36565:13;;36733:8;;;;:::i;36588:498::-;-1:-1:-1;;;;;36875:32:41;-1:-1:-1;;36931:81:41;;;;36867:41;;-1:-1:-1;;;;;1835:44756:41;36875:32;-1:-1:-1;;;;;1835:44756:41;;;36867:41;1835:44756;;;36931:81;;;;;;;;;;;;;;;;:::i;:::-;36867:159;;;;;;:::i;:::-;;33911:354;37040:35;37061:14;;;-1:-1:-1;37061:14:41;1835:44756;-1:-1:-1;37061:14:41;16315:59;16355:19;;;-1:-1:-1;16355:19:41;1835:44756;-1:-1:-1;16355:19:41;1835:44756;;;;;;-1:-1:-1;;1835:44756:41;;;;;;18693:31;1835:44756;;;;;;:::i;:::-;;;3228:164:0;1835:44756:41;3360:1:0;1835:44756:41;-1:-1:-1;1835:44756:41;18693:22;1835:44756;;8338:10;1835:44756;-1:-1:-1;1835:44756:41;;8338:10;3382:1:0;8338:10:41;;1835:44756;;3228:164:0;;18693:31:41;1835:44756;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44756:41;7316:83;1835:44756;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;17494:44;1835:44756;;;;;;:::i;:::-;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44756:41;17432:22;1835:44756;3584:398:0;;;;;;-1:-1:-1;3584:398:0;;-1:-1:-1;3584:398:0;;;;;;;;;;;;;;1835:44756:41;3584:398:0;;;;;;1835:44756:41;;;;;;;;;;;17494:44;1835:44756;;;;;;;-1:-1:-1;;1835:44756:41;;;;7732:86;1835:44756;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;-1:-1:-1;1835:44756:41;7732:86;1835:44756;;;-1:-1:-1;1835:44756:41;;-1:-1:-1;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;7732:86;1835:44756;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;1500:62:27;;;:::i;:::-;1835:44756:41;;;:::i;:::-;;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;;;;;;;;;;;;;;;;1503:37:22;;;:::i;1835:44756:41:-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;8277:1;;;;:::i;:::-;1835:44756;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;:::i;:::-;;-1:-1:-1;1835:44756:41;569:48:13;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;:::i;:::-;;-1:-1:-1;;;;;1835:44756:41;;14675:25;14671:62;;1835:44756;;;14757:17;1835:44756;14757:17;1835:44756;14747:27;;:67;;;;1835:44756;14743:92;;14849:20;;14845:50;;-1:-1:-1;;;;;1835:44756:41;;;;;;20394:17;1835:44756;;;;;;15070:27;1835:44756;;;;;;;;;;;:::i;:::-;15070:27;:::i;:::-;;;;15141:13;;;;-1:-1:-1;;;;;1835:44756:41;;-1:-1:-1;15156:19:41;;;;;;15108:604;;;-1:-1:-1;15887:77:41;15835:139;15108:604;;1835:44756;;;;15745:56;;;;;;;;1835:44756;15745:56;;;:::i;:::-;;1835:44756;;15745:56;;;;;;:::i;:::-;15887:77;;:::i;:::-;1835:44756;;8277:1;;;;;;;15835:139;;;1835:44756;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:44756;;;:::i;:::-;16043:9;1835:44756;;-1:-1:-1;1835:44756:41;16018:51;;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;;15984:112;:::i;:::-;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;16112:83;:::i;:::-;;;;1835:44756;15835:139;;;;;;;-1:-1:-1;15835:139:41;;;;;;:::i;:::-;;;;;15177:3;15218:11;;;;;;;;;;;:::i;:::-;1835:44756;15367:81;;;;;;1835:44756;;-1:-1:-1;;;15367:81:41;;15413:10;1835:44756;15367:81;;1835:44756;15433:4;1835:44756;;;;;;;;;;;-1:-1:-1;1835:44756:41;;;-1:-1:-1;15367:81:41;;;;;;;;1835:44756;15367:81;;;15177:3;;1835:44756;15141:13;;;;;;;;15367:81;;;-1:-1:-1;15367:81:41;;;:::i;:::-;;;;15108:604;1835:44756;;;-1:-1:-1;;;;;1835:44756: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:44756;-1:-1:-1;15686:15:41;14845:50;14878:17;;;-1:-1:-1;14878:17:41;1835:44756;-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:44756;-1:-1:-1;14709:24:41;1835:44756;;;;-1:-1:-1;1835:44756:41;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;3319:8:13;-1:-1:-1;;;;;1835:44756:41;;3319:31:13;;;;;1835:44756:41;;-1:-1:-1;;;3319:31:13;;-1:-1:-1;;;;;1835:44756:41;;;;3319:31:13;;1835:44756:41;;-1:-1:-1;;1835:44756:41;;3319:31:13;;1835:44756:41;;-1:-1:-1;;3319:31:13;;;;;;;;1835:44756:41;;;3319:31:13;;;;-1:-1:-1;3319:31:13;;:::i;1835:44756:41:-;;;;;;-1:-1:-1;;1835:44756:41;;;;17064:37;1835:44756;;;;;:::i;:::-;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;-1:-1:-1;1835:44756:41;;;17012:16;1835:44756;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;17064:37;1835:44756;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;1835:44756:41;;;18214:43;8338:10;18214:43;;;18210:76;;1835:44756;;;-1:-1:-1;;;;1835:44756:41;;;;;;-1:-1:-1;;;1835:44756:41;;;;;;;;;;;;18339:28;;1835:44756;;18339:28;1835:44756;18210:76;18266:20;;;-1:-1:-1;18266:20:41;1835:44756;-1:-1:-1;18266:20:41;1835:44756;;;;;;-1:-1:-1;;1835:44756:41;;;;4747:26:25;1835:44756:41;;;;;;;:::i;:::-;2475:4:25;4717:18;;-1:-1:-1;1835:44756:41;3901:6:25;1835:44756:41;;3901:22:25;1835:44756:41;-1:-1:-1;1835:44756:41;3901:22:25;1835:44756:41;3810:120:25;;2475:4;4747:26;:::i;1835:44756:41:-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;2475:4:25;;:::i;:::-;1835:44756:41;;;44133:26;;;44129:53;;1835:44756;;;44196:22;;;44192:47;;-1:-1:-1;;;;;1835:44756:41;;;44253:35;;44249:61;;-1:-1:-1;;;;;1835:44756:41;;;44324:37;;44320:63;;6286:9;1835:44756;;;44397:72;44393:145;;44589:13;44564:38;44589:13;;1835:44756;44665:17;1835:44756;44644:38;;44640:63;;44721:48;;;44717:90;;44612:300;-1:-1:-1;;;;;1835:44756:41;;;;;;20394:17;1835:44756;;;;;44926:68;;:54;;:40;1835:44756;44926:68;44922:110;;11063:38;11178:282;;11063:38;11178:282;11135:40;11063:38;:62;:38;;1835:44756;11063:38;1835:44756;;;;;;;;11063:13;1835:44756;;;;;;;11063:38;1835:44756;;-1:-1:-1;;;;;;1835:44756:41;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;11063:62;11178:282;1835:44756;;:::i;:::-;;;;;;;;11178:282;1835:44756;;;11178:282;;1835:44756;;11178:282;1835:44756;;;11178:282;;1835:44756;;11178:282;-1:-1:-1;;;;;1835:44756:41;;11178:282;;1835:44756;;11178:282;-1:-1:-1;;;;;1835:44756:41;;;;;20394:17;1835:44756;;;;;;;11135:40;1835:44756;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1835:44756:41;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;8338:10:41;;;;;1835:44756;;;;;;;;11476:87;-1:-1:-1;11476:87:41;;1835:44756;44922:110;45003:29;;;-1:-1:-1;45003:29:41;1835:44756;-1:-1:-1;45003:29:41;44717:90;44778:29;;;-1:-1:-1;44778:29:41;1835:44756;-1:-1:-1;44778:29:41;44612:300;1835:44756;44863:17;1835:44756;44842:38;;44612:300;44838:63;32840:12;;;-1:-1:-1;44889:12:41;1835:44756;-1:-1:-1;44889:12:41;44393:145;44492:35;;;-1:-1:-1;44492:35:41;1835:44756;-1:-1:-1;44492:35:41;44320:63;44297:13;;;-1:-1:-1;44370:13:41;1835:44756;-1:-1:-1;44370:13:41;1835:44756;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;6540:38;1835:44756;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;-1:-1:-1;;1835:44756:41;;;;488:59:14;1835:44756:41;;;;;:::i;:::-;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;488:59:14;;;528:4;488:59;;:::i;:::-;-1:-1:-1;488:59:14;;:::i;1835:44756:41:-;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1835:44756:41;19072:13;1835:44756;;;;;;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;8131:28;1835:44756;;;;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;1500:62:27;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;2627:22:27;;2623:91;;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;;;;1835:44756:41;;;;;;-1:-1:-1;;;;;1835:44756:41;;3052:40:27;;-1:-1:-1;3052:40:27;1835:44756:41;2623:91:27;2672:31;;;-1:-1:-1;2672:31:27;-1:-1:-1;1835:44756:41;;;-1:-1:-1;2672:31:27;1835:44756:41;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;12762:20;;;:40;;;;1835:44756;12758:70;;-1:-1:-1;;;;;1835:44756:41;;;;;;20394:17;1835:44756;;;;;;;;;;;12991:37;;12987:73;;13076:27;1835:44756;13075:28;1835:44756;;:::i;13076:27::-;13075:28;;1835:44756;13075:28;:88;;;1835:44756;13071:153;;13253:48;;;;;;;:::i;:::-;1835:44756;13335:136;-1:-1:-1;13392:69:41;1835:44756;;;;;;;;;;;13392:69;;;;;:::i;:::-;1835:44756;;8277:1;;;;;;;13335:136;;;1835:44756;13335:136;;;:::i;:::-;;:4;;:136;;;;;;;1835:44756;13335:136;13753:77;13335:136;13753:77;13335:136;13516:135;13335:136;-1:-1:-1;13335:136:41;;;1835:44756;;;:::i;13516:135::-;8277:1;13722:15;;13699:20;;1835:44756;;33997:14;1835:44756;;;;;;;13699:20;1835:44756;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;13753:77;:::i;:::-;;;;1835:44756;;;;;;;;;;;;;13071:153;13186:27;;;-1:-1:-1;13186:27:41;1835:44756;-1:-1:-1;13186:27:41;13075:88;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;13108:55:41;;1835:44756;;;;13108:55;;;;;;;;-1:-1:-1;13108:55:41;;;13075:88;13107:56;;13075:88;;13108:55;;;;1835:44756;13108:55;1835:44756;13108:55;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;12762:40;12786:16;;;12762:40;;1835:44756;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;-1:-1:-1;1835:44756:41;2876:5:15;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;2900:13:15;;1835:44756:41;;;2876:37:15;;1835:44756:41;;;8277:1;1835:44756;;8277:1;;1835:44756;8277:1;;:::i;:::-;1835:44756;;8277:1;;1835:44756;8277:1;;:::i;:::-;1835:44756;;8277:1;;;;;:::i;:::-;1835:44756;;8277:1;;38139:653;8277:1;;:::i;:::-;1835:44756;;8277:1;;1835:44756;8277:1;;:::i;:::-;-1:-1:-1;;;;;8277:1:41;;;;1835:44756;;-1:-1:-1;;1835:44756:41;8277:1;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;1835:44756;8277:1;1835:44756;;8277:1;;;:::i;:::-;;;;;;;;;;;;;-1:-1:-1;8277:1:41;;;;;;;;1835:44756;;;;;8277:1;:::o;:::-;;;;;;;;;;;-1:-1:-1;;;;;8277:1:41;;;;;;;;:::i;:::-;;:::o;:::-;;;1835:44756;8277:1;;;1835:44756;;;;8277:1;;;1835:44756;8277:1;;;;;;;;:::i;:::-;1835:44756;;8277:1;;;;;;;1835:44756;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;22770:2077::-;-1:-1:-1;;;;;1835:44756:41;;;;;20394:17;1835:44756;;;;;22770:2077;;;1835:44756;;;:::i;23010:40::-;1835:44756;:::i;:::-;23065:24;1835:44756;;23065:24;;;1835:44756;;;;;;;23065:29;23061:60;;1835:44756;23237:20;1835:44756;;;;;;;;23237:20;;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;;23267:18;1835:44756;;23180:13;23148:45;23180:13;;1835:44756;;-1:-1:-1;;;23328:49:41;;;;;1835:44756;;;;23065:24;1835:44756;;;-1:-1:-1;;;;;1835:44756:41;;23328:49;;-1:-1:-1;;23328:49:41;;;23296:1145;-1:-1:-1;23324:460:41;;23743:26;;;;-1:-1:-1;23743:26:41;-1:-1:-1;23743:26:41;:::o;23324:460::-;-1:-1:-1;;;;;1835:44756:41;;23441:4;23424:22;23441:4;;;;;;;23470:28;23493:4;23470:28;:::o;23420:162::-;23065:24;23545:18;23420:162;23296:1145;1835:44756;;-1:-1:-1;;;24552:160:41;;-1:-1:-1;;;;;1835:44756:41;;;24552:160;;;1835:44756;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;;;24552:160;1835:44756;24579:35;-1:-1:-1;;;;;1835:44756:41;24552:160;;-1:-1:-1;;24552:160:41;;;23296:1145;-1:-1:-1;24548:293:41;;24804:26;;-1:-1:-1;24804:26:41;:::o;24548:293::-;24751:21;-1:-1:-1;;;24751:21:41:o;24552:160::-;;;;;23065:24;24552:160;23065:24;24552:160;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;23328:49;;;;;23065:24;23328:49;23065:24;23328:49;;;;;;;:::i;:::-;;;;;23296:1145;-1:-1:-1;;;;;1835:44756:41;;;23934:37;;:92;;;;23296:1145;23930:501;;;24046:25;;;;-1:-1:-1;24046:25:41;24066:4;24046:25;:::o;23930:501::-;1835:44756;;-1:-1:-1;;;24114:52:41;;;;;1835:44756;;;23065:24;;;;1835:44756;;;;;;24114:52;;-1:-1:-1;;24114:52:41;;;23930:501;-1:-1:-1;24110:307:41;;24375:23;-1:-1:-1;24110:307:41;23296:1145;;24110:307;;23296:1145;;24114:52;;;;;;;;;;;;;;;:::i;:::-;;;;;23934:92;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;23975:51:41;;;;;1835:44756;;;23065:24;1835:44756;;;23975:51;;;;;;;;-1:-1:-1;23975:51:41;;;23934:92;;;;23975:51;;;;23065:24;23975:51;23065:24;23975:51;;;;;;;:::i;:::-;;;;23061:60;23096:25;;;-1:-1:-1;23096:25:41;23116:4;23096:25;:::o;28942:653::-;;;;;29331:164;28942:653;1835:44756;;;;;;-1:-1:-1;1835:44756:41;29187:17;1835:44756;;;;;;-1:-1:-1;1835:44756:41;;:::i;:::-;29259:24;;;1835:44756;29259:24;;1835:44756;;;;29259:34;29377:46;;1835:44756;;29331:164;:::i;:::-;29513:27;;;:::i;:::-;1059:20:23;808:1;1835:44756:41;1059:20:23;;;:::i;:::-;1835:44756:41;1059:30:23;1055:82;;2368:74;1835:44756:41;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;3589:22:1;;1835:44756:41;3589:22:1;;;;;;;:::i;:::-;2368:74:23;:::i;1055:82::-;1835:44756:41;1116:20:23;;;:::i;:::-;1098:39;;;-1:-1:-1;1098:39:23;1835:44756:41;1098:39:23;1835:44756:41;;-1:-1:-1;1098:39:23;1835:44756:41;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;:::i;5972:2::-;1835:44756;;;5972:2;;;;;;;;;1835:44756;;;5972:2;;1835:44756;5972:2;;;;:::o;:::-;;:::i;29833:837::-;46434:40;29833:837;;;;1835:44756;;;;;;-1:-1:-1;1835:44756:41;30053:17;1835:44756;;-1:-1:-1;;;;;1835:44756:41;;;-1:-1:-1;1835:44756:41;;:::i;:::-;;;30151:13;30119:45;45402:182;;;;;5634:6;45402:182;;45654:75;;;;6091:5;45654:75;1835:44756;;;6091:5;1835:44756;5529:7;1835:44756;46434:40;:::i;:::-;1835:44756;6286:9;-1:-1:-1;;;;;1835:44756:41;;46489:49;46485:97;;1835:44756;;5972:2;;1835:44756;;;;5972:2;;;;;30410:89;3994:12:23;30410:89:41;;:::i;:::-;30545:27;;;:::i;:::-;3994:12:23;:::i;45654:75:41:-;;5743:6;45654:75;;45402:182;5529:7;45402:182;;;8338:10;;;1835:44756;8338:10;;1835:44756;;;;;;8338:10;-1:-1:-1;8338:10:41;;;;;;1835:44756;;-1:-1:-1;;1835:44756:41;8338:10;;;:::o;:::-;;;;-1:-1:-1;;;;;8338:10:41;;;1835:44756;;;;;;:::i;:::-;;;;8338:10;;;1835:44756;8338:10;;;1835:44756;8338:10;1835:44756;;;;:::i;:::-;;8338:10;;;1835:44756;8338:10;;;1835:44756;8338:10;;;;;;;;:::i;:::-;1835:44756;;;8338:10;1835:44756;;8338:10;;;1835:44756;;;;;8338:10;:::o;:::-;;;;;;;;1835:44756;8338:10;;;;;;;;;;:::i;:::-;1835:44756;;;8338:10;;:::o;1835:44756::-;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;:::o;:::-;;;;;;;:::i;:::-;;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;;;;;;;-1:-1:-1;1835:44756:41;;8338:10;;;;1835:44756::o;:::-;;25359:3;1835:44756;;;25356:2;1835:44756;;;;:::o;:::-;;26718:2;1835:44756;;;26715:2;1835:44756;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;:::-;8338:10;;;;-1:-1:-1;8338:10:41;;1835:44756;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;3510:981:22:-;1835:44756:41;3510:981:22;1835:44756:41;3701:31:22;3510:981;;;;;1835:44756:41;-1:-1:-1;1835:44756:41;3701:15:22;1835:44756:41;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;3861:20:22;3857:46;;3964:25;;3960:46;;3701:15;4129:25;;;4125:267;;1835:44756:41;;4455:29:22;1835:44756:41;;4455:29:22;;;;;;;;;;;;:::i;:::-;;;;4125:267;1835:44756:41;;4170:34:22;1835:44756:41;;;;;:::i;:::-;4170:34:22;:::i;:::-;1835:44756:41;3701:15:22;1835:44756:41;;;3701:15:22;4340:41;1835:44756: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:44756:41;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;8277:1;;1835:44756;8277:1;:::i;:::-;-1:-1:-1;1835:44756:41;;;;8277:1;1835:44756;;;:::o;25167:1066::-;25347:16;25459:38;25167:1066;25336:48;25167:1066;;;;25347:16;:::i;:::-;25336:48;;;;:::i;:::-;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;;25459:38;;;;:::i;:::-;25508:33;;25585:36;;1835:44756;25585:36;26185:41;25585:36;1835:44756;;;;;;;;20394:17;1835:44756;;;;;;;;25636:27;;;;:::i;:::-;;;;-1:-1:-1;;;;;1835:44756:41;;;;;25760:15;1835:44756;;;;;26185:41;;-1:-1:-1;25760:43:41;;;;:34;1835:44756;25760:43;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;25760:43;25632:536;;1835:44756;;;-1:-1:-1;;;;;1835:44756:41;;;26185:41;;;1835:44756;;;;;;;;;;;;;;;;;;;;;;;;;;25632:536;-1:-1:-1;;1835:44756:41;25918:20;1835:44756;25907:40;;:32;;-1:-1:-1;;;;;1835:44756:41;25907:32;1835:44756;25907:40;1835:44756;;-1:-1:-1;;;25907:49:41;;;;;1835:44756;;;;25907:49;;1835:44756;;;;;;25907:49;;-1:-1:-1;;25907:49:41;;;25632:536;-1:-1:-1;25903:255:41;;26120:23;26185:41;-1:-1:-1;25903:255:41;25632:536;;25903:255;26185:41;25999:18;25903:255;25632:536;;25907:49;;;;;;;;;;;;;;;:::i;:::-;;;;;25508:33;25529:12;;;;;:::i;1835:44756::-;;-1:-1:-1;;;;;;1835:44756:41;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;;1835:44756:41;;;;;;;8338:10;;;1835:44756;;;-1:-1:-1;1835:44756:41:o;:::-;;;;;:::i;:::-;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;8338:10;;1835:44756;-1:-1:-1;1835:44756:41;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;;;;8338:10;;1835:44756;-1:-1:-1;1835:44756:41;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;26498:2072::-;1835:44756;26766:36;26690:33;26698:24;26706:15;1835:44756;26498:2072;1835:44756;26498:2072;;;;;26706:15;:::i;:::-;26698:24;;:::i;:::-;1835:44756;;;;;26837:20;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;;26899:32;;;:::i;:::-;26970;;;;:::i;:::-;27040;;;;:::i;:::-;27083:23;-1:-1:-1;27121:13:41;-1:-1:-1;27136:21:41;;;;;;1835:44756;;;;;27885:29;;27881:606;;1835:44756;28504:59;1835:44756;28504:59;1835:44756;;;26715:2;1835:44756;28504:59;;;;;;;:::i;27881:606::-;27968:26;;;;;:::i;:::-;28044;;;;:::i;:::-;28119;;;;:::i;:::-;28165:13;-1:-1:-1;28180:15:41;;;;;;1835:44756;;;;28396:80;1835:44756;;;;;28396:80;1835:44756;26715:2;1835:44756;28396:80;;;;;;;:::i;28197:3::-;28244:14;28276:34;28298:12;;28244:14;;28220:38;28244:14;28220:38;28244:14;;;1835:44756;28244:14;;;:::i;:::-;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;28244:14;28220:38;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;28220:38;28298:12;:::i;:::-;28276:34;;;;:::i;:::-;28349:11;;;;:::i;:::-;8277:1;28328:32;;;;:::i;:::-;1835:44756;;28165:13;;27159:3;27182:13;;;;;:::i;:::-;:25;;;27178:152;;27344:100;27401:13;27344:100;27401:13;27344:100;27401:13;;27344:100;27390:54;27401:13;;;;;:::i;:::-;27390:54;;;;:::i;:::-;27344:100;;;;;;:::i;:::-;1835:44756;-1:-1:-1;;;;;1835:44756:41;;27344:100;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;27344:100;;;;:::i;:::-;27463:14;;;;;:::i;:::-;:30;27481:12;;;;;:::i;27463:30::-;-1:-1:-1;;;;;1835:44756:41;;;27463:30;27459:300;;27159:3;1835:44756;27159:3;27121:13;1835:44756;27121:13;;27459:300;27537:11;1835:44756;27537:11;;;;;;:::i;:::-;8277:1;27513:35;;;;:::i;:::-;1835:44756;27566:41;27593:14;;;;;:::i;:::-;27566:41;;;;:::i;:::-;27625:37;27650:12;27625:37;27650:12;;;;;;:::i;27625:37::-;1835:44756;27459:300;;;;;27178:152;1835:44756;27307:8;;;1835:44756;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;39516:1;1835:44756;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;:::i;:::-;;;-1:-1:-1;1835:44756:41;;;;;;;;;:::o;:::-;;;;;8277:1;;;:::i;:::-;-1:-1:-1;1835:44756:41;;-1:-1:-1;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;;;;;38206:1;1835:44756;;;;;;;:::o;:::-;;7847:2:24;1835:44756:41;;;;;;;:::o;:::-;;;;;;;;;;:::o;37441:1619::-;;;;37781:53;37804:29;;;;:::i;:::-;37781:53;:::i;:::-;37850:13;37862:1;-1:-1:-1;;;;;38359:15:41;1835:44756;38732:19;;37845:972;37865:19;;;;;;8234:1;;;;;;;;39001:52;8234:1;38881:102;8234:1;;:::i;:::-;1835:44756;8234:1;;38881:102;1835:44756;38915:17;1835:44756;38528:245;38881:102;;1835:44756;;;38881:102;;1835:44756;-1:-1:-1;;;;;1835:44756:41;38139:653;38881:102;;1835:44756;;38881:102;1835:44756;38139:653;38881:102;;1835:44756;38977:4;38139:653;38881:102;;1835:44756;39001:52;:::i;37886:3::-;37862:1;37925:15;;;;;;37886:3;38206:1;1835:44756;37850:13;;37942:3;37988:35;;38015:7;;;;;;:::i;:::-;;:::i;:::-;1835:44756;;;;37988:35;1835:44756;3228:164:0;1835:44756:41;3360:1:0;1835:44756:41;-1:-1:-1;1835:44756:41;18693:22;1835:44756;;8338:10;1835:44756;-1:-1:-1;1835:44756:41;;8338:10;3382:1:0;8338:10:41;;1835:44756;;3228:164:0;;37988:35:41;1835:44756;;;38045:18;38041:43;;38202:5;;;;;:::i;:::-;38210:19;;;;:::i;:::-;38202:27;;;:::i;:::-;1835:44756;;38263:7;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;38476;;;;:::i;:::-;;;;:::i;:::-;38459:25;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;38695:11;;;;:::i;:::-;1835:44756;;-1:-1:-1;;;38528:245:41;;;;-1:-1:-1;;;;;1835:44756:41;;38528:245;;;1835:44756;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;;;;;;;38528:245;;;1835:44756;;38528:245;:::i;:::-;1835:44756;;:::i;:::-;;;;;;;;;38528:245;38139:653;;1835:44756;;;38139:653;;1835:44756;-1:-1:-1;;;;;1835:44756:41;;38139:653;;;1835:44756;;;38139:653;;;1835:44756;-1:-1:-1;;;;;1835:44756:41;38139:653;;;1835:44756;38139:653;;;1835:44756;38116:15;;;;;:::i;:::-;:19;;;;:::i;:::-;38103:689;;;;;:::i;:::-;;;;;;:::i;:::-;;38206:1;1835:44756;37910:13;;1835:44756;;;8277:1;;;;:::i;:::-;-1:-1:-1;1835:44756:41;;;;;;;:::o;:::-;;;;;;;;;;;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;:::o;2038:391:16:-;2259:163;2038:391;2291:86;2038:391;1835:44756:41;;:::i;:::-;;2316:25:16;;;:::i;:::-;2291:86;1835:44756:41;;:::i;:::-;;;;;;;;2291:86:16;;;;1835:44756:41;2291:86:16;;;1835:44756:41;2291:86:16;;;1835:44756:41;-1:-1:-1;2291:86:16;;;1835:44756:41;;;8277:1;;;;;;;2259:163:16;;2403:4;2259:163;;;;;:::i;:::-;;1835:44756:41;2259:8:16;-1:-1:-1;;;;;1835:44756: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:44756:41;;;-1:-1:-1;1835:44756:41;2822:5:13;1835:44756:41;;;-1:-1:-1;1835:44756:41;;2847:18:13;;;2843:43;;2896:11;2718:196;:::o;2843:43::-;2874:12;;;-1:-1:-1;2874:12:13;;1835:44756: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:44756;;;5417:6;;;;;;;;:::i;30952:1103::-;;;;;1835:44756;31165:16;1835:44756;;;;;;31165:47;;;;30952:1103;31161:82;;;31320:77;;1835:44756;;;8277:1;;;;;;31320:77;;;;;;;;;:::i;:::-;31643:51;31491:9;:29;:9;:29;:::i;:::-;31651:4;31643:51;:::i;:::-;31709:8;;;31705:344;;30952:1103;;;:::o;31705:344::-;1835:44756;31970:68;1835:44756;;;31806:56;;;31320:77;31806:56;;31848:13;;31651:4;;31806:56;;:::i;:::-;1835:44756;31796:67;;31970:68;32016:13;31984:14;31877:29;31891:14;;;:::i;:::-;1835:44756;;;;33120:13;1835:44756;;;;;;;31877:29;31907:14;31877:45;31320:77;31907:14;;1835:44756;31877:45;;1835:44756;;;;;;;;;;31877:45;31923:13;31877:60;1835:44756;31923:13;;;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;31877:60;1835:44756;31984:14;:::i;:::-;32016:13;;:::i;:::-;1835:44756;;;;;;;31970:68;;;:::i;:::-;;;;30952:1103::o;31161:82::-;31221:22;;;;;;;;31165:47;-1:-1:-1;;;;;1835:44756:41;;;;;31186:16;1835:44756;;;;;;;;13075:28;;-1:-1:-1;31165:47:41;;3199:103:25;735:10:35;-1:-1:-1;1835:44756: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:44756:41;6540:38;1835:44756;;;-1:-1:-1;3565:47:25;3199:103;-1:-1:-1;1835:44756:41;;;2954:6:25;1835:44756:41;;;;;;;;735:10:35;1835:44756: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:44756:41;;;;-1:-1:-1;3565:47:25;6179:316;1835:44756:41;;;;2954:6:25;1835:44756:41;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;2954:6:25;1835:44756:41;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;-1:-1:-1;;1835:44756:41;6347:4:25;1835:44756:41;;;735:10:35;;-1:-1:-1;;;;;1835:44756:41;;6370:40:25;-1:-1:-1;;6370:40:25;6347:4;6424:11;:::o;6272:217::-;6466:12;;1835:44756:41;6466:12:25;:::o;1796:162:27:-;1710:6;1835:44756:41;-1:-1:-1;;;;;1835:44756: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:44756:41;;1710:6:27;1901:40;2286:134:13;2393:20;2286:134;1835:44756:41;;2286:134:13;1835:44756:41;;;-1:-1:-1;1835:44756:41;2359:5:13;1835:44756:41;;;;-1:-1:-1;1835:44756:41;;;;2393:20:13;1835:44756:41;;;;;;2393:20:13;2286:134::o;6730:317:25:-;1835:44756:41;;;;2954:6:25;1835:44756:41;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;;;;;;2954:6:25;1835:44756:41;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;735:10:35;;-1:-1:-1;;;;;1835:44756:41;;6922:40:25;-1:-1:-1;;6922:40:25;1835:44756:41;6976:11:25;:::o;6091:5:41:-;;-1:-1:-1;;;;;6091:5:41;;1835:44756;;;6091:5;;-1:-1:-1;;;;;6091:5:41;;;;:::o;45045:1544::-;;-1:-1:-1;;;;;46434:40:41;45045:1544;;;;45937:56;;;;45045:1544;45937:175;;;;;46172:84;;;5529:7;;1835:44756;;46172:84;1835:44756;5634:6;;;1835:44756;46434:40;:::i;:::-;1835:44756;6286:9;-1:-1:-1;;;;;1835:44756:41;;46489:49;46485:97;;45045:1544::o;46172:84::-;;;45937:175;;5743:6;45937:175;;;:56;1835:44756;;;;45949:44;;45937:56;;1294:107:23;1835:44756:41;;-1:-1:-1;;;1370:24:23;;;808:1;1370:24;;;;;1835:44756:41;1370:24:23;:::i;1003:152::-;;808:1;1835:44756:41;1059:20:23;;;:::i;:::-;1835:44756:41;1059:30:23;1055:82;;1835:44756:41;;;;;;;-1:-1:-1;;1835:44756:41;4234:37:1;;;1835:44756:41;;8277:1;-1:-1:-1;;;;;;8277:1:41;1835:44756;;;;;4234:37:1;;;;1835:44756:41;4234:37:1;:::i;:::-;808:1:23;1835:44756:41;1059:20:23;;;:::i;:::-;1835:44756:41;1059:30:23;1055:82;;306:1:1;1835:44756:41;6912:25:23;1835:44756:41;;6912:25:23;:::i;:::-;1835:44756:41;250:1:1;;1835:44756:41;250:1:1;;;;;6809:221:23;1835:44756:41;250:1:1;;1835:44756:41;;;6809:221:23;;;;;;250:1:1;;:::i;:::-;-1:-1:-1;;;250:1:1;;808::23;;;;;-1:-1:-1;;;;;;808:1:23;1835:44756:41;250:1:1;;808::23;-1:-1:-1;;;808:1:23;250::1;;;;;;:::i;1055:82:23:-;1835:44756:41;1116:20:23;;;:::i;745:1292:47:-;;;33251:43:41;745:1292:47;;;;1835:44756:41;;;;:::i;:::-;;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;:::i;:::-;;;;;;;1269:722:47;;;;;;;;1835:44756:41;1269:722:47;;;;745:1292;1269:722;;;33251:43:41;1269:722:47;;;;2000:30;745:1292;:::o;1269:722::-;;1835:44756:41;1269:722:47;;1835:44756:41;;;;;;;;;:::o;:::-;-1:-1:-1;1835:44756:41;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;8338:10:41;;1835:44756;;;;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;1835:44756:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8338:10;;1835:44756;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2237:514:22;2357:1;2389:3;1835:44756:41;;2360:27:22;;;;;2542:19;:27;;:19;1835:44756:41;2542:19:22;;;:::i;:::-;;:27;;;:::i;:::-;1835:44756:41;2542:27:22;2656:19;;;;:::i;:::-;;:27;;1835:44756:41;2600:19:22;;;;:::i;:::-;;1835:44756:41;;2357:1:22;1835:44756:41;2584:15:22;1835:44756:41;;2584:69:22;2542:27;2357:1;1835:44756:41;2625:27:22;1835:44756:41;2625:19:22;;;;:::i;:::-;;:27;1835:44756:41;;;;;2625:27:22;1835:44756:41;;;;;;;;;;;2584:69:22;1835:44756:41;:::i;:::-;;2345:13:22;;2360:27;;2709:35;;2360:27;2542;1835:44756:41;2709:35:22;;;;;:::i;:::-;;;;2237:514::o;4631:264::-;808:1:23;1835:44756:41;4743:71:22;;;;1835:44756:41;4827:28:22;4823:65;;4631:264;:::o;4823:65::-;1835:44756:41;;-1:-1:-1;;;4864:24:22;;1835:44756:41;4864:24:22;;;1835:44756:41;;;;;;;;;;;:::i;43602:239::-;1835:44756;;;;43706:33;43702:69;;1835:44756;;;;43821:13;43789:45;43602:239;:::o;1835:44756::-;;;8277:1;;;;:::i;:::-;1835:44756;-1:-1:-1;1835:44756:41;;-1:-1:-1;1835:44756:41;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;8277:1;;;;:::i;:::-;1835:44756;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::o;3188:766:16:-;3809:92;;3188:766;;3755:192;3188:766;;1835:44756: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:44756:41;3809:92:16;1835:44756:41;;:::i;:::-;;;;;;;;3809:92:16;3617:15;3809:92;;1835:44756:41;3809:92:16;;;1835:44756:41;3809:92:16;;;1835:44756:41;;;3809:92:16;;;1835:44756:41;;3809:92:16;;1835:44756:41;8277:1;;;;;;;;;3755:192:16;;;;;;:::i;:::-;;;:8;-1:-1:-1;;;;;1835:44756: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:44756:41;;7231:34:24;:::i;:::-;1835:44756:41;;-1:-1:-1;;;7187:79:24;;;808:1:23;1835:44756:41;1467:1:24;;;808::23;;;;;;-1:-1:-1;;;;;;808:1:23;1467::24;;;808::23;7187:79:24;;;;;1835:44756:41;7187:79:24;:::i;:::-;7281:13;1835:44756:41;7276:133:24;7325:3;1835:44756:41;;7296:27:24;;;;;7350:48;8277:1:41;7378:19:24;;;;;:::i;:::-;;7350:48;;:::i;:::-;7325:3;1835:44756:41;7281:13:24;;;7296:27;;;;;;6760:57;1835:44756:41;;7187:79:24;6831:25;;1835:44756:41;;;;;;;6827:159:24;;6995:10;;6561:451;:::o;6827:159::-;6931:44;;;;:::i;12935:305:40:-;13065:1;1835:44756:41;;13039:27:40;1835:44756:41;;13065:1:40;13127:81;;12935:305;:::o;1835:44756:41:-;;;-1:-1:-1;;;1835:44756:41;;;;;;;;;;;;-1:-1:-1;;;1835:44756:41;;;;;;;6602:435:23;;808:1;1835:44756:41;1059:20:23;;;:::i;:::-;1835:44756:41;1059:30:23;1055:82;;1835:44756:41;;6912:25:23;1835:44756:41;;6912:25:23;:::i;:::-;1835:44756:41;250:1:1;;1835:44756:41;250:1:1;;;;;6809:221:23;1835:44756:41;250:1:1;;1835:44756:41;;;6809:221:23;;;;;;250:1:1;;:::i;:::-;-1:-1:-1;;;250:1:1;;;808::23;;;;;-1:-1:-1;;;;;;808:1:23;1835:44756:41;250:1:1;;808::23;;250::1;;;;;;;;;:::i;1835:44756:41:-;;;;;;;;;;;;;;;:::i;:::-;;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;-1:-1:-1;1835:44756:41;;;;:::o;:::-;;;:::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1835:44756:41;;;;;;;;:::i;34277:1851::-;34484:64;34277:1851;;;;34484:64;;;;:::i;:::-;-1:-1:-1;;;;;1835:44756:41;;;;;;;11063:13;1835:44756;;;;;;;;34591:28;;;1835:44756;34591:28;34663:40;34729:27;1835:44756;34663:40;;1835:44756;;;;;;;;20394:17;1835:44756;;;;;;;34729:27;34663:40;;;35034:8;;;;;;;:::i;34883:1239::-;35079:13;;;-1:-1:-1;35115:3:41;1835:44756;;35094:19;;;;;-1:-1:-1;35159:14:41;;;;;;:::i;:::-;35210:12;;;;;:::i;:::-;35258:11;;;;;:::i;:::-;8277:1;;-1:-1:-1;;;;;1835:44756:41;;35292:24;1835:44756;;;;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;35404:67:41;;;;;;-1:-1:-1;;;;;1835:44756:41;;;35404:67;;;1835:44756;;;;;;;;35404:67;1835:44756;;;;35404:67;1835:44756;35404:67;35382:90;;;;;;;;:::i;:::-;;35498:8;35494:33;;1835:44756;35288:766;;1835:44756;35079:13;;35494:33;35515:12;;;-1:-1:-1;35515:12:41;35404:67;-1:-1:-1;35515:12:41;35288:766;1835:44756;-1:-1:-1;;;;;1835:44756:41;;35556:22;1835:44756;;;;-1:-1:-1;1835:44756:41;;-1:-1:-1;;;35642:49:41;;;;;;;;;1835:44756;;;;35642:49;;-1:-1:-1;35642:49:41;1835:44756;;;;35642:49;1835:44756;35642:49;35620:72;;;;;;;;:::i;:::-;;35718:8;35714:33;;1835:44756;35552:502;35288:766;;35714:33;35735:12;;;-1:-1:-1;35735:12:41;35642:49;-1:-1:-1;35735:12:41;35552:502;1835:44756;;-1:-1:-1;;;35859:95:41;;;;;;-1:-1:-1;;;;;1835:44756:41;;;35859:95;;;1835:44756;;;;;;;;;;;;;;;;35859:95;1835:44756;;;;35859:95;1835:44756;35859:95;35812:164;;;;;;;;:::i;:::-;;36002:8;35998:37;;1835:44756;35552:502;35288:766;;35998:37;36019:16;;;-1:-1:-1;36019:16:41;35859:95;-1:-1:-1;36019:16:41;35094:19;;;;;;;;36082:29;;;;;1835:44756;;-1:-1:-1;;;36082:29:41;;;;;1835:44756;;;;-1:-1:-1;;1835:44756:41;;;;;;-1:-1:-1;;36082:29:41;;;;;;;;34883:1239;34277:1851::o;36082:29::-;;;-1:-1:-1;36082:29:41;;;:::i;4650:191:16:-;4749:9;;:23;4745:62;;4650:191;:::o;4745:62::-;4781:26;;;;;4749:9;4781:26;1835:44756:41;;4781:26:16;;5218:410;1835:44756:41;;-1:-1:-1;;;5389:18:16;;:8;-1:-1:-1;;;;;1835:44756:41;;5389:18:16;1835:44756:41;5389:18:16;1835:44756:41;;5389:18:16;;;;;;;-1:-1:-1;5389:18:16;;;5218:410;-1:-1:-1;;;;;;1835:44756:41;;5421:21:16;;5417:54;;1835:44756:41;;-1:-1:-1;;;5389:18:16;1797:53:32;;;;;;5578:10:16;1797:53:32;;;1835:44756:41;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;;-1:-1:-1;;1797:53:32;;1835:44756:41;;;;1797:53:32;1835:44756: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:44756: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:44756:41;1704:1:24;;1835:44756:41;8540:18:24;1835:44756:41;8540:18:24;;;1835:44756:41;;8576:19:24;;;;1704:1;1835:44756:41;;-1:-1:-1;;;;;8613:28:24;;;1704:1;1835:44756:41;8659:22:24;1835:44756:41;8659:22:24;;;1835:44756:41;;;8699:11:24;1835:44756:41;;;;;8699:11:24;;1835:44756:41;;;8576:19:24;1835:44756:41;8359:365:24;;;8540:18;8359:365;;1704:1;;:::i;:::-;-1:-1:-1;;;250:1:1;;-1:-1:-1;;;1835:44756:41;1704:1:24;;808::23;250::1;;;;-1:-1:-1;;;;;;250:1:1;1704::24;;;250::1;1835:44756:41;8277:1;;;;-1:-1:-1;;;;;;8277:1:41;1704::24;;;1835:44756: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:44756:41;;8359:365:24;;;;;;:::i;16296:213:39:-;1835:44756:41;16374:24:39;;16370:103;;1835:44756:41;;16296:213:39;:::o;16370:103::-;16421:41;;;;;16452:2;16421:41;1835:44756:41;;;;16421:41:39;;41689:381:41;41873:1;41897:3;1835:44756;;41876:19;;;;;-1:-1:-1;;;;;1835:44756:41;;41984:11;;;;:::i;:::-;8277:1;41916:80;;;;;;1835:44756;;-1:-1:-1;;;41916:80:41;;41964:4;41916:80;;;1835:44756;-1:-1:-1;;;;;1835:44756:41;;;;;;;;;;;;;-1:-1:-1;;1835:44756:41;;;;;;-1:-1:-1;;41916:80:41;;;;;;;;41897:3;;1835:44756;;41861:13;;41916:80;;;41873:1;41916:80;;;:::i;:::-;1835:44756;;;;;41916:80;;;41876:19;;42054:8;41876:19;;;42054:8;:::i;1835:44756::-;;;;;:::i;:::-;8277:1;1835:44756;;8277:1;;;:::i;:::-;1835:44756;;;;;;;;;;:::i;:::-;;;-1:-1:-1;1835:44756:41;;;;;;;;;:::o;:::-;;;;;;;;;;;;;6701:34;;;;;;;;;;;-1:-1:-1;;;;;6701:34:41;;;;;;;;;;;;;;;;;;;:::i;:::-;1835:44756;8277:1;1835:44756;;8277:1;;;:::i;:::-;6701:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;6701:34:41;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1835:44756;;;;;;;;6701:34;;1835:44756;6701:34;;;;;;8338:10;;6701:34;;;;;;;;;;;;;;;:::o;:::-;1835:44756;;;;;6701:34;1835:44756;6701:34;;1835:44756;;;6701:34;;;;;;;;;:::i;:::-;1835:44756;;6701:34;;;;;;;;;;39311:2125;;;39486:32;39498:19;1835:44756;;39498:19;:::i;:::-;39486:32;:::i;:::-;39623:11;1835:44756;39528:31;;39558:1;;39602:32;;-1:-1:-1;;;;;1835:44756:41;;;39602:32;-1:-1:-1;;;;;1835:44756:41;;;;39602:32;;;;6394:42;39602:77;;39558:1;39731:3;1835:44756;;39710:19;;;;;39769:12;;;;;:::i;:::-;39813:11;;;;:::i;:::-;8277:1;39859:34;:43;;:34;;;1835:44756;;;;;;;;25760:15;1835:44756;;;;;;;39859:43;1835:44756;;-1:-1:-1;;;39921:43:41;;39623:11;39921:43;;1835:44756;;;39921:43;1835:44756;;;;;;;39921:43;;;;;;;;;39558:1;39921:43;;;39731:3;-1:-1:-1;39976:4:41;-1:-1:-1;;;;;1835:44756:41;;;39921:60;39917:120;;1835:44756;;-1:-1:-1;;;;;1835:44756:41;;40051:479;;39731:3;-1:-1:-1;;;;;;1835:44756:41;;40544:547;;39731:3;;;;1835:44756;;39695:13;;40544:547;1835:44756;;-1:-1:-1;;;39921:43:41;40630:283;;;-1:-1:-1;;;;;1835:44756:41;;;40630:283;;;1835:44756;;;;6701:34;;;1835:44756;6701:34;;;1835:44756;;;;6701:34;;;1835:44756;;6701:34;;;1835:44756;;;;;;;;41022:54;;1835:44756;41022:43;;1835:44756;;40630:283;1835:44756;6701:34;;;40630:283;6701:34;40630:283;40590:323;;;;:::i;:::-;;;;;;:::i;:::-;-1:-1:-1;;;;;;1835:44756:41;;;;;;25760:15;1835:44756;;;;;;;;41022:34;;1835:44756;41022:54;40544:547;;;;;40051:479;1835:44756;;-1:-1:-1;;;39921:43:41;40139:286;;;-1:-1:-1;;;;;1835:44756:41;;;40139:286;;;1835:44756;;;6701:34;;;1835:44756;6701:34;;;1835:44756;;;;6701:34;;;1835:44756;39558:1;6701:34;;;1835:44756;;;;;40139:286;1835:44756;6701:34;;;40139:286;6701:34;40139:286;40099:326;;;;:::i;:::-;;;;;;:::i;:::-;;1835:44756;40051:479;;;;;39917:120;40008:14;;;39558:1;40008:14;39623:11;39558:1;40008:14;39921:43;;;;;;;;;;;;;;:::i;:::-;;;;39710:19;;;;;;;;;;41142:32;;;:::i;:::-;41189:13;39558:1;41204:23;;;;;;41311;;41307:123;;39311:2125;:::o;41307:123::-;39558:1;41350:69;1835:44756;;;8277:1;;;;;;;41350:69;;39623:11;41350:69;;;:::i;:::-;;1835:44756;;41368:25;-1:-1:-1;;;;;1835:44756:41;41350:69;;;;;;;;39311:2125;:::o;41350:69::-;;;;;39558:1;41350:69;;;;;;:::i;:::-;;;;;:::i;:::-;;34277:1851::o;41229:3::-;41267:19;;1835:44756;41267:19;;;:::i;:::-;;41248:38;;;;:::i;:::-;;;;;;:::i;:::-;;1835:44756;41189:13;;39602:77;;;;;1586:1:24;;;;;;;;;:::i;:::-;-1:-1:-1;;;250:1:1;;808::23;;;;-1:-1:-1;;;;;;808:1:23;;;1835:44756:41;1586:1:24;;808::23;-1:-1:-1;;;1586:1:24;;;808::23;;;;;;1586::24;;;808::23;1835:44756:41;8277:1;-1:-1:-1;;;;;;8277:1:41;1586::24;;;1835:44756:41;1586:1:24;;:::o;:::-;;;;;;;;;;;;:::i;:::-;1835:44756: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:44756:41;;;;;;;;7820:17:24;7656:247;7820:17;;;;7656:247;7819:42;7820:29;:17;;1835:44756:41;7820:29:24;:::i;:::-;7819:42;:::i;:::-;7875:18;;;1835:44756:41;;;;;;7656:247:24;;;7875:18;7656:247;;;:::i;:::-;;1835:44756:41;;7656:247:24;;;;;;:::i;:::-;1835:44756:41;7990:19:24;;1704:1;1835:44756:41;;8027:28:24;1704:1;8027:28;;;1704:1;-1:-1:-1;;;;;1835:44756:41;;;1704:1:24;8073:22;1835:44756:41;8113:11:24;1835:44756:41;8073:22:24;;;1835:44756:41;;;;;;8113:11:24;;1835:44756:41;-1:-1:-1;;;;;1835:44756:41;;;;8142:17:24;;1835:44756:41;;;7932:241:24;;;7875:18;7932:241;;;:::i;42241:1355:41:-;;;42375:28;1835:44756;;42375:28;:::i;:::-;42466:11;1835:44756;42445:32;;-1:-1:-1;;;;;1835:44756:41;;;42445:32;-1:-1:-1;;;;;1835:44756:41;;42445:32;:77;;6394:42;42445:77;;-1:-1:-1;42579:13:41;-1:-1:-1;42615:3:41;1835:44756;;42594:19;;;;;42652:11;;;;:::i;:::-;8277:1;42703:34;;:43;;:34;;;1835:44756;;;;;;;;25760:15;1835:44756;;;;;;;42703:43;-1:-1:-1;;;;;1835:44756:41;;42764:28;42760:42;;1835:44756;;-1:-1:-1;;;42839:262:41;;;;-1:-1:-1;;;;;1835:44756:41;;;42839:262;;;1835:44756;;;6701:34;;;1835:44756;6701:34;;;1835:44756;;;;6701:34;;;1835:44756;39558:1;6701:34;;;1835:44756;;;;43194:56;;:43;;1835:44756;;42839:262;1835:44756;6701:34;;;42839:262;6701:34;42839:262;42817:284;;;;:::i;:::-;;;;;;:::i;:::-;-1:-1:-1;;;;;;1835:44756:41;;;;;;25760:15;1835:44756;;;;;;;;43194:34;;1835:44756;43194:43;1835:44756;;-1:-1:-1;;;;;;1835:44756:41;;;;43194:56;1835:44756;42579:13;;42760:42;42794:8;;;;1835:44756;42794:8;;;42594:19;;;;;;;43302:32;;;:::i;:::-;43349:13;-1:-1:-1;43364:23:41;;;;;;43471;;43467:123;;42241:1355;:::o;43389:3::-;43427:19;;1835:44756;43427:19;;;:::i;:::-;;43408:38;;;;:::i;:::-;;;;;;:::i;:::-;;1835:44756;43349:13;;42445:77;;;
Swarm Source
ipfs://b6ee7d3d94ce99462617ed99493a6ec9a7f4dfb5fc14f459b5c15d181346632b
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.