0xD8D9E346Ad32D1f56bC5Fc959440D0A3A2118981
Source Code
- Check Previous Balance
Overview
ETH Balance
0 ETH
Token Holdings
ERC-20 Tokens (2)
- MockUSD (mUSD)11 mUSD
- USDC (USDC)1 USDC
More Info
ContractCreator
0x2cac89AB...4074e1CE5 at txn 0xe6625fa5ab1a59b79c08ed657aa2a96d7c7f6e1ea8a9477ee2124190561fb5f7
Multichain Info
N/A
- Transactions
- Token Transfers (ERC-20)
- Contract
- Events
Latest 10 from a total of 10 transactions
- View Completed Txns
- View Pending Txns
- View Failed Txns
- View Outgoing Txns
- View Incoming Txns
- View Contract Creation
Transaction Hash | Method | Block | From | To | |||||
---|---|---|---|---|---|---|---|---|---|
0x17e7c4645d8b2f9abff134a1be9ca6c798e42363d9c5faf4307965b12908562a | Send Request | 6000213 | 64 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.00937324 | |
0x4d29112fae1f82cbf48d521ce545d1fafa0b508893aef19861629ee1460e2c0a | Send Request | 6000201 | 64 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.00868242 | |
0x64ed06bc74a7f7c9ad0eeb290834b35d7d5cd7120f8341dddb49aabb19f511d3 | Perform Upkeep | 5998844 | 64 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.02016932 | |
0xf3ed06dca7d4b50e9fd6b0759c90bb44f63993f32bcf415d8889c5a6f02cbeb3 | Perform Upkeep | 5997602 | 64 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.00432452 | |
0x552772ca0970867a358e1901b8d67e0116afaf893320e17e45775eee585ab3fa | Purchase Subscri... | 5994280 | 65 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.01577278 | |
0x1abe6cccc213c140ece83036a9cb5291837b7aabd7c9501bb0c7be7a2404518b | Send Request | 5994211 | 65 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.00868485 | |
0x97b2663b288c59279b007a46643b1e6ea48aa6661c991ec1256c6e2c09411902 | Send Request | 5994182 | 65 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.01017669 | |
0x4c944ab3a576892aea36f48a58448561a067898894ef382a758664f0f5b8d5a6 | Update Model | 5993921 | 65 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.00221192 | |
0x7f5de564879f56e4314135f4d15985f682765e583bee297f437d5787a94db763 | Update Batch Mod... | 5991925 | 65 days ago | 0x2cac89AB...4074e1CE5 | IN | 0xD8D9E346...3A2118981 | 0 ETH | 0.03539151 | |
0xe6625fa5ab1a59b79c08ed657aa2a96d7c7f6e1ea8a9477ee2124190561fb5f7 | 0x60c06040 | 5991815 | 65 days ago | 0x2cac89AB...4074e1CE5 | IN | Create: NFTMarketplaceAutomation | 0 ETH | 0.12931632 |
Loading...
Loading
- Code
- Read Contract
- Write Contract
Contract Source Code Verified (Exact Match)
Contract Name:
NFTMarketplaceAutomation
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
- Similar
- Sol2Uml
- Submit Audit
- Compare
File 1 of 36 : Marketplace-Chainlink-Automation.sol
// SPDX-License-Identifier: MITpragma solidity 0.8.20;import "@openzeppelin/contracts/token/ERC20/IERC20.sol";import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";import "@openzeppelin/contracts/access/Ownable.sol";import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";import {CCIPReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol";import {AutomationCompatibleInterface} from "@chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol";import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";import {FunctionsClient} from "@chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol";import {FunctionsRequest} from "@chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol";import "./BlockTeaseNfts.sol";contract NFTMarketplaceAutomation is CCIPReceiver, ReentrancyGuard, Ownable, AutomationCompatibleInterface, FunctionsClient { using FunctionsRequest for FunctionsRequest.Request; bytes32 public s_lastRequestId; bytes public s_lastResponse; bytes public s_lastError; string public lastConfirmationMsg; error UnexpectedRequestID(bytes32 requestId); event UnexpectedRequestIDError(bytes32 indexed requestId); event DecodingFailed(bytes32 indexed requestId); event ResponseError(bytes32 indexed requestId, bytes err); event Response(bytes32 indexed requestId, string response, bytes err); address router = 0xb83E47C2bC239B3bf370bc41e1459A34b41238D0; string source = "const walletAddress = args[0];" "const tokenId = args[1];" "const url = `https://chainlink-ntfn-service-blocktease.onrender.com/send-email`;" "console.log(`HTTP GET Request to ${url}?wallet_address=${walletAddress}&tokenId=${tokenId}`);" "const emailRequest = Functions.makeHttpRequest({" " url: url," " headers: {" " 'Content-Type': 'application/json'," " }," " timeout: 9000," " params: {" " wallet_address: walletAddress," " tokenId: tokenId," " }," "});" "const emailResponse = await emailRequest;" "console.log(`Email sent successfully to wallet address ${walletAddress} with tokenId ${tokenId}`);" "return Functions.encodeString(`Email sent successfully to wallet address ${walletAddress} with tokenId ${tokenId}`);"; uint32 gasLimit = 300_000; bytes32 donID = 0x66756e2d657468657265756d2d7365706f6c69612d3100000000000000000000; BlockTeaseNFTs private nftContract; IERC20 public paymentToken; AggregatorV3Interface public priceFeed; struct Model { uint256 priceUSD; address associatedAddress; uint256 royaltyFees; uint256 duration; } struct Subscription { uint256 tokenId; uint256 expirationTime; uint256 modelId; address owner; bool paused; uint8 ntfnAttempts; } struct Listing { uint256 tokenId; uint256 price; address seller; bool isListed; } uint256[] public subscriptions; mapping(uint256 => Subscription) public tokenIdToSubscription; mapping(uint256 => Model) public models; mapping(uint256 => Listing) public listings; uint256 public listingId; event SubscriptionPurchased(address indexed buyer, uint256 modelId, uint256 subscriptionId, uint256 tokenId); event ModelUpdated(uint256 modelId, uint256 priceUSD, address associatedAddress, uint256 royaltyFee, uint256 duration); event NFTListed(uint256 indexed listingId, uint256 indexed tokenId, uint256 price, address indexed seller); event NFTSold(uint256 indexed listingId, uint256 indexed tokenId, uint256 price, address indexed buyer); constructor(address _priceFeedAddress, address _routerCrossChain, address _nftContract, address _paymentToken) Ownable(msg.sender) CCIPReceiver(_routerCrossChain) FunctionsClient(router) { nftContract = BlockTeaseNFTs(_nftContract); paymentToken = IERC20(_paymentToken); priceFeed = AggregatorV3Interface(_priceFeedAddress); listingId = 1; } function _ccipReceive(Client.Any2EVMMessage memory message) internal override { (uint256 modelId, uint256 subscriptionId, address user, uint256 duration) = abi.decode(message.data, (uint256, uint256, address, uint256)); Model memory model = models[modelId]; uint256 tokenId = nftContract._encodeTokenId(modelId, subscriptionId); nftContract.mint(user, modelId, subscriptionId, 1, model.duration, model.royaltyFees, model.associatedAddress, ""); subscriptions.push(tokenId); tokenIdToSubscription[tokenId] = Subscription(tokenId, block.timestamp + model.duration, modelId, user, false, 0); emit SubscriptionPurchased(user, modelId, subscriptionId, tokenId); } function updateModel(uint256 modelId, uint256 priceUSD, address associatedAddress, uint256 royaltyFee, uint256 duration) public onlyOwner { models[modelId] = Model(priceUSD, associatedAddress, royaltyFee, duration); emit ModelUpdated(modelId, priceUSD, associatedAddress, royaltyFee, duration); } function updateBatchModels(uint256[] memory modelIds, uint256[] memory pricesUSD, address[] memory associatedAddresses, uint256[] memory royaltyFees, uint256[] memory durations) public onlyOwner { require(modelIds.length == pricesUSD.length, "Array length mismatch"); require(pricesUSD.length == associatedAddresses.length, "Array length mismatch"); require(associatedAddresses.length == royaltyFees.length, "Array length mismatch"); require(royaltyFees.length == durations.length, "Array length mismatch"); for (uint256 i = 0; i < modelIds.length; i++) { models[modelIds[i]] = Model(pricesUSD[i], associatedAddresses[i], royaltyFees[i], durations[i]); emit ModelUpdated(modelIds[i], pricesUSD[i], associatedAddresses[i], royaltyFees[i], durations[i]); } } function checkUpkeep(bytes calldata) external view override returns (bool upkeepNeeded, bytes memory performData) { uint256[] memory expiredTokenIds = new uint256[](subscriptions.length); uint256 counter = 0; for (uint256 i = 0; i < subscriptions.length; i++) { uint256 tokenId = subscriptions[i]; Subscription memory subscription = tokenIdToSubscription[tokenId]; if (subscription.expirationTime <= block.timestamp && !subscription.paused) { expiredTokenIds[counter] = tokenId; counter++; } } upkeepNeeded = counter > 0; assembly { mstore(expiredTokenIds, counter) } performData = abi.encode(expiredTokenIds); return (upkeepNeeded, performData); } function performUpkeep(bytes calldata performData) external override { uint256[] memory expiredTokenIds = abi.decode(performData, (uint256[])); for (uint256 i = 0; i < expiredTokenIds.length; i++) { uint256 tokenId = expiredTokenIds[i]; Subscription storage subscription = tokenIdToSubscription[tokenId]; Model memory model = models[subscription.modelId]; if (paymentToken.balanceOf(subscription.owner) >= model.priceUSD && paymentToken.allowance(subscription.owner, address(this)) >= model.priceUSD) { require(paymentToken.transferFrom(subscription.owner, address(this), model.priceUSD)); subscription.expirationTime = block.timestamp + model.duration; subscription.ntfnAttempts = 0; // Reset failed attempts on successful payment } else { subscription.ntfnAttempts++; if (subscription.ntfnAttempts >= 2) { subscription.paused = true; } string[] memory args = new string[](2); args[0] = toAsciiString(subscription.owner); args[1] = uintToString(subscription.tokenId); sendRequest(2825, args); } } } function listNft(uint256 tokenId, uint256 price) external { Subscription memory subscription = tokenIdToSubscription[tokenId]; require(subscription.owner == msg.sender, "Only the owner can list this NFT"); require(!subscription.paused, "Paused subscriptions cannot be listed"); listings[listingId] = Listing(tokenId, price, msg.sender, true); emit NFTListed(listingId, tokenId, price, msg.sender); listingId++; } function buyNft(uint256 _listingId) external nonReentrant { Listing storage listing = listings[_listingId]; require(listing.isListed, "NFT not listed for sale"); require(paymentToken.balanceOf(msg.sender) >= listing.price, "Insufficient balance"); require(paymentToken.allowance(msg.sender, address(this)) >= listing.price, "Insufficient allowance"); Subscription storage subscription = tokenIdToSubscription[listing.tokenId]; require(paymentToken.transferFrom(msg.sender, listing.seller, listing.price)); nftContract.safeTransferFrom(subscription.owner, msg.sender, subscription.tokenId, 1, ""); subscription.owner = msg.sender; listing.isListed = false; emit NFTSold(_listingId, listing.tokenId, listing.price, msg.sender); } function sendRequest(uint64 subscriptionId, string[] memory args) public returns (bytes32 requestId) { FunctionsRequest.Request memory req; req.initializeRequestForInlineJavaScript(source); if (args.length > 0) req.setArgs(args); s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, gasLimit, donID); return s_lastRequestId; } function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { if (s_lastRequestId != requestId) { emit Response(requestId, string(response), err); return; } s_lastResponse = response; s_lastError = err; lastConfirmationMsg = string(response); emit Response(requestId, lastConfirmationMsg, s_lastError); } function purchaseSubscription(uint256 modelId, uint256 subscriptionId) public nonReentrant { Model memory model = models[modelId]; require(paymentToken.transferFrom(msg.sender, address(this), model.priceUSD), "Payment failed"); uint256 tokenId = nftContract._encodeTokenId(modelId, subscriptionId); nftContract.mint(msg.sender, modelId, subscriptionId, 1, model.duration, model.royaltyFees, model.associatedAddress, ""); subscriptions.push(tokenId); tokenIdToSubscription[tokenId] = Subscription(tokenId, block.timestamp + model.duration, modelId, msg.sender, false, 0); emit SubscriptionPurchased(msg.sender, modelId, subscriptionId, tokenId); } function updatePaymentToken(address newPaymentTokenAddress) public onlyOwner { require(newPaymentTokenAddress != address(0), "Invalid address"); paymentToken = IERC20(newPaymentTokenAddress); } function toAsciiString(address x) internal pure returns (string memory) { bytes memory s = new bytes(40); for (uint i = 0; i < 20; i++) { bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i))))); bytes1 hi = bytes1(uint8(b) / 16); bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); s[2*i] = char(hi); s[2*i+1] = char(lo); } return string(s); } function char(bytes1 b) internal pure returns (bytes1 c) { if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); else return bytes1(uint8(b) + 0x57); } function uintToString(uint v) internal pure returns (string memory) { if (v == 0) { return "0"; } uint j = v; uint length; while (j != 0) { length++; j /= 10; } bytes memory bstr = new bytes(length); uint k = length; while (v != 0) { k = k - 1; uint8 temp = (48 + uint8(v - v / 10 * 10)); bytes1 b1 = bytes1(temp); bstr[k] = b1; v /= 10; } return string(bstr); }}
File 2 of 36 : BlockTeaseNfts.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.20;import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";import "@openzeppelin/contracts/access/AccessControl.sol";import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";import "@openzeppelin/contracts/interfaces/IERC2981.sol";import "@openzeppelin/contracts/utils/Strings.sol";contract BlockTeaseNFTs is ERC1155, AccessControl, ERC1155Burnable, IERC2981 { using Strings for uint256; bytes32 public constant URI_SETTER_ROLE = keccak256("URI_SETTER_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); // Nested mapping to store expiration times for each token ID mapping(uint256 => uint256) public expirationTimes; // tokenId => expirationTime mapping(uint256 => address) public _royaltyReceivers; mapping(uint256 => uint256) public _royaltyFees; // basis points (e.g., 500 for 5%) constructor(address defaultAdmin, address minter) ERC1155("") { _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin); _grantRole(MINTER_ROLE, minter); _grantRole(URI_SETTER_ROLE, defaultAdmin); } function _setRoyaltyInfo(uint256 tokenId, address receiver, uint256 feeBasisPoints) private { _royaltyReceivers[tokenId] = receiver; _royaltyFees[tokenId] = feeBasisPoints; } function royaltyInfo(uint256 tokenId, uint256 salePrice) external view override returns (address receiver, uint256 royaltyAmount) { receiver = _royaltyReceivers[tokenId]; royaltyAmount = (salePrice * _royaltyFees[tokenId]) / 10000; } function setURI(string memory newuri) public onlyRole(URI_SETTER_ROLE) { _setURI(newuri); } function mint(address account, uint256 modelId, uint256 subscriptionId, uint256 amount, uint256 duration, uint256 royaltyFee, address royaltyReceiver, bytes memory data) public onlyRole(MINTER_ROLE) { uint256 tokenId = _encodeTokenId(modelId, subscriptionId); _mint(account, tokenId, amount, data); expirationTimes[tokenId] = block.timestamp + duration; _setRoyaltyInfo(tokenId, royaltyReceiver, royaltyFee); } function uri(uint256 tokenId) override public view returns (string memory) { require(expirationTimes[tokenId] > block.timestamp, "NFT is expired"); (uint256 modelId, ) = _decodeTokenId(tokenId); string memory baseURI = super.uri(0); return string(abi.encodePacked(baseURI, modelId.toString(), ".json")); } function _encodeTokenId(uint256 modelId, uint256 subscriptionId) public pure returns (uint256) { return modelId * 10**18 + subscriptionId; } function _decodeTokenId(uint256 tokenId) public pure returns (uint256 modelId, uint256 subscriptionId) { modelId = tokenId / 10**18; subscriptionId = tokenId % 10**18; } function supportsInterface(bytes4 interfaceId) public view override(ERC1155, AccessControl, IERC165) returns (bool) { return super.supportsInterface(interfaceId); }}
File 3 of 36 : FunctionsRequest.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.19;import {CBOR} from "../../../vendor/solidity-cborutils/v2.0.0/CBOR.sol";/// @title Library for encoding the input data of a Functions request into CBORlibrary FunctionsRequest { using CBOR for CBOR.CBORBuffer; uint16 public constant REQUEST_DATA_VERSION = 1; uint256 internal constant DEFAULT_BUFFER_SIZE = 256; enum Location { Inline, // Provided within the Request Remote, // Hosted through remote location that can be accessed through a provided URL DONHosted // Hosted on the DON's storage } enum CodeLanguage { JavaScript // In future version we may add other languages } struct Request { Location codeLocation; // ════════════╸ The location of the source code that will be executed on each node in the DON Location secretsLocation; // ═════════╸ The location of secrets that will be passed into the source code. *Only Remote secrets are supported CodeLanguage language; // ════════════╸ The coding language that the source code is written in string source; // ════════════════════╸ Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted bytes encryptedSecretsReference; // ══╸ Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) string[] args; // ════════════════════╸ String arguments that will be passed into the source code bytes[] bytesArgs; // ════════════════╸ Bytes arguments that will be passed into the source code } error EmptySource(); error EmptySecrets(); error EmptyArgs(); error NoInlineSecrets(); /// @notice Encodes a Request to CBOR encoded bytes /// @param self The request to encode /// @return CBOR encoded bytes function encodeCBOR(Request memory self) internal pure returns (bytes memory) { CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); buffer.writeString("codeLocation"); buffer.writeUInt256(uint256(self.codeLocation)); buffer.writeString("language"); buffer.writeUInt256(uint256(self.language)); buffer.writeString("source"); buffer.writeString(self.source); if (self.args.length > 0) { buffer.writeString("args"); buffer.startArray(); for (uint256 i = 0; i < self.args.length; ++i) { buffer.writeString(self.args[i]); } buffer.endSequence(); } if (self.encryptedSecretsReference.length > 0) { if (self.secretsLocation == Location.Inline) { revert NoInlineSecrets(); } buffer.writeString("secretsLocation"); buffer.writeUInt256(uint256(self.secretsLocation)); buffer.writeString("secrets"); buffer.writeBytes(self.encryptedSecretsReference); } if (self.bytesArgs.length > 0) { buffer.writeString("bytesArgs"); buffer.startArray(); for (uint256 i = 0; i < self.bytesArgs.length; ++i) { buffer.writeBytes(self.bytesArgs[i]); } buffer.endSequence(); } return buffer.buf.buf; } /// @notice Initializes a Chainlink Functions Request /// @dev Sets the codeLocation and code on the request /// @param self The uninitialized request /// @param codeLocation The user provided source code location /// @param language The programming language of the user code /// @param source The user provided source code or a url function initializeRequest( Request memory self, Location codeLocation, CodeLanguage language, string memory source ) internal pure { if (bytes(source).length == 0) revert EmptySource(); self.codeLocation = codeLocation; self.language = language; self.source = source; } /// @notice Initializes a Chainlink Functions Request /// @dev Simplified version of initializeRequest for PoC /// @param self The uninitialized request /// @param javaScriptSource The user provided JS code (must not be empty) function initializeRequestForInlineJavaScript(Request memory self, string memory javaScriptSource) internal pure { initializeRequest(self, Location.Inline, CodeLanguage.JavaScript, javaScriptSource); } /// @notice Adds Remote user encrypted secrets to a Request /// @param self The initialized request /// @param encryptedSecretsReference Encrypted comma-separated string of URLs pointing to off-chain secrets function addSecretsReference(Request memory self, bytes memory encryptedSecretsReference) internal pure { if (encryptedSecretsReference.length == 0) revert EmptySecrets(); self.secretsLocation = Location.Remote; self.encryptedSecretsReference = encryptedSecretsReference; } /// @notice Adds DON-hosted secrets reference to a Request /// @param self The initialized request /// @param slotID Slot ID of the user's secrets hosted on DON /// @param version User data version (for the slotID) function addDONHostedSecrets(Request memory self, uint8 slotID, uint64 version) internal pure { CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); buffer.writeString("slotID"); buffer.writeUInt64(slotID); buffer.writeString("version"); buffer.writeUInt64(version); self.secretsLocation = Location.DONHosted; self.encryptedSecretsReference = buffer.buf.buf; } /// @notice Sets args for the user run function /// @param self The initialized request /// @param args The array of string args (must not be empty) function setArgs(Request memory self, string[] memory args) internal pure { if (args.length == 0) revert EmptyArgs(); self.args = args; } /// @notice Sets bytes args for the user run function /// @param self The initialized request /// @param args The array of bytes args (must not be empty) function setBytesArgs(Request memory self, bytes[] memory args) internal pure { if (args.length == 0) revert EmptyArgs(); self.bytesArgs = args; }}
File 4 of 36 : FunctionsClient.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.19;import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol";import {IFunctionsClient} from "./interfaces/IFunctionsClient.sol";import {FunctionsRequest} from "./libraries/FunctionsRequest.sol";/// @title The Chainlink Functions client contract/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requestsabstract contract FunctionsClient is IFunctionsClient { using FunctionsRequest for FunctionsRequest.Request; IFunctionsRouter internal immutable i_router; event RequestSent(bytes32 indexed id); event RequestFulfilled(bytes32 indexed id); error OnlyRouterCanFulfill(); constructor(address router) { i_router = IFunctionsRouter(router); } /// @notice Sends a Chainlink Functions request /// @param data The CBOR encoded bytes data for a Functions request /// @param subscriptionId The subscription ID that will be charged to service the request /// @param callbackGasLimit the amount of gas that will be available for the fulfillment callback /// @return requestId The generated request ID for this request function _sendRequest( bytes memory data, uint64 subscriptionId, uint32 callbackGasLimit, bytes32 donId ) internal returns (bytes32) { bytes32 requestId = i_router.sendRequest( subscriptionId, data, FunctionsRequest.REQUEST_DATA_VERSION, callbackGasLimit, donId ); emit RequestSent(requestId); return requestId; } /// @notice User defined function to handle a response from the DON /// @param requestId The request ID, returned by sendRequest() /// @param response Aggregated response from the execution of the user's source code /// @param err Aggregated error from the execution of the user code or from the execution pipeline /// @dev Either response or error parameter will be set, but never both function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual; /// @inheritdoc IFunctionsClient function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override { if (msg.sender != address(i_router)) { revert OnlyRouterCanFulfill(); } fulfillRequest(requestId, response, err); emit RequestFulfilled(requestId); }}
File 5 of 36 : AggregatorV3Interface.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData( uint80 _roundId ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);}
File 6 of 36 : AutomationCompatibleInterface.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;// solhint-disable-next-line interface-starts-with-iinterface AutomationCompatibleInterface { /** * @notice method that is simulated by the keepers to see if any work actually * needs to be performed. This method does does not actually need to be * executable, and since it is only ever simulated it can consume lots of gas. * @dev To ensure that it is never called, you may want to add the * cannotExecute modifier from KeeperBase to your implementation of this * method. * @param checkData specified in the upkeep registration so it is always the * same for a registered upkeep. This can easily be broken down into specific * arguments using `abi.decode`, so multiple upkeeps can be registered on the * same contract and easily differentiated by the contract. * @return upkeepNeeded boolean to indicate whether the keeper should call * performUpkeep or not. * @return performData bytes that the keeper should call performUpkeep with, if * upkeep is needed. If you would like to encode data to decode later, try * `abi.encode`. */ function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); /** * @notice method that is actually executed by the keepers, via the registry. * The data returned by the checkUpkeep simulation will be passed into * this method to actually be executed. * @dev The input to this method should not be trusted, and the caller of the * method should not even be restricted to any single registry. Anyone should * be able call it, and the input should be validated, there is no guarantee * that the data passed in is the performData returned from checkUpkeep. This * could happen due to malicious keepers, racing keepers, or simply a state * change while the performUpkeep transaction is waiting for confirmation. * Always validate the data passed in. * @param performData is the data which was passed back from the checkData * simulation. If it is encoded, it can easily be decoded into other types by * calling `abi.decode`. This data should not be trusted, and should be * validated against the contract's current state. */ function performUpkeep(bytes calldata performData) external;}
File 7 of 36 : CCIPReceiver.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol";import {Client} from "../libraries/Client.sol";import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol";/// @title CCIPReceiver - Base contract for CCIP applications that can receive messages.abstract contract CCIPReceiver is IAny2EVMMessageReceiver, IERC165 { address internal immutable i_ccipRouter; constructor(address router) { if (router == address(0)) revert InvalidRouter(address(0)); i_ccipRouter = router; } /// @notice IERC165 supports an interfaceId /// @param interfaceId The interfaceId to check /// @return true if the interfaceId is supported /// @dev Should indicate whether the contract implements IAny2EVMMessageReceiver /// e.g. return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId /// This allows CCIP to check if ccipReceive is available before calling it. /// If this returns false or reverts, only tokens are transferred to the receiver. /// If this returns true, tokens are transferred and ccipReceive is called atomically. /// Additionally, if the receiver address does not have code associated with /// it at the time of execution (EXTCODESIZE returns 0), only tokens will be transferred. function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } /// @inheritdoc IAny2EVMMessageReceiver function ccipReceive(Client.Any2EVMMessage calldata message) external virtual override onlyRouter { _ccipReceive(message); } /// @notice Override this function in your implementation. /// @param message Any2EVMMessage function _ccipReceive(Client.Any2EVMMessage memory message) internal virtual; ///////////////////////////////////////////////////////////////////// // Plumbing ///////////////////////////////////////////////////////////////////// /// @notice Return the current router /// @return CCIP router address function getRouter() public view returns (address) { return address(i_ccipRouter); } error InvalidRouter(address router); /// @dev only calls from the set router are accepted. modifier onlyRouter() { if (msg.sender != address(i_ccipRouter)) revert InvalidRouter(msg.sender); _; }}
File 8 of 36 : Client.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;// End consumer library.library Client { /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct EVMTokenAmount { address token; // token address on the local chain. uint256 amount; // Amount of tokens. } struct Any2EVMMessage { bytes32 messageId; // MessageId corresponding to ccipSend on source. uint64 sourceChainSelector; // Source chain selector. bytes sender; // abi.decode(sender) if coming from an EVM chain. bytes data; // payload sent in original message. EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation. } // If extraArgs is empty bytes, the default is 200k gas limit. struct EVM2AnyMessage { bytes receiver; // abi.encode(receiver address) for dest EVM chains bytes data; // Data payload EVMTokenAmount[] tokenAmounts; // Token transfers address feeToken; // Address of feeToken. address(0) means you will send msg.value. bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1) } // bytes4(keccak256("CCIP EVMExtraArgsV1")); bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; struct EVMExtraArgsV1 { uint256 gasLimit; } function _argsToBytes(EVMExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); }}
File 9 of 36 : IRouterClient.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import {Client} from "../libraries/Client.sol";interface IRouterClient { error UnsupportedDestinationChain(uint64 destChainSelector); error InsufficientFeeTokenAmount(); error InvalidMsgValue(); /// @notice Checks if the given chain ID is supported for sending/receiving. /// @param chainSelector The chain to check. /// @return supported is true if it is supported, false if not. function isChainSupported(uint64 chainSelector) external view returns (bool supported); /// @notice Gets a list of all supported tokens which can be sent or received /// to/from a given chain id. /// @param chainSelector The chainSelector. /// @return tokens The addresses of all tokens that are supported. function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory tokens); /// @param destinationChainSelector The destination chainSelector /// @param message The cross-chain CCIP message including data and/or tokens /// @return fee returns execution fee for the message /// delivery to destination chain, denominated in the feeToken specified in the message. /// @dev Reverts with appropriate reason upon invalid message. function getFee( uint64 destinationChainSelector, Client.EVM2AnyMessage memory message ) external view returns (uint256 fee); /// @notice Request a message to be sent to the destination chain /// @param destinationChainSelector The destination chain ID /// @param message The cross-chain CCIP message including data and/or tokens /// @return messageId The message ID /// @dev Note if msg.value is larger than the required fee (from getFee) we accept /// the overpayment with no refund. /// @dev Reverts with appropriate reason upon invalid message. function ccipSend( uint64 destinationChainSelector, Client.EVM2AnyMessage calldata message ) external payable returns (bytes32);}
File 10 of 36 : Ownable.sol
// 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); }}
File 11 of 36 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)pragma solidity ^0.8.20;/** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be NOT_ENTERED if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail _status = ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; }}
File 12 of 36 : IERC20.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)pragma solidity ^0.8.20;/** * @dev Interface of the ERC20 standard as defined in the EIP. */interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool);}
File 13 of 36 : Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)pragma solidity ^0.8.20;import {Math} from "./math/Math.sol";import {SignedMath} from "./math/SignedMath.sol";/** * @dev String operations. */library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); }}
File 14 of 36 : IERC2981.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)pragma solidity ^0.8.20;import {IERC165} from "../utils/introspection/IERC165.sol";/** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. */interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo( uint256 tokenId, uint256 salePrice ) external view returns (address receiver, uint256 royaltyAmount);}
File 15 of 36 : ERC1155Burnable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Burnable.sol)pragma solidity ^0.8.20;import {ERC1155} from "../ERC1155.sol";/** * @dev Extension of {ERC1155} that allows token holders to destroy both their * own tokens and those that they have been approved to use. */abstract contract ERC1155Burnable is ERC1155 { function burn(address account, uint256 id, uint256 value) public virtual { if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { revert ERC1155MissingApprovalForAll(_msgSender(), account); } _burn(account, id, value); } function burnBatch(address account, uint256[] memory ids, uint256[] memory values) public virtual { if (account != _msgSender() && !isApprovedForAll(account, _msgSender())) { revert ERC1155MissingApprovalForAll(_msgSender(), account); } _burnBatch(account, ids, values); }}
File 16 of 36 : AccessControl.sol
// 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; } }}
File 17 of 36 : ERC1155.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/ERC1155.sol)pragma solidity ^0.8.20;import {IERC1155} from "./IERC1155.sol";import {IERC1155Receiver} from "./IERC1155Receiver.sol";import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol";import {Context} from "../../utils/Context.sol";import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";import {Arrays} from "../../utils/Arrays.sol";import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol";/** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 */abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors { using Arrays for uint256[]; using Arrays for address[]; mapping(uint256 id => mapping(address account => uint256)) private _balances; mapping(address account => mapping(address operator => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256 /* id */) public view virtual returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. */ function balanceOf(address account, uint256 id) public view virtual returns (uint256) { return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] memory accounts, uint256[] memory ids ) public view virtual returns (uint256[] memory) { if (accounts.length != ids.length) { revert ERC1155InvalidArrayLength(ids.length, accounts.length); } uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i)); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeTransferFrom(from, to, id, value, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) public virtual { address sender = _msgSender(); if (from != sender && !isApprovedForAll(from, sender)) { revert ERC1155MissingApprovalForAll(sender, from); } _safeBatchTransferFrom(from, to, ids, values, data); } /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` * (or `to`) is the zero address. * * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. * * Requirements: * * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. * - `ids` and `values` must have the same length. * * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead. */ function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual { if (ids.length != values.length) { revert ERC1155InvalidArrayLength(ids.length, values.length); } address operator = _msgSender(); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids.unsafeMemoryAccess(i); uint256 value = values.unsafeMemoryAccess(i); if (from != address(0)) { uint256 fromBalance = _balances[id][from]; if (fromBalance < value) { revert ERC1155InsufficientBalance(from, fromBalance, value, id); } unchecked { // Overflow not possible: value <= fromBalance _balances[id][from] = fromBalance - value; } } if (to != address(0)) { _balances[id][to] += value; } } if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); emit TransferSingle(operator, from, to, id, value); } else { emit TransferBatch(operator, from, to, ids, values); } } /** * @dev Version of {_update} that performs the token acceptance check by calling * {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it * contains code (eg. is a smart contract at the moment of execution). * * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any * update to the contract state after this function would break the check-effect-interaction pattern. Consider * overriding {_update} instead. */ function _updateWithAcceptanceCheck( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal virtual { _update(from, to, ids, values); if (to != address(0)) { address operator = _msgSender(); if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); _doSafeTransferAcceptanceCheck(operator, from, to, id, value, data); } else { _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, values, data); } } } /** * @dev Transfers a `value` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. * - `ids` and `values` must have the same length. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, to, ids, values, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the values in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `values` must have the same length. * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } _updateWithAcceptanceCheck(address(0), to, ids, values, data); } /** * @dev Destroys a `value` amount of tokens of type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. */ function _burn(address from, uint256 id, uint256 value) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `value` amount of tokens of type `id`. * - `ids` and `values` must have the same length. */ function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } _updateWithAcceptanceCheck(from, address(0), ids, values, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the zero address. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC1155InvalidOperator(address(0)); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Performs an acceptance check by calling {IERC1155-onERC1155Received} on the `to` address * if it contains code at the moment of execution. */ function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 value, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { // Tokens rejected revert ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Performs a batch acceptance check by calling {IERC1155-onERC1155BatchReceived} on the `to` address * if it contains code at the moment of execution. */ function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data ) private { if (to.code.length > 0) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { // Tokens rejected revert ERC1155InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-ERC1155Receiver implementer revert ERC1155InvalidReceiver(to); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } } /** * @dev Creates an array in memory with only one value for each of the elements provided. */ function _asSingletonArrays( uint256 element1, uint256 element2 ) private pure returns (uint256[] memory array1, uint256[] memory array2) { /// @solidity memory-safe-assembly assembly { // Load the free memory pointer array1 := mload(0x40) // Set array length to 1 mstore(array1, 1) // Store the single element at the next word after the length (where content starts) mstore(add(array1, 0x20), element1) // Repeat for next array locating it right after the first array array2 := add(array1, 0x40) mstore(array2, 1) mstore(add(array2, 0x20), element2) // Update the free memory pointer by pointing after the second array mstore(0x40, add(array2, 0x40)) } }}
File 18 of 36 : Context.sol
// 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; }}
File 19 of 36 : CBOR.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.4;import "../../@ensdomains/buffer/v0.1.0/Buffer.sol";/*** @dev A library for populating CBOR encoded payload in Solidity.** https://datatracker.ietf.org/doc/html/rfc7049** The library offers various write* and start* methods to encode values of different types.* The resulted buffer can be obtained with data() method.* Encoding of primitive types is staightforward, whereas encoding of sequences can result* in an invalid CBOR if start/write/end flow is violated.* For the purpose of gas saving, the library does not verify start/write/end flow internally,* except for nested start/end pairs.*/library CBOR { using Buffer for Buffer.buffer; struct CBORBuffer { Buffer.buffer buf; uint256 depth; } uint8 private constant MAJOR_TYPE_INT = 0; uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; uint8 private constant MAJOR_TYPE_BYTES = 2; uint8 private constant MAJOR_TYPE_STRING = 3; uint8 private constant MAJOR_TYPE_ARRAY = 4; uint8 private constant MAJOR_TYPE_MAP = 5; uint8 private constant MAJOR_TYPE_TAG = 6; uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; uint8 private constant TAG_TYPE_BIGNUM = 2; uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; uint8 private constant CBOR_FALSE = 20; uint8 private constant CBOR_TRUE = 21; uint8 private constant CBOR_NULL = 22; uint8 private constant CBOR_UNDEFINED = 23; function create(uint256 capacity) internal pure returns(CBORBuffer memory cbor) { Buffer.init(cbor.buf, capacity); cbor.depth = 0; return cbor; } function data(CBORBuffer memory buf) internal pure returns(bytes memory) { require(buf.depth == 0, "Invalid CBOR"); return buf.buf.buf; } function writeUInt256(CBORBuffer memory buf, uint256 value) internal pure { buf.buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); writeBytes(buf, abi.encode(value)); } function writeInt256(CBORBuffer memory buf, int256 value) internal pure { if (value < 0) { buf.buf.appendUint8( uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM) ); writeBytes(buf, abi.encode(uint256(-1 - value))); } else { writeUInt256(buf, uint256(value)); } } function writeUInt64(CBORBuffer memory buf, uint64 value) internal pure { writeFixedNumeric(buf, MAJOR_TYPE_INT, value); } function writeInt64(CBORBuffer memory buf, int64 value) internal pure { if(value >= 0) { writeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); } else{ writeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(-1 - value)); } } function writeBytes(CBORBuffer memory buf, bytes memory value) internal pure { writeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); buf.buf.append(value); } function writeString(CBORBuffer memory buf, string memory value) internal pure { writeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); buf.buf.append(bytes(value)); } function writeBool(CBORBuffer memory buf, bool value) internal pure { writeContentFree(buf, value ? CBOR_TRUE : CBOR_FALSE); } function writeNull(CBORBuffer memory buf) internal pure { writeContentFree(buf, CBOR_NULL); } function writeUndefined(CBORBuffer memory buf) internal pure { writeContentFree(buf, CBOR_UNDEFINED); } function startArray(CBORBuffer memory buf) internal pure { writeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); buf.depth += 1; } function startFixedArray(CBORBuffer memory buf, uint64 length) internal pure { writeDefiniteLengthType(buf, MAJOR_TYPE_ARRAY, length); } function startMap(CBORBuffer memory buf) internal pure { writeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); buf.depth += 1; } function startFixedMap(CBORBuffer memory buf, uint64 length) internal pure { writeDefiniteLengthType(buf, MAJOR_TYPE_MAP, length); } function endSequence(CBORBuffer memory buf) internal pure { writeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); buf.depth -= 1; } function writeKVString(CBORBuffer memory buf, string memory key, string memory value) internal pure { writeString(buf, key); writeString(buf, value); } function writeKVBytes(CBORBuffer memory buf, string memory key, bytes memory value) internal pure { writeString(buf, key); writeBytes(buf, value); } function writeKVUInt256(CBORBuffer memory buf, string memory key, uint256 value) internal pure { writeString(buf, key); writeUInt256(buf, value); } function writeKVInt256(CBORBuffer memory buf, string memory key, int256 value) internal pure { writeString(buf, key); writeInt256(buf, value); } function writeKVUInt64(CBORBuffer memory buf, string memory key, uint64 value) internal pure { writeString(buf, key); writeUInt64(buf, value); } function writeKVInt64(CBORBuffer memory buf, string memory key, int64 value) internal pure { writeString(buf, key); writeInt64(buf, value); } function writeKVBool(CBORBuffer memory buf, string memory key, bool value) internal pure { writeString(buf, key); writeBool(buf, value); } function writeKVNull(CBORBuffer memory buf, string memory key) internal pure { writeString(buf, key); writeNull(buf); } function writeKVUndefined(CBORBuffer memory buf, string memory key) internal pure { writeString(buf, key); writeUndefined(buf); } function writeKVMap(CBORBuffer memory buf, string memory key) internal pure { writeString(buf, key); startMap(buf); } function writeKVArray(CBORBuffer memory buf, string memory key) internal pure { writeString(buf, key); startArray(buf); } function writeFixedNumeric( CBORBuffer memory buf, uint8 major, uint64 value ) private pure { if (value <= 23) { buf.buf.appendUint8(uint8((major << 5) | value)); } else if (value <= 0xFF) { buf.buf.appendUint8(uint8((major << 5) | 24)); buf.buf.appendInt(value, 1); } else if (value <= 0xFFFF) { buf.buf.appendUint8(uint8((major << 5) | 25)); buf.buf.appendInt(value, 2); } else if (value <= 0xFFFFFFFF) { buf.buf.appendUint8(uint8((major << 5) | 26)); buf.buf.appendInt(value, 4); } else { buf.buf.appendUint8(uint8((major << 5) | 27)); buf.buf.appendInt(value, 8); } } function writeIndefiniteLengthType(CBORBuffer memory buf, uint8 major) private pure { buf.buf.appendUint8(uint8((major << 5) | 31)); } function writeDefiniteLengthType(CBORBuffer memory buf, uint8 major, uint64 length) private pure { writeFixedNumeric(buf, major, length); } function writeContentFree(CBORBuffer memory buf, uint8 value) private pure { buf.buf.appendUint8(uint8((MAJOR_TYPE_CONTENT_FREE << 5) | value)); }}
File 20 of 36 : IFunctionsClient.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.19;/// @title Chainlink Functions client interface.interface IFunctionsClient { /// @notice Chainlink Functions response handler called by the Functions Router /// during fullilment from the designated transmitter node in an OCR round. /// @param requestId The requestId returned by FunctionsClient.sendRequest(). /// @param response Aggregated response from the request's source code. /// @param err Aggregated error either from the request's source code or from the execution pipeline. /// @dev Either response or error parameter will be set, but never both. function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external;}
File 21 of 36 : IFunctionsRouter.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.19;import {FunctionsResponse} from "../libraries/FunctionsResponse.sol";/// @title Chainlink Functions Router interface.interface IFunctionsRouter { /// @notice The identifier of the route to retrieve the address of the access control contract /// The access control contract controls which accounts can manage subscriptions /// @return id - bytes32 id that can be passed to the "getContractById" of the Router function getAllowListId() external view returns (bytes32); /// @notice Set the identifier of the route to retrieve the address of the access control contract /// The access control contract controls which accounts can manage subscriptions function setAllowListId(bytes32 allowListId) external; /// @notice Get the flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network /// @return adminFee function getAdminFee() external view returns (uint72 adminFee); /// @notice Sends a request using the provided subscriptionId /// @param subscriptionId - A unique subscription ID allocated by billing system, /// a client can make requests from different contracts referencing the same subscription /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request /// @param dataVersion - Gas limit for the fulfillment callback /// @param callbackGasLimit - Gas limit for the fulfillment callback /// @param donId - An identifier used to determine which route to send the request along /// @return requestId - A unique request identifier function sendRequest( uint64 subscriptionId, bytes calldata data, uint16 dataVersion, uint32 callbackGasLimit, bytes32 donId ) external returns (bytes32); /// @notice Sends a request to the proposed contracts /// @param subscriptionId - A unique subscription ID allocated by billing system, /// a client can make requests from different contracts referencing the same subscription /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request /// @param dataVersion - Gas limit for the fulfillment callback /// @param callbackGasLimit - Gas limit for the fulfillment callback /// @param donId - An identifier used to determine which route to send the request along /// @return requestId - A unique request identifier function sendRequestToProposed( uint64 subscriptionId, bytes calldata data, uint16 dataVersion, uint32 callbackGasLimit, bytes32 donId ) external returns (bytes32); /// @notice Fulfill the request by: /// - calling back the data that the Oracle returned to the client contract /// - pay the DON for processing the request /// @dev Only callable by the Coordinator contract that is saved in the commitment /// @param response response data from DON consensus /// @param err error from DON consensus /// @param juelsPerGas - current rate of juels/gas /// @param costWithoutFulfillment - The cost of processing the request (in Juels of LINK ), without fulfillment /// @param transmitter - The Node that transmitted the OCR report /// @param commitment - The parameters of the request that must be held consistent between request and response time /// @return fulfillResult - /// @return callbackGasCostJuels - function fulfill( bytes memory response, bytes memory err, uint96 juelsPerGas, uint96 costWithoutFulfillment, address transmitter, FunctionsResponse.Commitment memory commitment ) external returns (FunctionsResponse.FulfillResult, uint96); /// @notice Validate requested gas limit is below the subscription max. /// @param subscriptionId subscription ID /// @param callbackGasLimit desired callback gas limit function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) external view; /// @notice Get the current contract given an ID /// @param id A bytes32 identifier for the route /// @return contract The current contract address function getContractById(bytes32 id) external view returns (address); /// @notice Get the proposed next contract given an ID /// @param id A bytes32 identifier for the route /// @return contract The current or proposed contract address function getProposedContractById(bytes32 id) external view returns (address); /// @notice Return the latest proprosal set /// @return ids The identifiers of the contracts to update /// @return to The addresses of the contracts that will be updated to function getProposedContractSet() external view returns (bytes32[] memory, address[] memory); /// @notice Proposes one or more updates to the contract routes /// @dev Only callable by owner function proposeContractsUpdate(bytes32[] memory proposalSetIds, address[] memory proposalSetAddresses) external; /// @notice Updates the current contract routes to the proposed contracts /// @dev Only callable by owner function updateContracts() external; /// @dev Puts the system into an emergency stopped state. /// @dev Only callable by owner function pause() external; /// @dev Takes the system out of an emergency stopped state. /// @dev Only callable by owner function unpause() external;}
File 22 of 36 : IERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)pragma solidity ^0.8.0;/** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * 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[EIP 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);}
File 23 of 36 : IAny2EVMMessageReceiver.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;import {Client} from "../libraries/Client.sol";/// @notice Application contracts that intend to receive messages from/// the router should implement this interface.interface IAny2EVMMessageReceiver { /// @notice Called by the Router to deliver a message. /// If this reverts, any token transfers also revert. The message /// will move to a FAILED state and become available for manual execution. /// @param message CCIP Message /// @dev Note ensure you check the msg.sender is the OffRampRouter function ccipReceive(Client.Any2EVMMessage calldata message) external;}
File 24 of 36 : SignedMath.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)pragma solidity ^0.8.20;/** * @dev Standard signed math utilities missing in the Solidity language. */library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } }}
File 25 of 36 : Math.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)pragma solidity ^0.8.20;/** * @dev Standard math utilities missing in the Solidity language. */library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; }}
File 26 of 36 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)pragma solidity ^0.8.20;/** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender);}/** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator);}/** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);}
File 27 of 36 : Arrays.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol)pragma solidity ^0.8.20;import {StorageSlot} from "./StorageSlot.sol";import {Math} from "./math/Math.sol";/** * @dev Collection of functions related to array types. */library Arrays { using StorageSlot for bytes32; /** * @dev Searches a sorted `array` and returns the first index that contains * a value greater or equal to `element`. If no such index exists (i.e. all * values in the array are strictly less than `element`), the array length is * returned. Time complexity O(log n). * * `array` is expected to be sorted in ascending order, and to contain no * repeated elements. */ function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = Math.average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeAccess(array, mid).value > element) { high = mid; } else { low = mid + 1; } } // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. if (low > 0 && unsafeAccess(array, low - 1).value == element) { return low - 1; } else { return low; } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getAddressSlot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getBytes32Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) { bytes32 slot; // We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr` // following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays. /// @solidity memory-safe-assembly assembly { mstore(0, arr.slot) slot := add(keccak256(0, 0x20), pos) } return slot.getUint256Slot(); } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } }}
File 28 of 36 : ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.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 ERC165 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; }}
File 29 of 36 : IERC1155MetadataURI.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)pragma solidity ^0.8.20;import {IERC1155} from "../IERC1155.sol";/** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. */interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory);}
File 30 of 36 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol)pragma solidity ^0.8.20;import {IERC165} from "../../utils/introspection/IERC165.sol";/** * @dev Interface that must be implemented by smart contracts in order to receive * ERC-1155 token transfers. */interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4);}
File 31 of 36 : IERC1155.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol)pragma solidity ^0.8.20;import {IERC165} from "../../utils/introspection/IERC165.sol";/** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. */interface IERC1155 is IERC165 { /** * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the value of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments. * * Requirements: * * - `ids` and `values` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external;}
File 32 of 36 : IERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)pragma solidity ^0.8.20;/** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * 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[EIP 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);}
File 33 of 36 : IAccessControl.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)pragma solidity ^0.8.20;/** * @dev External interface of AccessControl declared to support ERC165 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, an admin role * bearer except when using {AccessControl-_setupRole}. */ 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;}
File 34 of 36 : Buffer.sol
// SPDX-License-Identifier: BSD-2-Clausepragma solidity ^0.8.4;/*** @dev A library for working with mutable byte buffers in Solidity.** Byte buffers are mutable and expandable, and provide a variety of primitives* for appending to them. At any time you can fetch a bytes object containing the* current contents of the buffer. The bytes object should not be stored between* operations, as it may change due to resizing of the buffer.*/library Buffer { /** * @dev Represents a mutable buffer. Buffers have a current value (buf) and * a capacity. The capacity may be longer than the current value, in * which case it can be extended without the need to allocate more memory. */ struct buffer { bytes buf; uint capacity; } /** * @dev Initializes a buffer with an initial capacity. * @param buf The buffer to initialize. * @param capacity The number of bytes of space to allocate the buffer. * @return The buffer, for chaining. */ function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) { if (capacity % 32 != 0) { capacity += 32 - (capacity % 32); } // Allocate space for the buffer data buf.capacity = capacity; assembly { let ptr := mload(0x40) mstore(buf, ptr) mstore(ptr, 0) let fpm := add(32, add(ptr, capacity)) if lt(fpm, ptr) { revert(0, 0) } mstore(0x40, fpm) } return buf; } /** * @dev Initializes a new buffer from an existing bytes object. * Changes to the buffer may mutate the original value. * @param b The bytes object to initialize the buffer with. * @return A new buffer. */ function fromBytes(bytes memory b) internal pure returns(buffer memory) { buffer memory buf; buf.buf = b; buf.capacity = b.length; return buf; } function resize(buffer memory buf, uint capacity) private pure { bytes memory oldbuf = buf.buf; init(buf, capacity); append(buf, oldbuf); } /** * @dev Sets buffer length to 0. * @param buf The buffer to truncate. * @return The original buffer, for chaining.. */ function truncate(buffer memory buf) internal pure returns (buffer memory) { assembly { let bufptr := mload(buf) mstore(bufptr, 0) } return buf; } /** * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to copy. * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) { require(len <= data.length); uint off = buf.buf.length; uint newCapacity = off + len; if (newCapacity > buf.capacity) { resize(buf, newCapacity * 2); } uint dest; uint src; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Length of existing buffer data let buflen := mload(bufptr) // Start address = buffer address + offset + sizeof(buffer length) dest := add(add(bufptr, 32), off) // Update buffer length if we're extending it if gt(newCapacity, buflen) { mstore(bufptr, newCapacity) } src := add(data, 32) } // Copy word-length chunks while possible for (; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes unchecked { uint mask = (256 ** (32 - len)) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } return buf; } /** * @dev Appends a byte string to a buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { return append(buf, data, data.length); } /** * @dev Appends a byte to the buffer. Resizes if doing so would exceed the * capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) { uint off = buf.buf.length; uint offPlusOne = off + 1; if (off >= buf.capacity) { resize(buf, offPlusOne * 2); } assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + off let dest := add(add(bufptr, off), 32) mstore8(dest, data) // Update buffer length if we extended it if gt(offPlusOne, mload(bufptr)) { mstore(bufptr, offPlusOne) } } return buf; } /** * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to write (left-aligned). * @return The original buffer, for chaining. */ function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) { uint off = buf.buf.length; uint newCapacity = len + off; if (newCapacity > buf.capacity) { resize(buf, newCapacity * 2); } unchecked { uint mask = (256 ** len) - 1; // Right-align data data = data >> (8 * (32 - len)); assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + newCapacity let dest := add(bufptr, newCapacity) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(newCapacity, mload(bufptr)) { mstore(bufptr, newCapacity) } } } return buf; } /** * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chhaining. */ function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { return append(buf, bytes32(data), 20); } /** * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed * the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @return The original buffer, for chaining. */ function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { return append(buf, data, 32); } /** * @dev Appends a byte to the end of the buffer. Resizes if doing so would * exceed the capacity of the buffer. * @param buf The buffer to append to. * @param data The data to append. * @param len The number of bytes to write (right-aligned). * @return The original buffer. */ function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { uint off = buf.buf.length; uint newCapacity = len + off; if (newCapacity > buf.capacity) { resize(buf, newCapacity * 2); } uint mask = (256 ** len) - 1; assembly { // Memory address of the buffer data let bufptr := mload(buf) // Address = buffer address + sizeof(buffer length) + newCapacity let dest := add(bufptr, newCapacity) mstore(dest, or(and(mload(dest), not(mask)), data)) // Update buffer length if we extended it if gt(newCapacity, mload(bufptr)) { mstore(bufptr, newCapacity) } } return buf; }}
File 35 of 36 : FunctionsResponse.sol
// SPDX-License-Identifier: MITpragma solidity ^0.8.19;/// @title Library of types that are used for fulfillment of a Functions requestlibrary FunctionsResponse { // Used to send request information from the Router to the Coordinator struct RequestMeta { bytes data; // ══════════════════╸ CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request bytes32 flags; // ═══════════════╸ Per-subscription flags address requestingContract; // ══╗ The client contract that is sending the request uint96 availableBalance; // ═════╝ Common LINK balance of the subscription that is controlled by the Router to be used for all consumer requests. uint72 adminFee; // ═════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request uint64 initiatedRequests; // ║ The number of requests that have been started uint32 callbackGasLimit; // ║ The amount of gas that the callback to the consuming contract will be given uint16 dataVersion; // ══════════╝ The version of the structure of the CBOR encoded request data uint64 completedRequests; // ════╗ The number of requests that have successfully completed or timed out address subscriptionOwner; // ═══╝ The owner of the billing subscription } enum FulfillResult { FULFILLED, // 0 USER_CALLBACK_ERROR, // 1 INVALID_REQUEST_ID, // 2 COST_EXCEEDS_COMMITMENT, // 3 INSUFFICIENT_GAS_PROVIDED, // 4 SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION, // 5 INVALID_COMMITMENT // 6 } struct Commitment { bytes32 requestId; // ═════════════════╸ A unique identifier for a Chainlink Functions request address coordinator; // ═══════════════╗ The Coordinator contract that manages the DON that is servicing a request uint96 estimatedTotalCostJuels; // ════╝ The maximum cost in Juels (1e18) of LINK that will be charged to fulfill a request address client; // ════════════════════╗ The client contract that sent the request uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request uint32 callbackGasLimit; // ═══════════╝ The amount of gas that the callback to the consuming contract will be given uint72 adminFee; // ═══════════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network uint72 donFee; // ║ Fee (in Juels of LINK) that will be split between Node Operators for servicing a request uint40 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. uint40 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. uint32 timeoutTimestamp; // ═══════════╝ The timestamp at which a request will be eligible to be timed out }}
File 36 of 36 : StorageSlot.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.pragma solidity ^0.8.20;/** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } }}
Settings
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }}
Contract ABI
- JSON Format
- RAW/Text Format
[{"inputs":[{"internalType":"address","name":"_priceFeedAddress","type":"address"},{"internalType":"address","name":"_routerCrossChain","type":"address"},{"internalType":"address","name":"_nftContract","type":"address"},{"internalType":"address","name":"_paymentToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyArgs","type":"error"},{"inputs":[],"name":"EmptySource","type":"error"},{"inputs":[{"internalType":"address","name":"router","type":"address"}],"name":"InvalidRouter","type":"error"},{"inputs":[],"name":"NoInlineSecrets","type":"error"},{"inputs":[],"name":"OnlyRouterCanFulfill","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":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"UnexpectedRequestID","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"DecodingFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"modelId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceUSD","type":"uint256"},{"indexed":false,"internalType":"address","name":"associatedAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"royaltyFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"ModelUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"listingId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"}],"name":"NFTListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"listingId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"}],"name":"NFTSold","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":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"RequestFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"RequestSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"string","name":"response","type":"string"},{"indexed":false,"internalType":"bytes","name":"err","type":"bytes"}],"name":"Response","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"err","type":"bytes"}],"name":"ResponseError","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"modelId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"subscriptionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"SubscriptionPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"UnexpectedRequestIDError","type":"event"},{"inputs":[{"internalType":"uint256","name":"_listingId","type":"uint256"}],"name":"buyNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"messageId","type":"bytes32"},{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"sender","type":"bytes"},{"internalType":"bytes","name":"data","type":"bytes"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Client.EVMTokenAmount[]","name":"destTokenAmounts","type":"tuple[]"}],"internalType":"struct Client.Any2EVMMessage","name":"message","type":"tuple"}],"name":"ccipReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"bytes","name":"response","type":"bytes"},{"internalType":"bytes","name":"err","type":"bytes"}],"name":"handleOracleFulfillment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastConfirmationMsg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"listNft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"listingId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"listings","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"bool","name":"isListed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"models","outputs":[{"internalType":"uint256","name":"priceUSD","type":"uint256"},{"internalType":"address","name":"associatedAddress","type":"address"},{"internalType":"uint256","name":"royaltyFees","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"modelId","type":"uint256"},{"internalType":"uint256","name":"subscriptionId","type":"uint256"}],"name":"purchaseSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"s_lastError","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_lastRequestId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"s_lastResponse","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"subscriptionId","type":"uint64"},{"internalType":"string[]","name":"args","type":"string[]"}],"name":"sendRequest","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"subscriptions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdToSubscription","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"expirationTime","type":"uint256"},{"internalType":"uint256","name":"modelId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"uint8","name":"ntfnAttempts","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"modelIds","type":"uint256[]"},{"internalType":"uint256[]","name":"pricesUSD","type":"uint256[]"},{"internalType":"address[]","name":"associatedAddresses","type":"address[]"},{"internalType":"uint256[]","name":"royaltyFees","type":"uint256[]"},{"internalType":"uint256[]","name":"durations","type":"uint256[]"}],"name":"updateBatchModels","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"modelId","type":"uint256"},{"internalType":"uint256","name":"priceUSD","type":"uint256"},{"internalType":"address","name":"associatedAddress","type":"address"},{"internalType":"uint256","name":"royaltyFee","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"updateModel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPaymentTokenAddress","type":"address"}],"name":"updatePaymentToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
Decompile Bytecode Switch to Opcodes View
60c060405273b83e47c2bc239b3bf370bc41e1459a34b41238d060065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550604051806102e001604052806102ad8152602001620063bc6102ad91396007908162000085919062000687565b50620493e060085f6101000a81548163ffffffff021916908363ffffffff1602179055507f66756e2d657468657265756d2d7365706f6c69612d31000000000000000000005f1b600955348015620000db575f80fd5b5060405162006669380380620066698339818101604052810190620001019190620007d0565b60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633845f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000198575f6040517fd7f733340000000000000000000000000000000000000000000000000000000081526004016200018f919062000850565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505060015f819055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362000247575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016200023e919062000850565b60405180910390fd5b62000258816200036060201b60201c565b508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff16815250505081600a5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600c5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001601181905550505050506200086b565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200049f57607f821691505b602082108103620004b557620004b46200045a565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302620005197fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620004dc565b620005258683620004dc565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f6200056f6200056962000563846200053d565b62000546565b6200053d565b9050919050565b5f819050919050565b6200058a836200054f565b620005a2620005998262000576565b848454620004e8565b825550505050565b5f90565b620005b8620005aa565b620005c58184846200057f565b505050565b5b81811015620005ec57620005e05f82620005ae565b600181019050620005cb565b5050565b601f8211156200063b576200060581620004bb565b6200061084620004cd565b8101602085101562000620578190505b620006386200062f85620004cd565b830182620005ca565b50505b505050565b5f82821c905092915050565b5f6200065d5f198460080262000640565b1980831691505092915050565b5f6200067783836200064c565b9150826002028217905092915050565b620006928262000423565b67ffffffffffffffff811115620006ae57620006ad6200042d565b5b620006ba825462000487565b620006c7828285620005f0565b5f60209050601f831160018114620006fd575f8415620006e8578287015190505b620006f485826200066a565b86555062000763565b601f1984166200070d86620004bb565b5f5b8281101562000736578489015182556001820191506020850194506020810190506200070f565b8683101562000756578489015162000752601f8916826200064c565b8355505b6001600288020188555050505b505050505050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6200079a826200076f565b9050919050565b620007ac816200078e565b8114620007b7575f80fd5b50565b5f81519050620007ca81620007a1565b92915050565b5f805f8060808587031215620007eb57620007ea6200076b565b5b5f620007fa87828801620007ba565b94505060206200080d87828801620007ba565b93505060406200082087828801620007ba565b92505060606200083387828801620007ba565b91505092959194509250565b6200084a816200078e565b82525050565b5f602082019050620008655f8301846200083f565b92915050565b60805160a051615b216200089b5f395f818161060a0152612c5701525f81816117150152611c340152615b215ff3fe608060405234801561000f575f80fd5b50600436106101a7575f3560e01c8063715018a6116100f7578063b0f479a111610095578063de74e57b1161006f578063de74e57b146104b0578063f2fde38b146104e3578063f529ecbc146104ff578063fe8723e11461051b576101a7565b8063b0f479a114610456578063b1e2174914610474578063d34bcc8d14610492576101a7565b806385572ffb116100d157806385572ffb146103e25780638d1d44a9146103fe5780638da5cb5b1461041a5780639405dfdd14610438576101a7565b8063715018a614610385578063741bef1a1461038f57806375158514146103ad576101a7565b80634585e33b116101645780634ccf1b341161013e5780634ccf1b34146102e95780636a030ca9146103055780636decc218146103385780636e04ff0d14610354576101a7565b80634585e33b1461027f57806348a7d26d1461029b5780634b0795a8146102cb576101a7565b806301ffc9a7146101ab5780630ca76175146101db578063243adbdd146101f75780632d5bbf60146102135780633013ce29146102435780633944ea3a14610261575b5f80fd5b6101c560048036038101906101c09190613957565b610537565b6040516101d2919061399c565b60405180910390f35b6101f560048036038101906101f09190613b24565b610608565b005b610211600480360381019061020c9190613bdf565b6106ca565b005b61022d60048036038101906102289190613bdf565b610b51565b60405161023a9190613c19565b60405180910390f35b61024b610b71565b6040516102589190613cac565b60405180910390f35b610269610b96565b6040516102769190613d3f565b60405180910390f35b61029960048036038101906102949190613dbc565b610c22565b005b6102b560048036038101906102b09190613fc0565b611105565b6040516102c29190614029565b60405180910390f35b6102d36111ff565b6040516102e09190613d3f565b60405180910390f35b61030360048036038101906102fe919061407d565b61128b565b005b61031f600480360381019061031a9190613bdf565b611344565b60405161032f94939291906140b7565b60405180910390f35b610352600480360381019061034d91906140fa565b61138f565b005b61036e60048036038101906103699190613dbc565b61148a565b60405161037c929190614171565b60405180910390f35b61038d61166a565b005b61039761167d565b6040516103a491906141bf565b60405180910390f35b6103c760048036038101906103c29190613bdf565b6116a2565b6040516103d9969594939291906141f3565b60405180910390f35b6103fc60048036038101906103f79190614274565b611713565b005b610418600480360381019061041391906142bb565b6117b8565b005b610422611c03565b60405161042f91906142f9565b60405180910390f35b610440611c2b565b60405161044d9190613c19565b60405180910390f35b61045e611c31565b60405161046b91906142f9565b60405180910390f35b61047c611c58565b6040516104899190614029565b60405180910390f35b61049a611c5e565b6040516104a79190614364565b60405180910390f35b6104ca60048036038101906104c59190613bdf565b611cea565b6040516104da9493929190614384565b60405180910390f35b6104fd60048036038101906104f8919061407d565b611d42565b005b61051960048036038101906105149190614547565b611dc6565b005b610535600480360381019061053091906142bb565b6120f4565b005b5f7f85572ffb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061060157507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461068d576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106988383836123aa565b827f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e660405160405180910390a2505050565b6106d2612464565b5f60105f8381526020019081526020015f2090508060020160149054906101000a900460ff16610737576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072e90614694565b60405180910390fd5b8060010154600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b815260040161079691906142f9565b602060405180830381865afa1580156107b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d591906146c6565b1015610816576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080d9061473b565b60405180910390fd5b8060010154600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401610877929190614759565b602060405180830381865afa158015610892573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b691906146c6565b10156108f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ee906147ca565b60405180910390fd5b5f600e5f835f015481526020019081526020015f209050600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33846002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600101546040518463ffffffff1660e01b8152600401610993939291906147e8565b6020604051808303815f875af11580156109af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109d39190614847565b6109db575f80fd5b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f242432a826003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633845f015460016040518563ffffffff1660e01b8152600401610a6294939291906148ce565b5f604051808303815f87803b158015610a79575f80fd5b505af1158015610a8b573d5f803e3d5ffd5b5050505033816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f8260020160146101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16825f0154847fcbe87ada5f3ee71caed4f1443d212d022ecdd1d72742c75a756c186bc2e4dff88560010154604051610b3c9190613c19565b60405180910390a45050610b4e6124a8565b50565b600d8181548110610b60575f80fd5b905f5260205f20015f915090505481565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60038054610ba390614951565b80601f0160208091040260200160405190810160405280929190818152602001828054610bcf90614951565b8015610c1a5780601f10610bf157610100808354040283529160200191610c1a565b820191905f5260205f20905b815481529060010190602001808311610bfd57829003601f168201915b505050505081565b5f8282810190610c329190614981565b90505f5b81518110156110ff575f828281518110610c5357610c526149c8565b5b602002602001015190505f600e5f8381526020019081526020015f2090505f600f5f836002015481526020019081526020015f206040518060800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820154815250509050805f0151600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401610d8791906142f9565b602060405180830381865afa158015610da2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc691906146c6565b10158015610e945750805f0151600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16306040518363ffffffff1660e01b8152600401610e52929190614759565b602060405180830381865afa158015610e6d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e9191906146c6565b10155b15610f9f57600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1630845f01516040518463ffffffff1660e01b8152600401610f1d939291906147e8565b6020604051808303815f875af1158015610f39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5d9190614847565b610f65575f80fd5b806060015142610f759190614a22565b82600101819055505f8260030160156101000a81548160ff021916908360ff1602179055506110e9565b81600301601581819054906101000a900460ff1680929190610fc090614a55565b91906101000a81548160ff021916908360ff1602179055505060028260030160159054906101000a900460ff1660ff16106110135760018260030160146101000a81548160ff0219169083151502179055505b5f600267ffffffffffffffff81111561102f5761102e613a00565b5b60405190808252806020026020018201604052801561106257816020015b606081526020019060019003908161104d5790505b509050611091836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166124b1565b815f815181106110a4576110a36149c8565b5b60200260200101819052506110bb835f015461266d565b816001815181106110cf576110ce6149c8565b5b60200260200101819052506110e6610b0982611105565b50505b50505080806110f790614a7d565b915050610c36565b50505050565b5f61110e61384a565b6111a96007805461111e90614951565b80601f016020809104026020016040519081016040528092919081815260200182805461114a90614951565b80156111955780601f1061116c57610100808354040283529160200191611195565b820191905f5260205f20905b81548152906001019060200180831161117857829003601f168201915b5050505050826127eb90919063ffffffff16565b5f835111156111c6576111c583826127fb90919063ffffffff16565b5b6111ed6111d282612842565b8560085f9054906101000a900463ffffffff16600954612c53565b60028190555060025491505092915050565b6004805461120c90614951565b80601f016020809104026020016040519081016040528092919081815260200182805461123890614951565b80156112835780601f1061125a57610100808354040283529160200191611283565b820191905f5260205f20905b81548152906001019060200180831161126657829003601f168201915b505050505081565b611293612d32565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611301576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f890614b0e565b60405180910390fd5b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600f602052805f5260405f205f91509050805f015490806001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030154905084565b611397612d32565b60405180608001604052808581526020018473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182815250600f5f8781526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301559050507faa15cd9a715f663de2b0b442585d410be6b8b5538c624d56bbfc0e53bc4252c5858585858560405161147b959493929190614b2c565b60405180910390a15050505050565b5f60605f600d8054905067ffffffffffffffff8111156114ad576114ac613a00565b5b6040519080825280602002602001820160405280156114db5781602001602082028036833780820191505090505b5090505f805b600d80549050811015611636575f600d8281548110611503576115026149c8565b5b905f5260205f20015490505f600e5f8381526020019081526020015f206040518060c00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160149054906101000a900460ff161515151581526020016003820160159054906101000a900460ff1660ff1660ff16815250509050428160200151111580156115ed57508060800151155b156116215781858581518110611606576116056149c8565b5b602002602001018181525050838061161d90614a7d565b9450505b5050808061162e90614a7d565b9150506114e1565b505f81119350808252816040516020016116509190614c34565b604051602081830303815290604052925050509250929050565b611672612d32565b61167b5f612db9565b565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600e602052805f5260405f205f91509050805f015490806001015490806002015490806003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030160149054906101000a900460ff16908060030160159054906101000a900460ff16905086565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146117a357336040517fd7f7333400000000000000000000000000000000000000000000000000000000815260040161179a91906142f9565b60405180910390fd5b6117b5816117b090614e46565b612e7c565b50565b6117c0612464565b5f600f5f8481526020019081526020015f206040518060800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820154815250509050600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330845f01516040518463ffffffff1660e01b81526004016118b2939291906147e8565b6020604051808303815f875af11580156118ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118f29190614847565b611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192890614ea2565b60405180910390fd5b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ab531efd85856040518363ffffffff1660e01b815260040161198e929190614ec0565b602060405180830381865afa1580156119a9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119cd91906146c6565b9050600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389c5b73a33868660018760600151886040015189602001516040518863ffffffff1660e01b8152600401611a429796959493929190614ee7565b5f604051808303815f87803b158015611a59575f80fd5b505af1158015611a6b573d5f803e3d5ffd5b50505050600d81908060018154018082558091505060019003905f5260205f20015f90919091909150556040518060c00160405280828152602001836060015142611ab69190614a22565b81526020018581526020013373ffffffffffffffffffffffffffffffffffffffff1681526020015f151581526020015f60ff16815250600e5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160030160146101000a81548160ff02191690831515021790555060a08201518160030160156101000a81548160ff021916908360ff1602179055509050503373ffffffffffffffffffffffffffffffffffffffff167f64482b8b4ec00191fbaf536ab56bb397d8efc6d86b8c41ca712f144addc7a45a858584604051611bed93929190614f68565b60405180910390a25050611bff6124a8565b5050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60115481565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b60025481565b60058054611c6b90614951565b80601f0160208091040260200160405190810160405280929190818152602001828054611c9790614951565b8015611ce25780601f10611cb957610100808354040283529160200191611ce2565b820191905f5260205f20905b815481529060010190602001808311611cc557829003601f168201915b505050505081565b6010602052805f5260405f205f91509050805f015490806001015490806002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020160149054906101000a900460ff16905084565b611d4a612d32565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611dba575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611db191906142f9565b60405180910390fd5b611dc381612db9565b50565b611dce612d32565b8351855114611e12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0990614fe7565b60405180910390fd5b8251845114611e56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4d90614fe7565b60405180910390fd5b8151835114611e9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9190614fe7565b60405180910390fd5b8051825114611ede576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed590614fe7565b60405180910390fd5b5f5b85518110156120ec576040518060800160405280868381518110611f0757611f066149c8565b5b60200260200101518152602001858381518110611f2757611f266149c8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001848381518110611f5d57611f5c6149c8565b5b60200260200101518152602001838381518110611f7d57611f7c6149c8565b5b6020026020010151815250600f5f888481518110611f9e57611f9d6149c8565b5b602002602001015181526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301559050507faa15cd9a715f663de2b0b442585d410be6b8b5538c624d56bbfc0e53bc4252c586828151811061204c5761204b6149c8565b5b6020026020010151868381518110612067576120666149c8565b5b6020026020010151868481518110612082576120816149c8565b5b602002602001015186858151811061209d5761209c6149c8565b5b60200260200101518686815181106120b8576120b76149c8565b5b60200260200101516040516120d1959493929190614b2c565b60405180910390a180806120e490614a7d565b915050611ee0565b505050505050565b5f600e5f8481526020019081526020015f206040518060c00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160149054906101000a900460ff161515151581526020016003820160159054906101000a900460ff1660ff1660ff168152505090503373ffffffffffffffffffffffffffffffffffffffff16816060015173ffffffffffffffffffffffffffffffffffffffff161461222f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122269061504f565b60405180910390fd5b806080015115612274576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161226b906150dd565b60405180910390fd5b60405180608001604052808481526020018381526020013373ffffffffffffffffffffffffffffffffffffffff1681526020016001151581525060105f60115481526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160146101000a81548160ff0219169083151502179055509050503373ffffffffffffffffffffffffffffffffffffffff16836011547f5fc076273da30f9495a795f70cf6fedc3cec996f6a27ddc637c7e6328e77006d856040516123869190613c19565b60405180910390a460115f8154809291906123a090614a7d565b9190505550505050565b82600254146123f257827f17aac589b115f42ae5c9320ca9eb350d352b376d8c07f7d1b166e9a9b155481b83836040516123e59291906150fb565b60405180910390a261245f565b816003908161240191906152c4565b50806004908161241191906152c4565b50816005908161242191906153eb565b50827f17aac589b115f42ae5c9320ca9eb350d352b376d8c07f7d1b166e9a9b155481b600560046040516124569291906155bc565b60405180910390a25b505050565b60025f540361249f576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550565b60015f81905550565b60605f602867ffffffffffffffff8111156124cf576124ce613a00565b5b6040519080825280601f01601f1916602001820160405280156125015781602001600182028036833780820191505090505b5090505f5b6014811015612663575f81601361251d91906155f1565b60086125299190615624565b60026125359190615794565b8573ffffffffffffffffffffffffffffffffffffffff16612556919061580b565b60f81b90505f60108260f81c61256c919061583b565b60f81b90505f8160f81c6010612582919061586b565b8360f81c61259091906158a7565b60f81b905061259e826131fe565b858560026125ac9190615624565b815181106125bd576125bc6149c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506125f4816131fe565b8560018660026126049190615624565b61260e9190614a22565b8151811061261f5761261e6149c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350505050808061265b90614a7d565b915050612506565b5080915050919050565b60605f82036126b3576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506127e6565b5f8290505f5b5f82146126e25780806126cb90614a7d565b915050600a826126db919061580b565b91506126b9565b5f8167ffffffffffffffff8111156126fd576126fc613a00565b5b6040519080825280601f01601f19166020018201604052801561272f5781602001600182028036833780820191505090505b5090505f8290505b5f86146127de5760018161274b91906155f1565b90505f600a808861275c919061580b565b6127669190615624565b8761277191906155f1565b603061277d91906158db565b90505f8160f81b90508084848151811061279a576127996149c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a886127d5919061580b565b97505050612737565b819450505050505b919050565b6127f7825f8084613243565b5050565b5f815103612835576040517ffe936cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808260a001819052505050565b60605f6128506101006132e9565b905061289a6040518060400160405280600c81526020017f636f64654c6f636174696f6e00000000000000000000000000000000000000008152508261330e90919063ffffffff16565b6128c2835f015160028111156128b3576128b261590f565b5b8261333690919063ffffffff16565b61290a6040518060400160405280600881526020017f6c616e67756167650000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b61293283604001515f8111156129235761292261590f565b5b8261333690919063ffffffff16565b61297a6040518060400160405280600681526020017f736f7572636500000000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b61299183606001518261330e90919063ffffffff16565b5f8360a00151511115612a4b576129e66040518060400160405280600481526020017f61726773000000000000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b6129ef81613385565b5f5b8360a0015151811015612a4057612a2f8460a001518281518110612a1857612a176149c8565b5b60200260200101518361330e90919063ffffffff16565b80612a3990614a7d565b90506129f1565b50612a4a816133ad565b5b5f8360800151511115612b8a575f6002811115612a6b57612a6a61590f565b5b83602001516002811115612a8257612a8161590f565b5b03612ab9576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b016040518060400160405280600f81526020017f736563726574734c6f636174696f6e00000000000000000000000000000000008152508261330e90919063ffffffff16565b612b2a83602001516002811115612b1b57612b1a61590f565b5b8261333690919063ffffffff16565b612b726040518060400160405280600781526020017f73656372657473000000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b612b898360800151826133d590919063ffffffff16565b5b5f8360c00151511115612c4457612bdf6040518060400160405280600981526020017f62797465734172677300000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b612be881613385565b5f5b8360c0015151811015612c3957612c288460c001518281518110612c1157612c106149c8565b5b6020026020010151836133d590919063ffffffff16565b80612c3290614a7d565b9050612bea565b50612c43816133ad565b5b805f01515f0151915050919050565b5f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663461d27628688600188886040518663ffffffff1660e01b8152600401612cb7959493929190615985565b6020604051808303815f875af1158015612cd3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cf791906159f1565b9050807f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db860405160405180910390a280915050949350505050565b612d3a6133fd565b73ffffffffffffffffffffffffffffffffffffffff16612d58611c03565b73ffffffffffffffffffffffffffffffffffffffff1614612db757612d7b6133fd565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612dae91906142f9565b60405180910390fd5b565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f805f808460600151806020019051810190612e989190615a57565b93509350935093505f600f5f8681526020019081526020015f206040518060800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016002820154815260200160038201548152505090505f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ab531efd87876040518363ffffffff1660e01b8152600401612f8e929190614ec0565b602060405180830381865afa158015612fa9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fcd91906146c6565b9050600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389c5b73a85888860018760600151886040015189602001516040518863ffffffff1660e01b81526004016130429796959493929190614ee7565b5f604051808303815f87803b158015613059575f80fd5b505af115801561306b573d5f803e3d5ffd5b50505050600d81908060018154018082558091505060019003905f5260205f20015f90919091909150556040518060c001604052808281526020018360600151426130b69190614a22565b81526020018781526020018573ffffffffffffffffffffffffffffffffffffffff1681526020015f151581526020015f60ff16815250600e5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160030160146101000a81548160ff02191690831515021790555060a08201518160030160156101000a81548160ff021916908360ff1602179055509050508373ffffffffffffffffffffffffffffffffffffffff167f64482b8b4ec00191fbaf536ab56bb397d8efc6d86b8c41ca712f144addc7a45a8787846040516131ed93929190614f68565b60405180910390a250505050505050565b5f600a8260f81c60ff1610156132285760308260f81c61321e91906158db565b60f81b905061323e565b60578260f81c61323891906158db565b60f81b90505b919050565b5f81510361327d576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82845f019060028111156132945761329361590f565b5b908160028111156132a8576132a761590f565b5b815250508184604001905f8111156132c3576132c261590f565b5b90815f8111156132d6576132d561590f565b5b8152505080846060018190525050505050565b6132f16138b9565b6132fe815f015183613404565b505f816020018181525050919050565b61331b826003835161347a565b61333181835f015161361a90919063ffffffff16565b505050565b61335760026005600660ff16901b17835f015161363690919063ffffffff16565b50613381828260405160200161336d9190613c19565b6040516020818303038152906040526133d5565b5050565b61339081600461369d565b6001816020018181516133a39190614a22565b9150818152505050565b6133b881600761369d565b6001816020018181516133cb91906155f1565b9150818152505050565b6133e2826002835161347a565b6133f881835f015161361a90919063ffffffff16565b505050565b5f33905090565b61340c6138d8565b5f60208361341a9190615abb565b146134465760208261342c9190615abb565b602061343891906155f1565b826134439190614a22565b91505b818360200181815250506040518084525f81528281016020018181101561346b575f80fd5b80604052505082905092915050565b60178167ffffffffffffffff16116134b4576134ae8160058460ff16901b60ff1617845f015161363690919063ffffffff16565b50613615565b60ff8167ffffffffffffffff1611613510576134e6601860058460ff16901b17845f015161363690919063ffffffff16565b5061350a8167ffffffffffffffff166001855f01516136c29092919063ffffffff16565b50613614565b61ffff8167ffffffffffffffff161161356d57613543601960058460ff16901b17845f015161363690919063ffffffff16565b506135678167ffffffffffffffff166002855f01516136c29092919063ffffffff16565b50613613565b63ffffffff8167ffffffffffffffff16116135cc576135a2601a60058460ff16901b17845f015161363690919063ffffffff16565b506135c68167ffffffffffffffff166004855f01516136c29092919063ffffffff16565b50613612565b6135ec601b60058460ff16901b17845f015161363690919063ffffffff16565b506136108167ffffffffffffffff166008855f01516136c29092919063ffffffff16565b505b5b5b5b505050565b6136226138d8565b61362e8383845161374b565b905092915050565b61363e6138d8565b5f835f01515190505f6001826136549190614a22565b90508460200151821061367857613677856002836136729190615624565b613828565b5b84516020838201018581538151831115613690578282525b5050849250505092915050565b6136bd601f60058360ff16901b17835f015161363690919063ffffffff16565b505050565b6136ca6138d8565b5f845f01515190505f81846136df9190614a22565b9050856020015181111561370457613703866002836136fe9190615624565b613828565b5b5f6001856101006137159190615794565b61371f91906155f1565b90508651828101878319825116178152815184111561373c578382525b50508693505050509392505050565b6137536138d8565b8251821115613760575f80fd5b5f845f01515190505f83826137759190614a22565b9050856020015181111561379a57613799866002836137949190615624565b613828565b5b5f80875180518560208301019350808511156137b4578482525b60208901925050505b602086106137fb57805182526020826137d69190614a22565b91506020816137e59190614a22565b90506020866137f491906155f1565b95506137bd565b5f6001876020036101000a0390508019825116818451168181178552505050879450505050509392505050565b5f825f015190506138398383613404565b50613844838261361a565b50505050565b6040518060e001604052805f60028111156138685761386761590f565b5b81526020015f60028111156138805761387f61590f565b5b81526020015f808111156138975761389661590f565b5b8152602001606081526020016060815260200160608152602001606081525090565b60405180604001604052806138cc6138d8565b81526020015f81525090565b6040518060400160405280606081526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61393681613902565b8114613940575f80fd5b50565b5f813590506139518161392d565b92915050565b5f6020828403121561396c5761396b6138fa565b5b5f61397984828501613943565b91505092915050565b5f8115159050919050565b61399681613982565b82525050565b5f6020820190506139af5f83018461398d565b92915050565b5f819050919050565b6139c7816139b5565b81146139d1575f80fd5b50565b5f813590506139e2816139be565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613a36826139f0565b810181811067ffffffffffffffff82111715613a5557613a54613a00565b5b80604052505050565b5f613a676138f1565b9050613a738282613a2d565b919050565b5f67ffffffffffffffff821115613a9257613a91613a00565b5b613a9b826139f0565b9050602081019050919050565b828183375f83830152505050565b5f613ac8613ac384613a78565b613a5e565b905082815260208101848484011115613ae457613ae36139ec565b5b613aef848285613aa8565b509392505050565b5f82601f830112613b0b57613b0a6139e8565b5b8135613b1b848260208601613ab6565b91505092915050565b5f805f60608486031215613b3b57613b3a6138fa565b5b5f613b48868287016139d4565b935050602084013567ffffffffffffffff811115613b6957613b686138fe565b5b613b7586828701613af7565b925050604084013567ffffffffffffffff811115613b9657613b956138fe565b5b613ba286828701613af7565b9150509250925092565b5f819050919050565b613bbe81613bac565b8114613bc8575f80fd5b50565b5f81359050613bd981613bb5565b92915050565b5f60208284031215613bf457613bf36138fa565b5b5f613c0184828501613bcb565b91505092915050565b613c1381613bac565b82525050565b5f602082019050613c2c5f830184613c0a565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f613c74613c6f613c6a84613c32565b613c51565b613c32565b9050919050565b5f613c8582613c5a565b9050919050565b5f613c9682613c7b565b9050919050565b613ca681613c8c565b82525050565b5f602082019050613cbf5f830184613c9d565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613cfc578082015181840152602081019050613ce1565b5f8484015250505050565b5f613d1182613cc5565b613d1b8185613ccf565b9350613d2b818560208601613cdf565b613d34816139f0565b840191505092915050565b5f6020820190508181035f830152613d578184613d07565b905092915050565b5f80fd5b5f80fd5b5f8083601f840112613d7c57613d7b6139e8565b5b8235905067ffffffffffffffff811115613d9957613d98613d5f565b5b602083019150836001820283011115613db557613db4613d63565b5b9250929050565b5f8060208385031215613dd257613dd16138fa565b5b5f83013567ffffffffffffffff811115613def57613dee6138fe565b5b613dfb85828601613d67565b92509250509250929050565b5f67ffffffffffffffff82169050919050565b613e2381613e07565b8114613e2d575f80fd5b50565b5f81359050613e3e81613e1a565b92915050565b5f67ffffffffffffffff821115613e5e57613e5d613a00565b5b602082029050602081019050919050565b5f67ffffffffffffffff821115613e8957613e88613a00565b5b613e92826139f0565b9050602081019050919050565b5f613eb1613eac84613e6f565b613a5e565b905082815260208101848484011115613ecd57613ecc6139ec565b5b613ed8848285613aa8565b509392505050565b5f82601f830112613ef457613ef36139e8565b5b8135613f04848260208601613e9f565b91505092915050565b5f613f1f613f1a84613e44565b613a5e565b90508083825260208201905060208402830185811115613f4257613f41613d63565b5b835b81811015613f8957803567ffffffffffffffff811115613f6757613f666139e8565b5b808601613f748982613ee0565b85526020850194505050602081019050613f44565b5050509392505050565b5f82601f830112613fa757613fa66139e8565b5b8135613fb7848260208601613f0d565b91505092915050565b5f8060408385031215613fd657613fd56138fa565b5b5f613fe385828601613e30565b925050602083013567ffffffffffffffff811115614004576140036138fe565b5b61401085828601613f93565b9150509250929050565b614023816139b5565b82525050565b5f60208201905061403c5f83018461401a565b92915050565b5f61404c82613c32565b9050919050565b61405c81614042565b8114614066575f80fd5b50565b5f8135905061407781614053565b92915050565b5f60208284031215614092576140916138fa565b5b5f61409f84828501614069565b91505092915050565b6140b181614042565b82525050565b5f6080820190506140ca5f830187613c0a565b6140d760208301866140a8565b6140e46040830185613c0a565b6140f16060830184613c0a565b95945050505050565b5f805f805f60a08688031215614113576141126138fa565b5b5f61412088828901613bcb565b955050602061413188828901613bcb565b945050604061414288828901614069565b935050606061415388828901613bcb565b925050608061416488828901613bcb565b9150509295509295909350565b5f6040820190506141845f83018561398d565b81810360208301526141968184613d07565b90509392505050565b5f6141a982613c7b565b9050919050565b6141b98161419f565b82525050565b5f6020820190506141d25f8301846141b0565b92915050565b5f60ff82169050919050565b6141ed816141d8565b82525050565b5f60c0820190506142065f830189613c0a565b6142136020830188613c0a565b6142206040830187613c0a565b61422d60608301866140a8565b61423a608083018561398d565b61424760a08301846141e4565b979650505050505050565b5f80fd5b5f60a0828403121561426b5761426a614252565b5b81905092915050565b5f60208284031215614289576142886138fa565b5b5f82013567ffffffffffffffff8111156142a6576142a56138fe565b5b6142b284828501614256565b91505092915050565b5f80604083850312156142d1576142d06138fa565b5b5f6142de85828601613bcb565b92505060206142ef85828601613bcb565b9150509250929050565b5f60208201905061430c5f8301846140a8565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f61433682614312565b614340818561431c565b9350614350818560208601613cdf565b614359816139f0565b840191505092915050565b5f6020820190508181035f83015261437c818461432c565b905092915050565b5f6080820190506143975f830187613c0a565b6143a46020830186613c0a565b6143b160408301856140a8565b6143be606083018461398d565b95945050505050565b5f67ffffffffffffffff8211156143e1576143e0613a00565b5b602082029050602081019050919050565b5f6144046143ff846143c7565b613a5e565b9050808382526020820190506020840283018581111561442757614426613d63565b5b835b81811015614450578061443c8882613bcb565b845260208401935050602081019050614429565b5050509392505050565b5f82601f83011261446e5761446d6139e8565b5b813561447e8482602086016143f2565b91505092915050565b5f67ffffffffffffffff8211156144a1576144a0613a00565b5b602082029050602081019050919050565b5f6144c46144bf84614487565b613a5e565b905080838252602082019050602084028301858111156144e7576144e6613d63565b5b835b8181101561451057806144fc8882614069565b8452602084019350506020810190506144e9565b5050509392505050565b5f82601f83011261452e5761452d6139e8565b5b813561453e8482602086016144b2565b91505092915050565b5f805f805f60a086880312156145605761455f6138fa565b5b5f86013567ffffffffffffffff81111561457d5761457c6138fe565b5b6145898882890161445a565b955050602086013567ffffffffffffffff8111156145aa576145a96138fe565b5b6145b68882890161445a565b945050604086013567ffffffffffffffff8111156145d7576145d66138fe565b5b6145e38882890161451a565b935050606086013567ffffffffffffffff811115614604576146036138fe565b5b6146108882890161445a565b925050608086013567ffffffffffffffff811115614631576146306138fe565b5b61463d8882890161445a565b9150509295509295909350565b7f4e4654206e6f74206c697374656420666f722073616c650000000000000000005f82015250565b5f61467e60178361431c565b91506146898261464a565b602082019050919050565b5f6020820190508181035f8301526146ab81614672565b9050919050565b5f815190506146c081613bb5565b92915050565b5f602082840312156146db576146da6138fa565b5b5f6146e8848285016146b2565b91505092915050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f61472560148361431c565b9150614730826146f1565b602082019050919050565b5f6020820190508181035f83015261475281614719565b9050919050565b5f60408201905061476c5f8301856140a8565b61477960208301846140a8565b9392505050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f6147b460168361431c565b91506147bf82614780565b602082019050919050565b5f6020820190508181035f8301526147e1816147a8565b9050919050565b5f6060820190506147fb5f8301866140a8565b61480860208301856140a8565b6148156040830184613c0a565b949350505050565b61482681613982565b8114614830575f80fd5b50565b5f815190506148418161481d565b92915050565b5f6020828403121561485c5761485b6138fa565b5b5f61486984828501614833565b91505092915050565b5f819050919050565b5f61489561489061488b84614872565b613c51565b613bac565b9050919050565b6148a58161487b565b82525050565b50565b5f6148b95f83613ccf565b91506148c4826148ab565b5f82019050919050565b5f60a0820190506148e15f8301876140a8565b6148ee60208301866140a8565b6148fb6040830185613c0a565b614908606083018461489c565b8181036080830152614919816148ae565b905095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061496857607f821691505b60208210810361497b5761497a614924565b5b50919050565b5f60208284031215614996576149956138fa565b5b5f82013567ffffffffffffffff8111156149b3576149b26138fe565b5b6149bf8482850161445a565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614a2c82613bac565b9150614a3783613bac565b9250828201905080821115614a4f57614a4e6149f5565b5b92915050565b5f614a5f826141d8565b915060ff8203614a7257614a716149f5565b5b600182019050919050565b5f614a8782613bac565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ab957614ab86149f5565b5b600182019050919050565b7f496e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f614af8600f8361431c565b9150614b0382614ac4565b602082019050919050565b5f6020820190508181035f830152614b2581614aec565b9050919050565b5f60a082019050614b3f5f830188613c0a565b614b4c6020830187613c0a565b614b5960408301866140a8565b614b666060830185613c0a565b614b736080830184613c0a565b9695505050505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b614baf81613bac565b82525050565b5f614bc08383614ba6565b60208301905092915050565b5f602082019050919050565b5f614be282614b7d565b614bec8185614b87565b9350614bf783614b97565b805f5b83811015614c27578151614c0e8882614bb5565b9750614c1983614bcc565b925050600181019050614bfa565b5085935050505092915050565b5f6020820190508181035f830152614c4c8184614bd8565b905092915050565b5f80fd5b5f80fd5b5f67ffffffffffffffff821115614c7657614c75613a00565b5b602082029050602081019050919050565b5f60408284031215614c9c57614c9b614c54565b5b614ca66040613a5e565b90505f614cb584828501614069565b5f830152506020614cc884828501613bcb565b60208301525092915050565b5f614ce6614ce184614c5c565b613a5e565b90508083825260208201905060408402830185811115614d0957614d08613d63565b5b835b81811015614d325780614d1e8882614c87565b845260208401935050604081019050614d0b565b5050509392505050565b5f82601f830112614d5057614d4f6139e8565b5b8135614d60848260208601614cd4565b91505092915050565b5f60a08284031215614d7e57614d7d614c54565b5b614d8860a0613a5e565b90505f614d97848285016139d4565b5f830152506020614daa84828501613e30565b602083015250604082013567ffffffffffffffff811115614dce57614dcd614c58565b5b614dda84828501613af7565b604083015250606082013567ffffffffffffffff811115614dfe57614dfd614c58565b5b614e0a84828501613af7565b606083015250608082013567ffffffffffffffff811115614e2e57614e2d614c58565b5b614e3a84828501614d3c565b60808301525092915050565b5f614e513683614d69565b9050919050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f614e8c600e8361431c565b9150614e9782614e58565b602082019050919050565b5f6020820190508181035f830152614eb981614e80565b9050919050565b5f604082019050614ed35f830185613c0a565b614ee06020830184613c0a565b9392505050565b5f61010082019050614efb5f83018a6140a8565b614f086020830189613c0a565b614f156040830188613c0a565b614f22606083018761489c565b614f2f6080830186613c0a565b614f3c60a0830185613c0a565b614f4960c08301846140a8565b81810360e0830152614f5a816148ae565b905098975050505050505050565b5f606082019050614f7b5f830186613c0a565b614f886020830185613c0a565b614f956040830184613c0a565b949350505050565b7f4172726179206c656e677468206d69736d6174636800000000000000000000005f82015250565b5f614fd160158361431c565b9150614fdc82614f9d565b602082019050919050565b5f6020820190508181035f830152614ffe81614fc5565b9050919050565b7f4f6e6c7920746865206f776e65722063616e206c6973742074686973204e46545f82015250565b5f61503960208361431c565b915061504482615005565b602082019050919050565b5f6020820190508181035f8301526150668161502d565b9050919050565b7f50617573656420737562736372697074696f6e732063616e6e6f74206265206c5f8201527f6973746564000000000000000000000000000000000000000000000000000000602082015250565b5f6150c760258361431c565b91506150d28261506d565b604082019050919050565b5f6020820190508181035f8301526150f4816150bb565b9050919050565b5f6040820190508181035f830152615113818561432c565b905081810360208301526151278184613d07565b90509392505050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261518c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615151565b6151968683615151565b95508019841693508086168417925050509392505050565b5f6151c86151c36151be84613bac565b613c51565b613bac565b9050919050565b5f819050919050565b6151e1836151ae565b6151f56151ed826151cf565b84845461515d565b825550505050565b5f90565b6152096151fd565b6152148184846151d8565b505050565b5b818110156152375761522c5f82615201565b60018101905061521a565b5050565b601f82111561527c5761524d81615130565b61525684615142565b81016020851015615265578190505b61527961527185615142565b830182615219565b50505b505050565b5f82821c905092915050565b5f61529c5f1984600802615281565b1980831691505092915050565b5f6152b4838361528d565b9150826002028217905092915050565b6152cd82613cc5565b67ffffffffffffffff8111156152e6576152e5613a00565b5b6152f08254614951565b6152fb82828561523b565b5f60209050601f83116001811461532c575f841561531a578287015190505b61532485826152a9565b86555061538b565b601f19841661533a86615130565b5f5b828110156153615784890151825560018201915060208501945060208101905061533c565b8683101561537e578489015161537a601f89168261528d565b8355505b6001600288020188555050505b505050505050565b5f819050815f5260205f209050919050565b601f8211156153e6576153b781615393565b6153c084615142565b810160208510156153cf578190505b6153e36153db85615142565b830182615219565b50505b505050565b6153f482614312565b67ffffffffffffffff81111561540d5761540c613a00565b5b6154178254614951565b6154228282856153a5565b5f60209050601f831160018114615453575f8415615441578287015190505b61544b85826152a9565b8655506154b2565b601f19841661546186615393565b5f5b8281101561548857848901518255600182019150602085019450602081019050615463565b868310156154a557848901516154a1601f89168261528d565b8355505b6001600288020188555050505b505050505050565b5f81546154c681614951565b6154d0818661431c565b9450600182165f81146154ea576001811461550057615532565b60ff198316865281151560200286019350615532565b61550985615393565b5f5b8381101561552a5781548189015260018201915060208101905061550b565b808801955050505b50505092915050565b5f815461554781614951565b6155518186613ccf565b9450600182165f811461556b5760018114615581576155b3565b60ff1983168652811515602002860193506155b3565b61558a85615130565b5f5b838110156155ab5781548189015260018201915060208101905061558c565b808801955050505b50505092915050565b5f6040820190508181035f8301526155d481856154ba565b905081810360208301526155e8818461553b565b90509392505050565b5f6155fb82613bac565b915061560683613bac565b925082820390508181111561561e5761561d6149f5565b5b92915050565b5f61562e82613bac565b915061563983613bac565b925082820261564781613bac565b9150828204841483151761565e5761565d6149f5565b5b5092915050565b5f8160011c9050919050565b5f808291508390505b60018511156156ba57808604811115615696576156956149f5565b5b60018516156156a55780820291505b80810290506156b385615665565b945061567a565b94509492505050565b5f826156d2576001905061578d565b816156df575f905061578d565b81600181146156f557600281146156ff5761572e565b600191505061578d565b60ff841115615711576157106149f5565b5b8360020a915084821115615728576157276149f5565b5b5061578d565b5060208310610133831016604e8410600b84101617156157635782820a90508381111561575e5761575d6149f5565b5b61578d565b6157708484846001615671565b92509050818404811115615787576157866149f5565b5b81810290505b9392505050565b5f61579e82613bac565b91506157a983613bac565b92506157d67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846156c3565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61581582613bac565b915061582083613bac565b9250826158305761582f6157de565b5b828204905092915050565b5f615845826141d8565b9150615850836141d8565b9250826158605761585f6157de565b5b828204905092915050565b5f615875826141d8565b9150615880836141d8565b925082820261588e816141d8565b91508082146158a05761589f6149f5565b5b5092915050565b5f6158b1826141d8565b91506158bc836141d8565b9250828203905060ff8111156158d5576158d46149f5565b5b92915050565b5f6158e5826141d8565b91506158f0836141d8565b9250828201905060ff811115615909576159086149f5565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b61594581613e07565b82525050565b5f61ffff82169050919050565b6159618161594b565b82525050565b5f63ffffffff82169050919050565b61597f81615967565b82525050565b5f60a0820190506159985f83018861593c565b81810360208301526159aa8187613d07565b90506159b96040830186615958565b6159c66060830185615976565b6159d3608083018461401a565b9695505050505050565b5f815190506159eb816139be565b92915050565b5f60208284031215615a0657615a056138fa565b5b5f615a13848285016159dd565b91505092915050565b5f615a2682613c32565b9050919050565b615a3681615a1c565b8114615a40575f80fd5b50565b5f81519050615a5181615a2d565b92915050565b5f805f8060808587031215615a6f57615a6e6138fa565b5b5f615a7c878288016146b2565b9450506020615a8d878288016146b2565b9350506040615a9e87828801615a43565b9250506060615aaf878288016146b2565b91505092959194509250565b5f615ac582613bac565b9150615ad083613bac565b925082615ae057615adf6157de565b5b82820690509291505056fea264697066735822122024a685ec64a20abc76ead2788f5c1e702407f820bff4786606f6028b6bbdfaac64736f6c63430008140033636f6e73742077616c6c657441646472657373203d20617267735b305d3b636f6e737420746f6b656e4964203d20617267735b315d3b636f6e73742075726c203d206068747470733a2f2f636861696e6c696e6b2d6e74666e2d736572766963652d626c6f636b74656173652e6f6e72656e6465722e636f6d2f73656e642d656d61696c603b636f6e736f6c652e6c6f6728604854545020474554205265717565737420746f20247b75726c7d3f77616c6c65745f616464726573733d247b77616c6c6574416464726573737d26746f6b656e49643d247b746f6b656e49647d60293b636f6e737420656d61696c52657175657374203d2046756e6374696f6e732e6d616b654874747052657175657374287b202075726c3a2075726c2c2020686561646572733a207b2020202027436f6e74656e742d54797065273a20276170706c69636174696f6e2f6a736f6e272c20207d2c202074696d656f75743a20393030302c2020706172616d733a207b2020202077616c6c65745f616464726573733a2077616c6c6574416464726573732c20202020746f6b656e49643a20746f6b656e49642c20207d2c7d293b636f6e737420656d61696c526573706f6e7365203d20617761697420656d61696c526571756573743b636f6e736f6c652e6c6f672860456d61696c2073656e74207375636365737366756c6c7920746f2077616c6c6574206164647265737320247b77616c6c6574416464726573737d207769746820746f6b656e496420247b746f6b656e49647d60293b72657475726e2046756e6374696f6e732e656e636f6465537472696e672860456d61696c2073656e74207375636365737366756c6c7920746f2077616c6c6574206164647265737320247b77616c6c6574416464726573737d207769746820746f6b656e496420247b746f6b656e49647d60293b000000000000000000000000694aa1769357215de4fac081bf1f309adc3253060000000000000000000000000bf3de8c5d3e8a2b34d2beeb17abfcebaf363a59000000000000000000000000c96b21eda35a43effc57d459688e066315106f590000000000000000000000009d24c52916a14afc31d86b5aa046b252383ee444
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101a7575f3560e01c8063715018a6116100f7578063b0f479a111610095578063de74e57b1161006f578063de74e57b146104b0578063f2fde38b146104e3578063f529ecbc146104ff578063fe8723e11461051b576101a7565b8063b0f479a114610456578063b1e2174914610474578063d34bcc8d14610492576101a7565b806385572ffb116100d157806385572ffb146103e25780638d1d44a9146103fe5780638da5cb5b1461041a5780639405dfdd14610438576101a7565b8063715018a614610385578063741bef1a1461038f57806375158514146103ad576101a7565b80634585e33b116101645780634ccf1b341161013e5780634ccf1b34146102e95780636a030ca9146103055780636decc218146103385780636e04ff0d14610354576101a7565b80634585e33b1461027f57806348a7d26d1461029b5780634b0795a8146102cb576101a7565b806301ffc9a7146101ab5780630ca76175146101db578063243adbdd146101f75780632d5bbf60146102135780633013ce29146102435780633944ea3a14610261575b5f80fd5b6101c560048036038101906101c09190613957565b610537565b6040516101d2919061399c565b60405180910390f35b6101f560048036038101906101f09190613b24565b610608565b005b610211600480360381019061020c9190613bdf565b6106ca565b005b61022d60048036038101906102289190613bdf565b610b51565b60405161023a9190613c19565b60405180910390f35b61024b610b71565b6040516102589190613cac565b60405180910390f35b610269610b96565b6040516102769190613d3f565b60405180910390f35b61029960048036038101906102949190613dbc565b610c22565b005b6102b560048036038101906102b09190613fc0565b611105565b6040516102c29190614029565b60405180910390f35b6102d36111ff565b6040516102e09190613d3f565b60405180910390f35b61030360048036038101906102fe919061407d565b61128b565b005b61031f600480360381019061031a9190613bdf565b611344565b60405161032f94939291906140b7565b60405180910390f35b610352600480360381019061034d91906140fa565b61138f565b005b61036e60048036038101906103699190613dbc565b61148a565b60405161037c929190614171565b60405180910390f35b61038d61166a565b005b61039761167d565b6040516103a491906141bf565b60405180910390f35b6103c760048036038101906103c29190613bdf565b6116a2565b6040516103d9969594939291906141f3565b60405180910390f35b6103fc60048036038101906103f79190614274565b611713565b005b610418600480360381019061041391906142bb565b6117b8565b005b610422611c03565b60405161042f91906142f9565b60405180910390f35b610440611c2b565b60405161044d9190613c19565b60405180910390f35b61045e611c31565b60405161046b91906142f9565b60405180910390f35b61047c611c58565b6040516104899190614029565b60405180910390f35b61049a611c5e565b6040516104a79190614364565b60405180910390f35b6104ca60048036038101906104c59190613bdf565b611cea565b6040516104da9493929190614384565b60405180910390f35b6104fd60048036038101906104f8919061407d565b611d42565b005b61051960048036038101906105149190614547565b611dc6565b005b610535600480360381019061053091906142bb565b6120f4565b005b5f7f85572ffb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061060157507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b7f000000000000000000000000b83e47c2bc239b3bf370bc41e1459a34b41238d073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461068d576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106988383836123aa565b827f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e660405160405180910390a2505050565b6106d2612464565b5f60105f8381526020019081526020015f2090508060020160149054906101000a900460ff16610737576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072e90614694565b60405180910390fd5b8060010154600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b815260040161079691906142f9565b602060405180830381865afa1580156107b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d591906146c6565b1015610816576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080d9061473b565b60405180910390fd5b8060010154600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b8152600401610877929190614759565b602060405180830381865afa158015610892573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b691906146c6565b10156108f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108ee906147ca565b60405180910390fd5b5f600e5f835f015481526020019081526020015f209050600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33846002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600101546040518463ffffffff1660e01b8152600401610993939291906147e8565b6020604051808303815f875af11580156109af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109d39190614847565b6109db575f80fd5b600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f242432a826003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1633845f015460016040518563ffffffff1660e01b8152600401610a6294939291906148ce565b5f604051808303815f87803b158015610a79575f80fd5b505af1158015610a8b573d5f803e3d5ffd5b5050505033816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f8260020160146101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16825f0154847fcbe87ada5f3ee71caed4f1443d212d022ecdd1d72742c75a756c186bc2e4dff88560010154604051610b3c9190613c19565b60405180910390a45050610b4e6124a8565b50565b600d8181548110610b60575f80fd5b905f5260205f20015f915090505481565b600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60038054610ba390614951565b80601f0160208091040260200160405190810160405280929190818152602001828054610bcf90614951565b8015610c1a5780601f10610bf157610100808354040283529160200191610c1a565b820191905f5260205f20905b815481529060010190602001808311610bfd57829003601f168201915b505050505081565b5f8282810190610c329190614981565b90505f5b81518110156110ff575f828281518110610c5357610c526149c8565b5b602002602001015190505f600e5f8381526020019081526020015f2090505f600f5f836002015481526020019081526020015f206040518060800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820154815250509050805f0151600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518263ffffffff1660e01b8152600401610d8791906142f9565b602060405180830381865afa158015610da2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dc691906146c6565b10158015610e945750805f0151600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e846003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16306040518363ffffffff1660e01b8152600401610e52929190614759565b602060405180830381865afa158015610e6d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e9191906146c6565b10155b15610f9f57600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1630845f01516040518463ffffffff1660e01b8152600401610f1d939291906147e8565b6020604051808303815f875af1158015610f39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f5d9190614847565b610f65575f80fd5b806060015142610f759190614a22565b82600101819055505f8260030160156101000a81548160ff021916908360ff1602179055506110e9565b81600301601581819054906101000a900460ff1680929190610fc090614a55565b91906101000a81548160ff021916908360ff1602179055505060028260030160159054906101000a900460ff1660ff16106110135760018260030160146101000a81548160ff0219169083151502179055505b5f600267ffffffffffffffff81111561102f5761102e613a00565b5b60405190808252806020026020018201604052801561106257816020015b606081526020019060019003908161104d5790505b509050611091836003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff166124b1565b815f815181106110a4576110a36149c8565b5b60200260200101819052506110bb835f015461266d565b816001815181106110cf576110ce6149c8565b5b60200260200101819052506110e6610b0982611105565b50505b50505080806110f790614a7d565b915050610c36565b50505050565b5f61110e61384a565b6111a96007805461111e90614951565b80601f016020809104026020016040519081016040528092919081815260200182805461114a90614951565b80156111955780601f1061116c57610100808354040283529160200191611195565b820191905f5260205f20905b81548152906001019060200180831161117857829003601f168201915b5050505050826127eb90919063ffffffff16565b5f835111156111c6576111c583826127fb90919063ffffffff16565b5b6111ed6111d282612842565b8560085f9054906101000a900463ffffffff16600954612c53565b60028190555060025491505092915050565b6004805461120c90614951565b80601f016020809104026020016040519081016040528092919081815260200182805461123890614951565b80156112835780601f1061125a57610100808354040283529160200191611283565b820191905f5260205f20905b81548152906001019060200180831161126657829003601f168201915b505050505081565b611293612d32565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611301576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f890614b0e565b60405180910390fd5b80600b5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600f602052805f5260405f205f91509050805f015490806001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020154908060030154905084565b611397612d32565b60405180608001604052808581526020018473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182815250600f5f8781526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301559050507faa15cd9a715f663de2b0b442585d410be6b8b5538c624d56bbfc0e53bc4252c5858585858560405161147b959493929190614b2c565b60405180910390a15050505050565b5f60605f600d8054905067ffffffffffffffff8111156114ad576114ac613a00565b5b6040519080825280602002602001820160405280156114db5781602001602082028036833780820191505090505b5090505f805b600d80549050811015611636575f600d8281548110611503576115026149c8565b5b905f5260205f20015490505f600e5f8381526020019081526020015f206040518060c00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160149054906101000a900460ff161515151581526020016003820160159054906101000a900460ff1660ff1660ff16815250509050428160200151111580156115ed57508060800151155b156116215781858581518110611606576116056149c8565b5b602002602001018181525050838061161d90614a7d565b9450505b5050808061162e90614a7d565b9150506114e1565b505f81119350808252816040516020016116509190614c34565b604051602081830303815290604052925050509250929050565b611672612d32565b61167b5f612db9565b565b600c5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600e602052805f5260405f205f91509050805f015490806001015490806002015490806003015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030160149054906101000a900460ff16908060030160159054906101000a900460ff16905086565b7f0000000000000000000000000bf3de8c5d3e8a2b34d2beeb17abfcebaf363a5973ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146117a357336040517fd7f7333400000000000000000000000000000000000000000000000000000000815260040161179a91906142f9565b60405180910390fd5b6117b5816117b090614e46565b612e7c565b50565b6117c0612464565b5f600f5f8481526020019081526020015f206040518060800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600282015481526020016003820154815250509050600b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330845f01516040518463ffffffff1660e01b81526004016118b2939291906147e8565b6020604051808303815f875af11580156118ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118f29190614847565b611931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192890614ea2565b60405180910390fd5b5f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ab531efd85856040518363ffffffff1660e01b815260040161198e929190614ec0565b602060405180830381865afa1580156119a9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119cd91906146c6565b9050600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389c5b73a33868660018760600151886040015189602001516040518863ffffffff1660e01b8152600401611a429796959493929190614ee7565b5f604051808303815f87803b158015611a59575f80fd5b505af1158015611a6b573d5f803e3d5ffd5b50505050600d81908060018154018082558091505060019003905f5260205f20015f90919091909150556040518060c00160405280828152602001836060015142611ab69190614a22565b81526020018581526020013373ffffffffffffffffffffffffffffffffffffffff1681526020015f151581526020015f60ff16815250600e5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160030160146101000a81548160ff02191690831515021790555060a08201518160030160156101000a81548160ff021916908360ff1602179055509050503373ffffffffffffffffffffffffffffffffffffffff167f64482b8b4ec00191fbaf536ab56bb397d8efc6d86b8c41ca712f144addc7a45a858584604051611bed93929190614f68565b60405180910390a25050611bff6124a8565b5050565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60115481565b5f7f0000000000000000000000000bf3de8c5d3e8a2b34d2beeb17abfcebaf363a59905090565b60025481565b60058054611c6b90614951565b80601f0160208091040260200160405190810160405280929190818152602001828054611c9790614951565b8015611ce25780601f10611cb957610100808354040283529160200191611ce2565b820191905f5260205f20905b815481529060010190602001808311611cc557829003601f168201915b505050505081565b6010602052805f5260405f205f91509050805f015490806001015490806002015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020160149054906101000a900460ff16905084565b611d4a612d32565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611dba575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401611db191906142f9565b60405180910390fd5b611dc381612db9565b50565b611dce612d32565b8351855114611e12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0990614fe7565b60405180910390fd5b8251845114611e56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e4d90614fe7565b60405180910390fd5b8151835114611e9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9190614fe7565b60405180910390fd5b8051825114611ede576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed590614fe7565b60405180910390fd5b5f5b85518110156120ec576040518060800160405280868381518110611f0757611f066149c8565b5b60200260200101518152602001858381518110611f2757611f266149c8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001848381518110611f5d57611f5c6149c8565b5b60200260200101518152602001838381518110611f7d57611f7c6149c8565b5b6020026020010151815250600f5f888481518110611f9e57611f9d6149c8565b5b602002602001015181526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020155606082015181600301559050507faa15cd9a715f663de2b0b442585d410be6b8b5538c624d56bbfc0e53bc4252c586828151811061204c5761204b6149c8565b5b6020026020010151868381518110612067576120666149c8565b5b6020026020010151868481518110612082576120816149c8565b5b602002602001015186858151811061209d5761209c6149c8565b5b60200260200101518686815181106120b8576120b76149c8565b5b60200260200101516040516120d1959493929190614b2c565b60405180910390a180806120e490614a7d565b915050611ee0565b505050505050565b5f600e5f8481526020019081526020015f206040518060c00160405290815f82015481526020016001820154815260200160028201548152602001600382015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820160149054906101000a900460ff161515151581526020016003820160159054906101000a900460ff1660ff1660ff168152505090503373ffffffffffffffffffffffffffffffffffffffff16816060015173ffffffffffffffffffffffffffffffffffffffff161461222f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122269061504f565b60405180910390fd5b806080015115612274576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161226b906150dd565b60405180910390fd5b60405180608001604052808481526020018381526020013373ffffffffffffffffffffffffffffffffffffffff1681526020016001151581525060105f60115481526020019081526020015f205f820151815f0155602082015181600101556040820151816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160146101000a81548160ff0219169083151502179055509050503373ffffffffffffffffffffffffffffffffffffffff16836011547f5fc076273da30f9495a795f70cf6fedc3cec996f6a27ddc637c7e6328e77006d856040516123869190613c19565b60405180910390a460115f8154809291906123a090614a7d565b9190505550505050565b82600254146123f257827f17aac589b115f42ae5c9320ca9eb350d352b376d8c07f7d1b166e9a9b155481b83836040516123e59291906150fb565b60405180910390a261245f565b816003908161240191906152c4565b50806004908161241191906152c4565b50816005908161242191906153eb565b50827f17aac589b115f42ae5c9320ca9eb350d352b376d8c07f7d1b166e9a9b155481b600560046040516124569291906155bc565b60405180910390a25b505050565b60025f540361249f576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550565b60015f81905550565b60605f602867ffffffffffffffff8111156124cf576124ce613a00565b5b6040519080825280601f01601f1916602001820160405280156125015781602001600182028036833780820191505090505b5090505f5b6014811015612663575f81601361251d91906155f1565b60086125299190615624565b60026125359190615794565b8573ffffffffffffffffffffffffffffffffffffffff16612556919061580b565b60f81b90505f60108260f81c61256c919061583b565b60f81b90505f8160f81c6010612582919061586b565b8360f81c61259091906158a7565b60f81b905061259e826131fe565b858560026125ac9190615624565b815181106125bd576125bc6149c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506125f4816131fe565b8560018660026126049190615624565b61260e9190614a22565b8151811061261f5761261e6149c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350505050808061265b90614a7d565b915050612506565b5080915050919050565b60605f82036126b3576040518060400160405280600181526020017f300000000000000000000000000000000000000000000000000000000000000081525090506127e6565b5f8290505f5b5f82146126e25780806126cb90614a7d565b915050600a826126db919061580b565b91506126b9565b5f8167ffffffffffffffff8111156126fd576126fc613a00565b5b6040519080825280601f01601f19166020018201604052801561272f5781602001600182028036833780820191505090505b5090505f8290505b5f86146127de5760018161274b91906155f1565b90505f600a808861275c919061580b565b6127669190615624565b8761277191906155f1565b603061277d91906158db565b90505f8160f81b90508084848151811061279a576127996149c8565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a886127d5919061580b565b97505050612737565b819450505050505b919050565b6127f7825f8084613243565b5050565b5f815103612835576040517ffe936cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808260a001819052505050565b60605f6128506101006132e9565b905061289a6040518060400160405280600c81526020017f636f64654c6f636174696f6e00000000000000000000000000000000000000008152508261330e90919063ffffffff16565b6128c2835f015160028111156128b3576128b261590f565b5b8261333690919063ffffffff16565b61290a6040518060400160405280600881526020017f6c616e67756167650000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b61293283604001515f8111156129235761292261590f565b5b8261333690919063ffffffff16565b61297a6040518060400160405280600681526020017f736f7572636500000000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b61299183606001518261330e90919063ffffffff16565b5f8360a00151511115612a4b576129e66040518060400160405280600481526020017f61726773000000000000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b6129ef81613385565b5f5b8360a0015151811015612a4057612a2f8460a001518281518110612a1857612a176149c8565b5b60200260200101518361330e90919063ffffffff16565b80612a3990614a7d565b90506129f1565b50612a4a816133ad565b5b5f8360800151511115612b8a575f6002811115612a6b57612a6a61590f565b5b83602001516002811115612a8257612a8161590f565b5b03612ab9576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b016040518060400160405280600f81526020017f736563726574734c6f636174696f6e00000000000000000000000000000000008152508261330e90919063ffffffff16565b612b2a83602001516002811115612b1b57612b1a61590f565b5b8261333690919063ffffffff16565b612b726040518060400160405280600781526020017f73656372657473000000000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b612b898360800151826133d590919063ffffffff16565b5b5f8360c00151511115612c4457612bdf6040518060400160405280600981526020017f62797465734172677300000000000000000000000000000000000000000000008152508261330e90919063ffffffff16565b612be881613385565b5f5b8360c0015151811015612c3957612c288460c001518281518110612c1157612c106149c8565b5b6020026020010151836133d590919063ffffffff16565b80612c3290614a7d565b9050612bea565b50612c43816133ad565b5b805f01515f0151915050919050565b5f807f000000000000000000000000b83e47c2bc239b3bf370bc41e1459a34b41238d073ffffffffffffffffffffffffffffffffffffffff1663461d27628688600188886040518663ffffffff1660e01b8152600401612cb7959493929190615985565b6020604051808303815f875af1158015612cd3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612cf791906159f1565b9050807f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db860405160405180910390a280915050949350505050565b612d3a6133fd565b73ffffffffffffffffffffffffffffffffffffffff16612d58611c03565b73ffffffffffffffffffffffffffffffffffffffff1614612db757612d7b6133fd565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401612dae91906142f9565b60405180910390fd5b565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f805f808460600151806020019051810190612e989190615a57565b93509350935093505f600f5f8681526020019081526020015f206040518060800160405290815f8201548152602001600182015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016002820154815260200160038201548152505090505f600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ab531efd87876040518363ffffffff1660e01b8152600401612f8e929190614ec0565b602060405180830381865afa158015612fa9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fcd91906146c6565b9050600a5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166389c5b73a85888860018760600151886040015189602001516040518863ffffffff1660e01b81526004016130429796959493929190614ee7565b5f604051808303815f87803b158015613059575f80fd5b505af115801561306b573d5f803e3d5ffd5b50505050600d81908060018154018082558091505060019003905f5260205f20015f90919091909150556040518060c001604052808281526020018360600151426130b69190614a22565b81526020018781526020018573ffffffffffffffffffffffffffffffffffffffff1681526020015f151581526020015f60ff16815250600e5f8381526020019081526020015f205f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160030160146101000a81548160ff02191690831515021790555060a08201518160030160156101000a81548160ff021916908360ff1602179055509050508373ffffffffffffffffffffffffffffffffffffffff167f64482b8b4ec00191fbaf536ab56bb397d8efc6d86b8c41ca712f144addc7a45a8787846040516131ed93929190614f68565b60405180910390a250505050505050565b5f600a8260f81c60ff1610156132285760308260f81c61321e91906158db565b60f81b905061323e565b60578260f81c61323891906158db565b60f81b90505b919050565b5f81510361327d576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82845f019060028111156132945761329361590f565b5b908160028111156132a8576132a761590f565b5b815250508184604001905f8111156132c3576132c261590f565b5b90815f8111156132d6576132d561590f565b5b8152505080846060018190525050505050565b6132f16138b9565b6132fe815f015183613404565b505f816020018181525050919050565b61331b826003835161347a565b61333181835f015161361a90919063ffffffff16565b505050565b61335760026005600660ff16901b17835f015161363690919063ffffffff16565b50613381828260405160200161336d9190613c19565b6040516020818303038152906040526133d5565b5050565b61339081600461369d565b6001816020018181516133a39190614a22565b9150818152505050565b6133b881600761369d565b6001816020018181516133cb91906155f1565b9150818152505050565b6133e2826002835161347a565b6133f881835f015161361a90919063ffffffff16565b505050565b5f33905090565b61340c6138d8565b5f60208361341a9190615abb565b146134465760208261342c9190615abb565b602061343891906155f1565b826134439190614a22565b91505b818360200181815250506040518084525f81528281016020018181101561346b575f80fd5b80604052505082905092915050565b60178167ffffffffffffffff16116134b4576134ae8160058460ff16901b60ff1617845f015161363690919063ffffffff16565b50613615565b60ff8167ffffffffffffffff1611613510576134e6601860058460ff16901b17845f015161363690919063ffffffff16565b5061350a8167ffffffffffffffff166001855f01516136c29092919063ffffffff16565b50613614565b61ffff8167ffffffffffffffff161161356d57613543601960058460ff16901b17845f015161363690919063ffffffff16565b506135678167ffffffffffffffff166002855f01516136c29092919063ffffffff16565b50613613565b63ffffffff8167ffffffffffffffff16116135cc576135a2601a60058460ff16901b17845f015161363690919063ffffffff16565b506135c68167ffffffffffffffff166004855f01516136c29092919063ffffffff16565b50613612565b6135ec601b60058460ff16901b17845f015161363690919063ffffffff16565b506136108167ffffffffffffffff166008855f01516136c29092919063ffffffff16565b505b5b5b5b505050565b6136226138d8565b61362e8383845161374b565b905092915050565b61363e6138d8565b5f835f01515190505f6001826136549190614a22565b90508460200151821061367857613677856002836136729190615624565b613828565b5b84516020838201018581538151831115613690578282525b5050849250505092915050565b6136bd601f60058360ff16901b17835f015161363690919063ffffffff16565b505050565b6136ca6138d8565b5f845f01515190505f81846136df9190614a22565b9050856020015181111561370457613703866002836136fe9190615624565b613828565b5b5f6001856101006137159190615794565b61371f91906155f1565b90508651828101878319825116178152815184111561373c578382525b50508693505050509392505050565b6137536138d8565b8251821115613760575f80fd5b5f845f01515190505f83826137759190614a22565b9050856020015181111561379a57613799866002836137949190615624565b613828565b5b5f80875180518560208301019350808511156137b4578482525b60208901925050505b602086106137fb57805182526020826137d69190614a22565b91506020816137e59190614a22565b90506020866137f491906155f1565b95506137bd565b5f6001876020036101000a0390508019825116818451168181178552505050879450505050509392505050565b5f825f015190506138398383613404565b50613844838261361a565b50505050565b6040518060e001604052805f60028111156138685761386761590f565b5b81526020015f60028111156138805761387f61590f565b5b81526020015f808111156138975761389661590f565b5b8152602001606081526020016060815260200160608152602001606081525090565b60405180604001604052806138cc6138d8565b81526020015f81525090565b6040518060400160405280606081526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61393681613902565b8114613940575f80fd5b50565b5f813590506139518161392d565b92915050565b5f6020828403121561396c5761396b6138fa565b5b5f61397984828501613943565b91505092915050565b5f8115159050919050565b61399681613982565b82525050565b5f6020820190506139af5f83018461398d565b92915050565b5f819050919050565b6139c7816139b5565b81146139d1575f80fd5b50565b5f813590506139e2816139be565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b613a36826139f0565b810181811067ffffffffffffffff82111715613a5557613a54613a00565b5b80604052505050565b5f613a676138f1565b9050613a738282613a2d565b919050565b5f67ffffffffffffffff821115613a9257613a91613a00565b5b613a9b826139f0565b9050602081019050919050565b828183375f83830152505050565b5f613ac8613ac384613a78565b613a5e565b905082815260208101848484011115613ae457613ae36139ec565b5b613aef848285613aa8565b509392505050565b5f82601f830112613b0b57613b0a6139e8565b5b8135613b1b848260208601613ab6565b91505092915050565b5f805f60608486031215613b3b57613b3a6138fa565b5b5f613b48868287016139d4565b935050602084013567ffffffffffffffff811115613b6957613b686138fe565b5b613b7586828701613af7565b925050604084013567ffffffffffffffff811115613b9657613b956138fe565b5b613ba286828701613af7565b9150509250925092565b5f819050919050565b613bbe81613bac565b8114613bc8575f80fd5b50565b5f81359050613bd981613bb5565b92915050565b5f60208284031215613bf457613bf36138fa565b5b5f613c0184828501613bcb565b91505092915050565b613c1381613bac565b82525050565b5f602082019050613c2c5f830184613c0a565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f613c74613c6f613c6a84613c32565b613c51565b613c32565b9050919050565b5f613c8582613c5a565b9050919050565b5f613c9682613c7b565b9050919050565b613ca681613c8c565b82525050565b5f602082019050613cbf5f830184613c9d565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015613cfc578082015181840152602081019050613ce1565b5f8484015250505050565b5f613d1182613cc5565b613d1b8185613ccf565b9350613d2b818560208601613cdf565b613d34816139f0565b840191505092915050565b5f6020820190508181035f830152613d578184613d07565b905092915050565b5f80fd5b5f80fd5b5f8083601f840112613d7c57613d7b6139e8565b5b8235905067ffffffffffffffff811115613d9957613d98613d5f565b5b602083019150836001820283011115613db557613db4613d63565b5b9250929050565b5f8060208385031215613dd257613dd16138fa565b5b5f83013567ffffffffffffffff811115613def57613dee6138fe565b5b613dfb85828601613d67565b92509250509250929050565b5f67ffffffffffffffff82169050919050565b613e2381613e07565b8114613e2d575f80fd5b50565b5f81359050613e3e81613e1a565b92915050565b5f67ffffffffffffffff821115613e5e57613e5d613a00565b5b602082029050602081019050919050565b5f67ffffffffffffffff821115613e8957613e88613a00565b5b613e92826139f0565b9050602081019050919050565b5f613eb1613eac84613e6f565b613a5e565b905082815260208101848484011115613ecd57613ecc6139ec565b5b613ed8848285613aa8565b509392505050565b5f82601f830112613ef457613ef36139e8565b5b8135613f04848260208601613e9f565b91505092915050565b5f613f1f613f1a84613e44565b613a5e565b90508083825260208201905060208402830185811115613f4257613f41613d63565b5b835b81811015613f8957803567ffffffffffffffff811115613f6757613f666139e8565b5b808601613f748982613ee0565b85526020850194505050602081019050613f44565b5050509392505050565b5f82601f830112613fa757613fa66139e8565b5b8135613fb7848260208601613f0d565b91505092915050565b5f8060408385031215613fd657613fd56138fa565b5b5f613fe385828601613e30565b925050602083013567ffffffffffffffff811115614004576140036138fe565b5b61401085828601613f93565b9150509250929050565b614023816139b5565b82525050565b5f60208201905061403c5f83018461401a565b92915050565b5f61404c82613c32565b9050919050565b61405c81614042565b8114614066575f80fd5b50565b5f8135905061407781614053565b92915050565b5f60208284031215614092576140916138fa565b5b5f61409f84828501614069565b91505092915050565b6140b181614042565b82525050565b5f6080820190506140ca5f830187613c0a565b6140d760208301866140a8565b6140e46040830185613c0a565b6140f16060830184613c0a565b95945050505050565b5f805f805f60a08688031215614113576141126138fa565b5b5f61412088828901613bcb565b955050602061413188828901613bcb565b945050604061414288828901614069565b935050606061415388828901613bcb565b925050608061416488828901613bcb565b9150509295509295909350565b5f6040820190506141845f83018561398d565b81810360208301526141968184613d07565b90509392505050565b5f6141a982613c7b565b9050919050565b6141b98161419f565b82525050565b5f6020820190506141d25f8301846141b0565b92915050565b5f60ff82169050919050565b6141ed816141d8565b82525050565b5f60c0820190506142065f830189613c0a565b6142136020830188613c0a565b6142206040830187613c0a565b61422d60608301866140a8565b61423a608083018561398d565b61424760a08301846141e4565b979650505050505050565b5f80fd5b5f60a0828403121561426b5761426a614252565b5b81905092915050565b5f60208284031215614289576142886138fa565b5b5f82013567ffffffffffffffff8111156142a6576142a56138fe565b5b6142b284828501614256565b91505092915050565b5f80604083850312156142d1576142d06138fa565b5b5f6142de85828601613bcb565b92505060206142ef85828601613bcb565b9150509250929050565b5f60208201905061430c5f8301846140a8565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f61433682614312565b614340818561431c565b9350614350818560208601613cdf565b614359816139f0565b840191505092915050565b5f6020820190508181035f83015261437c818461432c565b905092915050565b5f6080820190506143975f830187613c0a565b6143a46020830186613c0a565b6143b160408301856140a8565b6143be606083018461398d565b95945050505050565b5f67ffffffffffffffff8211156143e1576143e0613a00565b5b602082029050602081019050919050565b5f6144046143ff846143c7565b613a5e565b9050808382526020820190506020840283018581111561442757614426613d63565b5b835b81811015614450578061443c8882613bcb565b845260208401935050602081019050614429565b5050509392505050565b5f82601f83011261446e5761446d6139e8565b5b813561447e8482602086016143f2565b91505092915050565b5f67ffffffffffffffff8211156144a1576144a0613a00565b5b602082029050602081019050919050565b5f6144c46144bf84614487565b613a5e565b905080838252602082019050602084028301858111156144e7576144e6613d63565b5b835b8181101561451057806144fc8882614069565b8452602084019350506020810190506144e9565b5050509392505050565b5f82601f83011261452e5761452d6139e8565b5b813561453e8482602086016144b2565b91505092915050565b5f805f805f60a086880312156145605761455f6138fa565b5b5f86013567ffffffffffffffff81111561457d5761457c6138fe565b5b6145898882890161445a565b955050602086013567ffffffffffffffff8111156145aa576145a96138fe565b5b6145b68882890161445a565b945050604086013567ffffffffffffffff8111156145d7576145d66138fe565b5b6145e38882890161451a565b935050606086013567ffffffffffffffff811115614604576146036138fe565b5b6146108882890161445a565b925050608086013567ffffffffffffffff811115614631576146306138fe565b5b61463d8882890161445a565b9150509295509295909350565b7f4e4654206e6f74206c697374656420666f722073616c650000000000000000005f82015250565b5f61467e60178361431c565b91506146898261464a565b602082019050919050565b5f6020820190508181035f8301526146ab81614672565b9050919050565b5f815190506146c081613bb5565b92915050565b5f602082840312156146db576146da6138fa565b5b5f6146e8848285016146b2565b91505092915050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f61472560148361431c565b9150614730826146f1565b602082019050919050565b5f6020820190508181035f83015261475281614719565b9050919050565b5f60408201905061476c5f8301856140a8565b61477960208301846140a8565b9392505050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f6147b460168361431c565b91506147bf82614780565b602082019050919050565b5f6020820190508181035f8301526147e1816147a8565b9050919050565b5f6060820190506147fb5f8301866140a8565b61480860208301856140a8565b6148156040830184613c0a565b949350505050565b61482681613982565b8114614830575f80fd5b50565b5f815190506148418161481d565b92915050565b5f6020828403121561485c5761485b6138fa565b5b5f61486984828501614833565b91505092915050565b5f819050919050565b5f61489561489061488b84614872565b613c51565b613bac565b9050919050565b6148a58161487b565b82525050565b50565b5f6148b95f83613ccf565b91506148c4826148ab565b5f82019050919050565b5f60a0820190506148e15f8301876140a8565b6148ee60208301866140a8565b6148fb6040830185613c0a565b614908606083018461489c565b8181036080830152614919816148ae565b905095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061496857607f821691505b60208210810361497b5761497a614924565b5b50919050565b5f60208284031215614996576149956138fa565b5b5f82013567ffffffffffffffff8111156149b3576149b26138fe565b5b6149bf8482850161445a565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f614a2c82613bac565b9150614a3783613bac565b9250828201905080821115614a4f57614a4e6149f5565b5b92915050565b5f614a5f826141d8565b915060ff8203614a7257614a716149f5565b5b600182019050919050565b5f614a8782613bac565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614ab957614ab86149f5565b5b600182019050919050565b7f496e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f614af8600f8361431c565b9150614b0382614ac4565b602082019050919050565b5f6020820190508181035f830152614b2581614aec565b9050919050565b5f60a082019050614b3f5f830188613c0a565b614b4c6020830187613c0a565b614b5960408301866140a8565b614b666060830185613c0a565b614b736080830184613c0a565b9695505050505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b614baf81613bac565b82525050565b5f614bc08383614ba6565b60208301905092915050565b5f602082019050919050565b5f614be282614b7d565b614bec8185614b87565b9350614bf783614b97565b805f5b83811015614c27578151614c0e8882614bb5565b9750614c1983614bcc565b925050600181019050614bfa565b5085935050505092915050565b5f6020820190508181035f830152614c4c8184614bd8565b905092915050565b5f80fd5b5f80fd5b5f67ffffffffffffffff821115614c7657614c75613a00565b5b602082029050602081019050919050565b5f60408284031215614c9c57614c9b614c54565b5b614ca66040613a5e565b90505f614cb584828501614069565b5f830152506020614cc884828501613bcb565b60208301525092915050565b5f614ce6614ce184614c5c565b613a5e565b90508083825260208201905060408402830185811115614d0957614d08613d63565b5b835b81811015614d325780614d1e8882614c87565b845260208401935050604081019050614d0b565b5050509392505050565b5f82601f830112614d5057614d4f6139e8565b5b8135614d60848260208601614cd4565b91505092915050565b5f60a08284031215614d7e57614d7d614c54565b5b614d8860a0613a5e565b90505f614d97848285016139d4565b5f830152506020614daa84828501613e30565b602083015250604082013567ffffffffffffffff811115614dce57614dcd614c58565b5b614dda84828501613af7565b604083015250606082013567ffffffffffffffff811115614dfe57614dfd614c58565b5b614e0a84828501613af7565b606083015250608082013567ffffffffffffffff811115614e2e57614e2d614c58565b5b614e3a84828501614d3c565b60808301525092915050565b5f614e513683614d69565b9050919050565b7f5061796d656e74206661696c65640000000000000000000000000000000000005f82015250565b5f614e8c600e8361431c565b9150614e9782614e58565b602082019050919050565b5f6020820190508181035f830152614eb981614e80565b9050919050565b5f604082019050614ed35f830185613c0a565b614ee06020830184613c0a565b9392505050565b5f61010082019050614efb5f83018a6140a8565b614f086020830189613c0a565b614f156040830188613c0a565b614f22606083018761489c565b614f2f6080830186613c0a565b614f3c60a0830185613c0a565b614f4960c08301846140a8565b81810360e0830152614f5a816148ae565b905098975050505050505050565b5f606082019050614f7b5f830186613c0a565b614f886020830185613c0a565b614f956040830184613c0a565b949350505050565b7f4172726179206c656e677468206d69736d6174636800000000000000000000005f82015250565b5f614fd160158361431c565b9150614fdc82614f9d565b602082019050919050565b5f6020820190508181035f830152614ffe81614fc5565b9050919050565b7f4f6e6c7920746865206f776e65722063616e206c6973742074686973204e46545f82015250565b5f61503960208361431c565b915061504482615005565b602082019050919050565b5f6020820190508181035f8301526150668161502d565b9050919050565b7f50617573656420737562736372697074696f6e732063616e6e6f74206265206c5f8201527f6973746564000000000000000000000000000000000000000000000000000000602082015250565b5f6150c760258361431c565b91506150d28261506d565b604082019050919050565b5f6020820190508181035f8301526150f4816150bb565b9050919050565b5f6040820190508181035f830152615113818561432c565b905081810360208301526151278184613d07565b90509392505050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261518c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82615151565b6151968683615151565b95508019841693508086168417925050509392505050565b5f6151c86151c36151be84613bac565b613c51565b613bac565b9050919050565b5f819050919050565b6151e1836151ae565b6151f56151ed826151cf565b84845461515d565b825550505050565b5f90565b6152096151fd565b6152148184846151d8565b505050565b5b818110156152375761522c5f82615201565b60018101905061521a565b5050565b601f82111561527c5761524d81615130565b61525684615142565b81016020851015615265578190505b61527961527185615142565b830182615219565b50505b505050565b5f82821c905092915050565b5f61529c5f1984600802615281565b1980831691505092915050565b5f6152b4838361528d565b9150826002028217905092915050565b6152cd82613cc5565b67ffffffffffffffff8111156152e6576152e5613a00565b5b6152f08254614951565b6152fb82828561523b565b5f60209050601f83116001811461532c575f841561531a578287015190505b61532485826152a9565b86555061538b565b601f19841661533a86615130565b5f5b828110156153615784890151825560018201915060208501945060208101905061533c565b8683101561537e578489015161537a601f89168261528d565b8355505b6001600288020188555050505b505050505050565b5f819050815f5260205f209050919050565b601f8211156153e6576153b781615393565b6153c084615142565b810160208510156153cf578190505b6153e36153db85615142565b830182615219565b50505b505050565b6153f482614312565b67ffffffffffffffff81111561540d5761540c613a00565b5b6154178254614951565b6154228282856153a5565b5f60209050601f831160018114615453575f8415615441578287015190505b61544b85826152a9565b8655506154b2565b601f19841661546186615393565b5f5b8281101561548857848901518255600182019150602085019450602081019050615463565b868310156154a557848901516154a1601f89168261528d565b8355505b6001600288020188555050505b505050505050565b5f81546154c681614951565b6154d0818661431c565b9450600182165f81146154ea576001811461550057615532565b60ff198316865281151560200286019350615532565b61550985615393565b5f5b8381101561552a5781548189015260018201915060208101905061550b565b808801955050505b50505092915050565b5f815461554781614951565b6155518186613ccf565b9450600182165f811461556b5760018114615581576155b3565b60ff1983168652811515602002860193506155b3565b61558a85615130565b5f5b838110156155ab5781548189015260018201915060208101905061558c565b808801955050505b50505092915050565b5f6040820190508181035f8301526155d481856154ba565b905081810360208301526155e8818461553b565b90509392505050565b5f6155fb82613bac565b915061560683613bac565b925082820390508181111561561e5761561d6149f5565b5b92915050565b5f61562e82613bac565b915061563983613bac565b925082820261564781613bac565b9150828204841483151761565e5761565d6149f5565b5b5092915050565b5f8160011c9050919050565b5f808291508390505b60018511156156ba57808604811115615696576156956149f5565b5b60018516156156a55780820291505b80810290506156b385615665565b945061567a565b94509492505050565b5f826156d2576001905061578d565b816156df575f905061578d565b81600181146156f557600281146156ff5761572e565b600191505061578d565b60ff841115615711576157106149f5565b5b8360020a915084821115615728576157276149f5565b5b5061578d565b5060208310610133831016604e8410600b84101617156157635782820a90508381111561575e5761575d6149f5565b5b61578d565b6157708484846001615671565b92509050818404811115615787576157866149f5565b5b81810290505b9392505050565b5f61579e82613bac565b91506157a983613bac565b92506157d67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846156c3565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61581582613bac565b915061582083613bac565b9250826158305761582f6157de565b5b828204905092915050565b5f615845826141d8565b9150615850836141d8565b9250826158605761585f6157de565b5b828204905092915050565b5f615875826141d8565b9150615880836141d8565b925082820261588e816141d8565b91508082146158a05761589f6149f5565b5b5092915050565b5f6158b1826141d8565b91506158bc836141d8565b9250828203905060ff8111156158d5576158d46149f5565b5b92915050565b5f6158e5826141d8565b91506158f0836141d8565b9250828201905060ff811115615909576159086149f5565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b61594581613e07565b82525050565b5f61ffff82169050919050565b6159618161594b565b82525050565b5f63ffffffff82169050919050565b61597f81615967565b82525050565b5f60a0820190506159985f83018861593c565b81810360208301526159aa8187613d07565b90506159b96040830186615958565b6159c66060830185615976565b6159d3608083018461401a565b9695505050505050565b5f815190506159eb816139be565b92915050565b5f60208284031215615a0657615a056138fa565b5b5f615a13848285016159dd565b91505092915050565b5f615a2682613c32565b9050919050565b615a3681615a1c565b8114615a40575f80fd5b50565b5f81519050615a5181615a2d565b92915050565b5f805f8060808587031215615a6f57615a6e6138fa565b5b5f615a7c878288016146b2565b9450506020615a8d878288016146b2565b9350506040615a9e87828801615a43565b9250506060615aaf878288016146b2565b91505092959194509250565b5f615ac582613bac565b9150615ad083613bac565b925082615ae057615adf6157de565b5b82820690509291505056fea264697066735822122024a685ec64a20abc76ead2788f5c1e702407f820bff4786606f6028b6bbdfaac64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000694aa1769357215de4fac081bf1f309adc3253060000000000000000000000000bf3de8c5d3e8a2b34d2beeb17abfcebaf363a59000000000000000000000000c96b21eda35a43effc57d459688e066315106f590000000000000000000000009d24c52916a14afc31d86b5aa046b252383ee444-----Decoded View---------------
Arg [0] : _priceFeedAddress (address): 0x694AA1769357215DE4FAC081bf1f309aDC325306
Arg [1] : _routerCrossChain (address): 0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59
Arg [2] : _nftContract (address): 0xc96b21eDA35A43eFfc57d459688e066315106f59
Arg [3] : _paymentToken (address): 0x9d24c52916A14afc31D86B5Aa046b252383ee444-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000694aa1769357215de4fac081bf1f309adc325306
Arg [1] : 0000000000000000000000000bf3de8c5d3e8a2b34d2beeb17abfcebaf363a59
Arg [2] : 000000000000000000000000c96b21eda35a43effc57d459688e066315106f59
Arg [3] : 0000000000000000000000009d24c52916a14afc31d86b5aa046b252383ee444
Block | Transaction | Difficulty | Gas Used | Reward |
---|
Block | Uncle Number | Difficulty | Gas Used | Reward |
---|
Loading...
Loading
Validator Index | Block | Amount |
---|
Transaction Hash | Block | Value | Eth2 PubKey | Valid |
---|
[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.
Address QR Code
My Address - Private Name Tag or Note
My Name Tag:
Private Name Tags (up to 35 characters) can be used for easy identification of addresses
Private Note:
A private note (up to 500 characters) can be attached to this address.
Please DO NOT store any passwords or private keys here.
View all Private Name Tags
Connect a Wallet
Connect a Wallet
Connect a Wallet
Before You Copy
${zeroWidthWarningMessage} Check the actual text at ENS.
`; } const contentHtml = `Additional Info
Full Name:
Note:
- Name tag is displayed due to forward and reverse resolution. Find out more.
- A Domain Name is not necessarily held by a person popularly associated with the name.
${ensUnicodeWarningHtml} ${ensZeroWidthWarningHtml}
Other names resolving to this address:
${listOtherENSNames} ${moreOtherENSNames}
`; return result; } // ===== end ENS name tag var adjustPosition = 0; $(document).ready(function () { switchAmountToValue(document.getElementById("headerAmountValue"), 'Value (USD)', 'Amount', true); switchAmountToValue(document.getElementById("headerIntAmountValue"), 'Value (USD)', 'Amount', true); onDocumentReady(); $("[rel='tooltip']").tooltip(); $("[data-bs-toggle-second='tooltip']").tooltip({ trigger: 'hover' }); $("[rel='tooltipEns']").each(function () { $(this).tooltip({ title: $(this).attr("tooltip-title") }); }); //if (hash != '') { // activaTab(hash); //}; onAddressDocReady(); //// Note: this is causing "Copied" tooltip not showing when copy button is clicked in V3, and seems like not applicable to v3, comment out first in case there is issue //$('[data-bs-toggle="tooltip"]').click(function () { // $('[data-bs-toggle="tooltip"]').tooltip("hide"); //}); document.getElementById("copyaddressbutton").classList.remove("disabled"); if ($("#txtSearchContract").length) { initialiseKeyupOnDocReady(); } if (!!$('#ensName')[0]) { initEnsNamePopOver(); } handleToggle(); if (window.matchMedia("(max-width: 767px)").matches) { // Mobile adjustPosition = 90; } else { // Others adjustPosition = 50; } }); function displayAudit() { $('html, body').animate({ scrollTop: $("#auditReportId").offset().top - adjustPosition }); } function handleToggle() { var className = document.getElementsByClassName('editor'); var classNameCount = className.length; for (var j = 0; j < classNameCount; j++) { var editorSearch = ace.edit(className[j].id); if (getCookie('displaymode') === 'light' || themeMode === 'light') { editorSearch.setTheme('ace/theme/dawn'); } else if (getCookie('displaymode') === 'dim' || themeMode === 'dim') { editorSearch.setTheme('ace/theme/tomorrow_night_blue'); } else if (getCookie('displaymode') === 'dark' || themeMode === 'dark') { editorSearch.setTheme('ace/theme/tomorrow_night'); } if (editorSearch.session.getLength() < parseInt(MaxLines)) { var x = className[j].id.replace("editor", ""); if (x.trim() !== "") { $("#panel-sourcecode_" + x).hide(); } } } if ($('#panel-sourcecode').length) { var editorSetting = ace.edit("editor"); if (editorSetting.session.getLength() < parseInt(MaxLines)) { $("#panel-sourcecode").hide(); } } } // Bootstrap Dropdown in Table Responsive $('.table-responsive').on('shown.bs.dropdown', function (e) { var t = $(this), m = $(e.target).find('.dropdown-menu'), tb = t.offset().top + t.height(), mb = m.offset().top + m.outerHeight(true), d = 20; // Space for shadow + scrollbar. if (t[0].scrollWidth > t.innerWidth()) { if (mb + d > tb) { t.css('padding-bottom', ((mb + d) - tb)); } } else { t.css('overflow', 'visible'); } }).on('hidden.bs.dropdown', function () { $(this).css({ 'padding-bottom': '', 'overflow': '' }); }); var btn_ERC20_sort = { count: 0, reminder_count: 2, list: [], default_list: [], ERC20_sort_start: function (count) { if (document.getElementsByClassName('list-custom-divider-ERC20')[0]) { var self = this if (count != undefined) { self.count = count } var before_el = document.getElementsByClassName('list-custom-divider-ERC20')[0] var parent_el = before_el.parentNode var element_selector = parent_el.querySelectorAll(".list-custom-ERC20"); if (self.list.length == 0) { element_selector.forEach(function (e) { self.list.push(e); self.default_list.push(e); }); } $(".list-custom-ERC20").remove() var type = self.count % self.reminder_count self.sortList(type, parent_el, before_el); self.count++ } }, sortList: function (type, parent_el, before_el) { var self = this var sorted_list = [] var icon_el = $(before_el).find('button').find('i') switch (type) { case 1: icon_el.attr("class", "fad fa-sort-up") sorted_list = self.sortUsdAsc() break; default: icon_el.attr("class", "fad fa-sort-down") sorted_list = self.sortUsdDesc() } for (var i = sorted_list.length - 1; i >= 0; i--) { before_el.insertAdjacentElement('afterend', sorted_list[i]) } }, sortUsdAsc: function () { var self = this var sort_list = self.list sort_list.sort(function (a, b) { var target_a_value = self.formatCurrencyToNumber(a.querySelector('.list-usd-value').textContent.trim() || -1); var target_b_value = self.formatCurrencyToNumber(b.querySelector('.list-usd-value').textContent.trim() || -1); if (target_a_value == -1 || target_b_value == -1) { return 1; } if (target_a_value < target_b_value) { return -1; } if (target_a_value > target_b_value) { return 1; } return 0 }); return sort_list }, sortUsdDesc: function () { var self = this var sort_list = self.list sort_list.sort(function (a, b) { var target_a_value = self.formatCurrencyToNumber(a.querySelector('.list-usd-value').textContent.trim() || -1); var target_b_value = self.formatCurrencyToNumber(b.querySelector('.list-usd-value').textContent.trim() || -1); if (target_a_value < target_b_value) { return 1; } if (target_a_value > target_b_value) { return -1; } return 0 }); return sort_list }, formatCurrencyToNumber: function (strCurrency) { if (typeof strCurrency == "number") return strCurrency else return Number(strCurrency.replace(/[^0-9.-]+/g, "")); }, } $("#btn_ERC20_sort").on("click", function (event) { event.preventDefault(); setTimeout(function () { btn_ERC20_sort.ERC20_sort_start() }, 10) }) function hrefTokenHolding() { var location = "/tokenholdings?a=0xd8d9e346ad32d1f56bc5fc959440d0a3a2118981" var queryString = $("input.form-control.form-control-xs.search.mb-3")[0].value if (queryString) { location += "&q=" + queryString } window.location.href = location }