Sepolia Testnet

Contract

0x996C2D45D53C393fC7Eb6E00a3950061F54b26e7
Source Code Source Code

Overview

ETH Balance

0 ETH

More Info

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Amount
Set Config75009432025-01-16 2:11:36331 days ago1736993496IN
0x996C2D45...1F54b26e7
0 ETH0.00004931.01137895
Set Config74994502025-01-15 21:11:24331 days ago1736975484IN
0x996C2D45...1F54b26e7
0 ETH0.000148812.17733814
Authorize Contra...74986392025-01-15 18:29:12332 days ago1736965752IN
0x996C2D45...1F54b26e7
0 ETH0.0005415710.91344367
Authorize Contra...74986252025-01-15 18:26:24332 days ago1736965584IN
0x996C2D45...1F54b26e7
0 ETH0.0005891211.86869915
Register Source ...74984372025-01-15 17:48:36332 days ago1736963316IN
0x996C2D45...1F54b26e7
0 ETH0.0413156912.62199009
Set Config74984342025-01-15 17:48:00332 days ago1736963280IN
0x996C2D45...1F54b26e7
0 ETH0.0022523710.84836948

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ChainlinkFunctionsBeaconV1

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 100000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import "@chainlink/contracts/src/v0.8/functions/dev/v1_0_0/libraries/FunctionsRequest.sol";
import "@chainlink/contracts/src/v0.8/functions/dev/v1_0_0/FunctionsClient.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./storage/ProviderStorage.sol";

/**
 * @title ChainlinkFunctionsBeaconV1
 * @notice ALL RIGHTS RESERVED
 * @dev PROPRIETARY AND CONFIDENTIAL
 * Unauthorized copying, modification, distribution, or use of this code, via any medium, is strictly prohibited.
 * Written by Instruxi, 2024
 *
 * @notice EXPERIMENTAL CODE - USE AT YOUR OWN RISK
 * @dev This smart contract is undergoing a formal audit and meant for demonstration purposes only.
 * This code has not undergone a formal security audit and should not be used in production
 * without proper review and testing. Users interact with this contract at their own discretion
 * and assume all associated risks.
 */

contract ChainlinkFunctionsBeaconV1 is AbstractProviderStorage, FunctionsClient, ReentrancyGuard {
    using FunctionsRequest for FunctionsRequest.Request;

    bytes32 public donId;
    uint64 public subscriptionId;
    uint32 public callbackGasLimit;
    FunctionsRequest.Location public secretsLocation;
    bytes public encryptedSecretsReference;

    mapping(bytes32 => address) public requestToRequester;
    mapping(address => bool) public authorizedContracts;

    event OCRResponse(bytes32 indexed requestId, bytes response);
    event RequestFailed(bytes32 indexed requestId, bytes err);
    event RequestSent(string data);
    event ContractAuthorized(address indexed contractAddress);
    event ContractDeauthorized(address indexed contractAddress);

    error UnauthorizedContract(address caller);

    constructor(
        address router,
        bytes32 _donId
    ) FunctionsClient(router) Ownable(msg.sender) ReentrancyGuard() {
        if (msg.sender == address(0)) {
            revert OwnableInvalidOwner(msg.sender);
        }
        donId = _donId;
    }

    modifier onlyAuthorized() {
        if (!authorizedContracts[msg.sender]) {
            revert UnauthorizedContract(msg.sender);
        }
        _;
    }

    function setConfig(
        uint64 _subscriptionId,
        uint32 _callbackGasLimit,
        FunctionsRequest.Location _secretsLocation,
        bytes calldata _encryptedSecretsReference
    ) external nonReentrant onlyOwner {
        subscriptionId = _subscriptionId;
        callbackGasLimit = _callbackGasLimit;
        secretsLocation = _secretsLocation;
        encryptedSecretsReference = _encryptedSecretsReference;
    }

    function authorizeContract(address contractAddress) external nonReentrant onlyOwner {
        authorizedContracts[contractAddress] = true;
        emit ContractAuthorized(contractAddress);
    }

    function deauthorizeContract(address contractAddress) external nonReentrant onlyOwner {
        authorizedContracts[contractAddress] = false;
        emit ContractDeauthorized(contractAddress);
    }

    function isContractAuthorized(address contractAddress) external view returns (bool) {
        return authorizedContracts[contractAddress];
    }
    
    function requestComputation(
        bytes calldata data,
        bytes32 providerHash
    ) external nonReentrant onlyAuthorized returns (bytes32) {
        string memory source = getProviderSource(providerHash);
        
        FunctionsRequest.Request memory req;
        req.initializeRequest(
            FunctionsRequest.Location.Inline, // Chainlink Functions does not support external URI yet
            FunctionsRequest.CodeLanguage.JavaScript,
            source
        );
        req.secretsLocation = secretsLocation;
        req.encryptedSecretsReference = encryptedSecretsReference;
        
        string[] memory args = new string[](1);
        args[0] = string(data);
        req.setArgs(args);
        
        bytes32 requestId = _sendRequest(
            req.encodeCBOR(),
            subscriptionId,
            callbackGasLimit,
            donId
        );

        this.incrementProviderUseCount(providerHash);
        requestToRequester[requestId] = msg.sender;
        emit RequestSent(args[0]);
        return requestId;
    }

    function fulfillRequest(
        bytes32 requestId,
        bytes memory response,
        bytes memory err
    ) internal override nonReentrant {
        address requester = requestToRequester[requestId];
        require(requester != address(0), "Invalid request ID");

        if (err.length > 0) {
            emit RequestFailed(requestId, err);
        } else {
            emit OCRResponse(requestId, response);
        }

        delete requestToRequester[requestId];

        (bool success, ) = requester.call(abi.encodeWithSignature(
            "oracleCallback(bytes32,bytes,bytes)",
            requestId,
            response,
            err
        ));
        require(success, "Callback failed");
    }
}

// SPDX-License-Identifier: MIT
pragma 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 requests
abstract 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);
  }
}

// SPDX-License-Identifier: MIT
pragma 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;
}

// SPDX-License-Identifier: MIT
pragma 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;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {FunctionsResponse} from "../libraries/FunctionsResponse.sol";

/// @title Chainlink Functions Subscription interface.
interface IFunctionsSubscriptions {
  struct Subscription {
    uint96 balance; // ═════════╗ Common LINK balance that is controlled by the Router to be used for all consumer requests.
    address owner; // ══════════╝ The owner can fund/withdraw/cancel the subscription.
    uint96 blockedBalance; // ══╗ LINK balance that is reserved to pay for pending consumer requests.
    address proposedOwner; // ══╝ For safely transferring sub ownership.
    address[] consumers; // ════╸ Client contracts that can use the subscription
    bytes32 flags; // ══════════╸ Per-subscription flags
  }

  struct Consumer {
    bool allowed; // ══════════════╗ Owner can fund/withdraw/cancel the sub.
    uint64 initiatedRequests; //   ║ The number of requests that have been started
    uint64 completedRequests; // ══╝ The number of requests that have successfully completed or timed out
  }

  /// @notice Get details about a subscription.
  /// @param subscriptionId - the ID of the subscription
  /// @return subscription - see IFunctionsSubscriptions.Subscription for more information on the structure
  function getSubscription(uint64 subscriptionId) external view returns (Subscription memory);

  /// @notice Retrieve details about multiple subscriptions using an inclusive range
  /// @param subscriptionIdStart - the ID of the subscription to start the range at
  /// @param subscriptionIdEnd - the ID of the subscription to end the range at
  /// @return subscriptions - see IFunctionsSubscriptions.Subscription for more information on the structure
  function getSubscriptionsInRange(
    uint64 subscriptionIdStart,
    uint64 subscriptionIdEnd
  ) external view returns (Subscription[] memory);

  /// @notice Get details about a consumer of a subscription.
  /// @param client - the consumer contract address
  /// @param subscriptionId - the ID of the subscription
  /// @return consumer - see IFunctionsSubscriptions.Consumer for more information on the structure
  function getConsumer(address client, uint64 subscriptionId) external view returns (Consumer memory);

  /// @notice Get details about the total amount of LINK within the system
  /// @return totalBalance - total Juels of LINK held by the contract
  function getTotalBalance() external view returns (uint96);

  /// @notice Get details about the total number of subscription accounts
  /// @return count - total number of subscriptions in the system
  function getSubscriptionCount() external view returns (uint64);

  /// @notice Time out all expired requests: unlocks funds and removes the ability for the request to be fulfilled
  /// @param requestsToTimeoutByCommitment - A list of request commitments to time out
  /// @dev The commitment can be found on the "OracleRequest" event created when sending the request.
  function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external;

  /// @notice Oracle withdraw LINK earned through fulfilling requests
  /// @notice If amount is 0 the full balance will be withdrawn
  /// @notice Both signing and transmitting wallets will have a balance to withdraw
  /// @param recipient where to send the funds
  /// @param amount amount to withdraw
  function oracleWithdraw(address recipient, uint96 amount) external;

  /// @notice Owner cancel subscription, sends remaining link directly to the subscription owner.
  /// @dev Only callable by the Router Owner
  /// @param subscriptionId subscription id
  /// @dev notably can be called even if there are pending requests, outstanding ones may fail onchain
  function ownerCancelSubscription(uint64 subscriptionId) external;

  /// @notice Recover link sent with transfer instead of transferAndCall.
  /// @dev Only callable by the Router Owner
  /// @param to address to send link to
  function recoverFunds(address to) external;

  /// @notice Create a new subscription.
  /// @return subscriptionId - A unique subscription id.
  /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
  /// @dev Note to fund the subscription, use transferAndCall. For example
  /// @dev  LINKTOKEN.transferAndCall(
  /// @dev    address(ROUTER),
  /// @dev    amount,
  /// @dev    abi.encode(subscriptionId));
  function createSubscription() external returns (uint64);

  /// @notice Create a new subscription and add a consumer.
  /// @return subscriptionId - A unique subscription id.
  /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
  /// @dev Note to fund the subscription, use transferAndCall. For example
  /// @dev  LINKTOKEN.transferAndCall(
  /// @dev    address(ROUTER),
  /// @dev    amount,
  /// @dev    abi.encode(subscriptionId));
  function createSubscriptionWithConsumer(address consumer) external returns (uint64 subscriptionId);

  /// @notice Propose a new owner for a subscription.
  /// @dev Only callable by the Subscription's owner
  /// @param subscriptionId - ID of the subscription
  /// @param newOwner - proposed new owner of the subscription
  function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external;

  /// @notice Accept an ownership transfer.
  /// @param subscriptionId - ID of the subscription
  /// @dev will revert if original owner of subscriptionId has not requested that msg.sender become the new owner.
  function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external;

  /// @notice Remove a consumer from a Chainlink Functions subscription.
  /// @dev Only callable by the Subscription's owner
  /// @param subscriptionId - ID of the subscription
  /// @param consumer - Consumer to remove from the subscription
  function removeConsumer(uint64 subscriptionId, address consumer) external;

  /// @notice Add a consumer to a Chainlink Functions subscription.
  /// @dev Only callable by the Subscription's owner
  /// @param subscriptionId - ID of the subscription
  /// @param consumer - New consumer which can use the subscription
  function addConsumer(uint64 subscriptionId, address consumer) external;

  /// @notice Cancel a subscription
  /// @dev Only callable by the Subscription's owner
  /// @param subscriptionId - ID of the subscription
  /// @param to - Where to send the remaining LINK to
  function cancelSubscription(uint64 subscriptionId, address to) external;

  /// @notice Check to see if there exists a request commitment for all consumers for a given sub.
  /// @param subscriptionId - ID of the subscription
  /// @return true if there exists at least one unfulfilled request for the subscription, false otherwise.
  /// @dev Looping is bounded to MAX_CONSUMERS*(number of DONs).
  /// @dev Used to disable subscription canceling while outstanding request are present.
  function pendingRequestExists(uint64 subscriptionId) external view returns (bool);

  /// @notice Set subscription specific flags for a subscription.
  /// Each byte of the flag is used to represent a resource tier that the subscription can utilize.
  /// @param subscriptionId - ID of the subscription
  /// @param flags - desired flag values
  function setFlags(uint64 subscriptionId, bytes32 flags) external;

  /// @notice Get flags for a given subscription.
  /// @param subscriptionId - ID of the subscription
  /// @return flags - current flag values
  function getFlags(uint64 subscriptionId) external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
pragma 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 CBOR
library 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 7 of 14 : FunctionsResponse.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IFunctionsSubscriptions} from "../interfaces/IFunctionsSubscriptions.sol";

/// @title Library of types that are used for fulfillment of a Functions request
library 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
  }
}

// SPDX-License-Identifier: BSD-2-Clause
pragma 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 9 of 14 : CBOR.sol
// SPDX-License-Identifier: MIT
pragma 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));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title IProviderStorage
 * @dev Interface defining the provider storage functionality
 */
interface IProviderStorage {
    struct Provider {
        string source;
        bool isRegistered;
        uint256 registeredAt;
        uint256 lastUpdated;
        uint256 useCount;
    }

    event ProviderRegistered(bytes32 indexed providerHash);
    event ProviderUpdated(bytes32 indexed providerHash);
    event ProviderUnregistered(bytes32 indexed providerHash);

    function registerSourceProvider(string calldata source) external;
    function updateSourceProvider(bytes32 providerHash, string calldata newSource) external;
    function unregisterSourceProvider(bytes32 providerHash) external;
    function getProvider(bytes32 providerHash) external view returns (
        string memory source,
        bool isRegistered,
        uint256 registeredAt,
        uint256 lastUpdated,
        uint256 useCount
    );
    function isProviderRegistered(string calldata source) external view returns (bool);
    function incrementProviderUseCount(bytes32 providerHash) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "../interfaces/IProviderStorage.sol";

/**
 * @title AbstractProviderStorage
 * @dev Abstract contract implementing provider storage functionality
 */

abstract contract AbstractProviderStorage is IProviderStorage, Ownable {
    mapping(bytes32 => Provider) private _providers;
    bytes32[] private _providerHashes;

    modifier onlyRegistered(bytes32 providerHash) {
        require(_providers[providerHash].isRegistered, "Provider not registered");
        _;
    }

    modifier notRegistered(bytes32 providerHash) {
        require(!_providers[providerHash].isRegistered, "Provider already registered");
        _;
    }

    function registerSourceProvider(
        string calldata source
    ) external override onlyOwner {
        bytes32 hash = keccak256(abi.encodePacked(source));
        require(!_providers[hash].isRegistered, "Provider already registered");
        
        _providers[hash] = Provider({
            source: source,
            isRegistered: true,
            registeredAt: block.timestamp,
            lastUpdated: block.timestamp,
            useCount: 0
        });
        
        _providerHashes.push(hash);
        emit ProviderRegistered(hash);
    }

    function updateSourceProvider(
        bytes32 providerHash,
        string calldata newSource
    ) external override onlyOwner onlyRegistered(providerHash) {
        Provider storage provider = _providers[providerHash];
        provider.source = newSource;
        provider.lastUpdated = block.timestamp;
        
        emit ProviderUpdated(providerHash);
    }

    function unregisterSourceProvider(
        bytes32 providerHash
    ) external override onlyOwner onlyRegistered(providerHash) {
        _providers[providerHash].isRegistered = false;
        emit ProviderUnregistered(providerHash);
    }

    function getProvider(
        bytes32 providerHash
    ) external view override returns (
        string memory source,
        bool isRegistered,
        uint256 registeredAt,
        uint256 lastUpdated,
        uint256 useCount
    ) {
        Provider memory provider = _providers[providerHash];
        return (
            provider.source,
            provider.isRegistered,
            provider.registeredAt,
            provider.lastUpdated,
            provider.useCount
        );
    }

    function getProviderSource(
        bytes32 providerHash
    ) internal view returns (string memory) {
        require(_providers[providerHash].isRegistered, "Provider not registered");
        return _providers[providerHash].source;
    }

    function isProviderRegistered(
        string calldata source
    ) external view override returns (bool) {
        bytes32 hash = keccak256(abi.encodePacked(source));
        return _providers[hash].isRegistered;
    }

    function incrementProviderUseCount(
        bytes32 providerHash
    ) external override onlyRegistered(providerHash) {
        _providers[providerHash].useCount++;
    }

    function getProviderCount() public view returns (uint256) {
        return _providerHashes.length;
    }

    function getProviderHashAt(uint256 index) public view returns (bytes32) {
        require(index < _providerHashes.length, "Index out of bounds");
        return _providerHashes[index];
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"bytes32","name":"_donId","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyArgs","type":"error"},{"inputs":[],"name":"EmptySource","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":"address","name":"caller","type":"address"}],"name":"UnauthorizedContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"ContractAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"ContractDeauthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"response","type":"bytes"}],"name":"OCRResponse","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":"providerHash","type":"bytes32"}],"name":"ProviderRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"providerHash","type":"bytes32"}],"name":"ProviderUnregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"providerHash","type":"bytes32"}],"name":"ProviderUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"err","type":"bytes"}],"name":"RequestFailed","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":false,"internalType":"string","name":"data","type":"string"}],"name":"RequestSent","type":"event"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"authorizeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorizedContracts","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callbackGasLimit","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"deauthorizeContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"donId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"encryptedSecretsReference","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"providerHash","type":"bytes32"}],"name":"getProvider","outputs":[{"internalType":"string","name":"source","type":"string"},{"internalType":"bool","name":"isRegistered","type":"bool"},{"internalType":"uint256","name":"registeredAt","type":"uint256"},{"internalType":"uint256","name":"lastUpdated","type":"uint256"},{"internalType":"uint256","name":"useCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProviderCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getProviderHashAt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":[{"internalType":"bytes32","name":"providerHash","type":"bytes32"}],"name":"incrementProviderUseCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"isContractAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"source","type":"string"}],"name":"isProviderRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"source","type":"string"}],"name":"registerSourceProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"providerHash","type":"bytes32"}],"name":"requestComputation","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestToRequester","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secretsLocation","outputs":[{"internalType":"enum FunctionsRequest.Location","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_subscriptionId","type":"uint64"},{"internalType":"uint32","name":"_callbackGasLimit","type":"uint32"},{"internalType":"enum FunctionsRequest.Location","name":"_secretsLocation","type":"uint8"},{"internalType":"bytes","name":"_encryptedSecretsReference","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscriptionId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"providerHash","type":"bytes32"}],"name":"unregisterSourceProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"providerHash","type":"bytes32"},{"internalType":"string","name":"newSource","type":"string"}],"name":"updateSourceProvider","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b5060405162002c6c38038062002c6c8339810160408190526200003491620000f6565b8133806200005d57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6200006881620000a6565b506001600160a01b03166080526001600355336200009c57604051631e4fbdf760e01b815233600482015260240162000054565b6004555062000132565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080604083850312156200010a57600080fd5b82516001600160a01b03811681146200012257600080fd5b6020939093015192949293505050565b608051612b17620001556000396000818161046d0152611af80152612b176000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c80636e861c0e116100e3578063b9bdccf31161008c578063d5b9221b11610066578063d5b9221b1461040c578063e93ce74f1461042f578063f2fde38b1461044257600080fd5b8063b9bdccf3146103d1578063bf8a793f146103e4578063cdc634f1146103f757600080fd5b80638da5cb5b116100bd5780638da5cb5b146103975780638dbe7b9d146103b5578063abb08b3f146103be57600080fd5b80636e861c0e14610369578063715018a61461037c57806388405e6c1461038457600080fd5b806333c0950a1161014557806346ce41751161011f57806346ce41751461033b578063603ea4981461034357806367561d931461035657600080fd5b806333c0950a146102a95780633f66286a146102cd57806345e1fa0d1461032857600080fd5b8063103aeda711610176578063103aeda71461020e57806324f74697146102575780632f73bab81461028857600080fd5b806309c1ba2e1461019d5780630ca76175146101cf5780630e599a73146101e4575b600080fd5b6005546101b19067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6101e26101dd366004612171565b610455565b005b600554610201906c01000000000000000000000000900460ff1681565b6040516101c6919061220d565b61024761021c36600461224e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205460ff1690565b60405190151581526020016101c6565b6005546102739068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016101c6565b61029b610296366004612284565b6104ff565b6040519081526020016101c6565b6102bc6102b7366004612284565b610597565b6040516101c695949392919061230b565b6103036102db366004612284565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c6565b6101e261033636600461238b565b6106b9565b60025461029b565b6101e26103513660046123cd565b6108c2565b6101e261036436600461224e565b610985565b6101e261037736600461224e565b610a16565b6101e2610aa1565b61024761039236600461238b565b610ab5565b60005473ffffffffffffffffffffffffffffffffffffffff16610303565b61029b60045481565b6101e26103cc366004612463565b610b1c565b61029b6103df3660046124af565b610bf5565b6101e26103f2366004612284565b610f45565b6103ff61102f565b6040516101c691906124fb565b61024761041a36600461224e565b60086020526000908152604090205460ff1681565b6101e261043d366004612284565b6110bd565b6101e261045036600461224e565b611161565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146104c4576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104cf8383836111c2565b60405183907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a2505050565b6002546000908210610572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496e646578206f7574206f6620626f756e64730000000000000000000000000060448201526064015b60405180910390fd5b600282815481106105855761058561250e565b90600052602060002001549050919050565b60606000806000806000600160008881526020019081526020016000206040518060a00160405290816000820180546105cf9061253d565b80601f01602080910402602001604051908101604052809291908181526020018280546105fb9061253d565b80156106485780601f1061061d57610100808354040283529160200191610648565b820191906000526020600020905b81548152906001019060200180831161062b57829003601f168201915b505050505081526020016001820160009054906101000a900460ff161515151581526020016002820154815260200160038201548152602001600482015481525050905080600001518160200151826040015183606001518460800151955095509550955095505091939590929450565b6106c1611472565b600082826040516020016106d6929190612590565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600193849052919091209091015490915060ff161561078c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f50726f766964657220616c7265616479207265676973746572656400000000006044820152606401610569565b6040518060a0016040528084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060016020808501829052426040808701829052606087019190915260809095018490528684525250208151819061080590826125ee565b506020820151600182810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692151592909217909155604080840151600280850191909155606085015160038501556080909401516004909301929092558254908101835560009283527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace018390555182917f32dfc590cafade73cbba6680180fc790a94eb0cfa92a3186559d6fb8864101dd91a2505050565b6108ca6114c5565b6108d2611472565b6005805463ffffffff861668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911667ffffffffffffffff881617178082558491907fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff166c01000000000000000000000000836002811115610961576109616121de565b02179055506006610973828483612708565b5061097e6001600355565b5050505050565b61098d6114c5565b610995611472565b73ffffffffffffffffffffffffffffffffffffffff811660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f8983a1f3c3cb45c24c8226b5b805e3b6eb49686530b808534b2a920129eff6519190a2610a136001600355565b50565b610a1e6114c5565b610a26611472565b73ffffffffffffffffffffffffffffffffffffffff811660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f54142b7cb3ceaa9e564243ce4cc2303723c842a1144192de6b3c594f68b16a9a9190a2610a136001600355565b610aa9611472565b610ab36000611508565b565b6000808383604051602001610acb929190612590565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120600090815260019283905220015460ff169150505b92915050565b610b24611472565b60008381526001602081905260409091200154839060ff16610ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600084815260016020526040902080610bbc848683612708565b5042600382015560405185907f04ed8331e86b605a92965a0cf623cd7bf9a5cd75ca23c4a139245bca110b59f390600090a25050505050565b6000610bff6114c5565b3360009081526008602052604090205460ff16610c4a576040517fe195aa13000000000000000000000000000000000000000000000000000000008152336004820152602401610569565b6000610c558361157d565b9050610c986040805160e0810190915280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b610ca5816000808561169a565b60055460208201906c01000000000000000000000000900460ff166002811115610cd157610cd16121de565b90816002811115610ce457610ce46121de565b90525060068054610cf49061253d565b80601f0160208091040260200160405190810160405280929190818152602001828054610d209061253d565b8015610d6d5780601f10610d4257610100808354040283529160200191610d6d565b820191906000526020600020905b815481529060010190602001808311610d5057829003601f168201915b50505050506080820152604080516001808252818301909252600091816020015b6060815260200190600190039081610d8e57905050905086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250855186945090925015159050610def57610def61250e565b6020908102919091010152610e048282611731565b6000610e3c610e1284611774565b60055460045467ffffffffffffffff82169168010000000000000000900463ffffffff1690611af3565b6040517fe93ce74f00000000000000000000000000000000000000000000000000000000815260048101889052909150309063e93ce74f90602401600060405180830381600087803b158015610e9157600080fd5b505af1158015610ea5573d6000803e3d6000fd5b505050600082815260076020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905583517f7843201bc61dabd0c5d1ae50c3c5f42890f52e0e4499eb70174606c2b6686dab9250849190610f1257610f1261250e565b6020026020010151604051610f2791906124fb565b60405180910390a19350505050610f3e6001600355565b9392505050565b610f4d611472565b60008181526001602081905260409091200154819060ff16610fcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600082815260016020819052604080832090910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555183917fd1983ea33649b47070f29135589ec31ac5dc7eab4e3882668d50929807b6f68691a25050565b6006805461103c9061253d565b80601f01602080910402602001604051908101604052809291908181526020018280546110689061253d565b80156110b55780601f1061108a576101008083540402835291602001916110b5565b820191906000526020600020905b81548152906001019060200180831161109857829003601f168201915b505050505081565b60008181526001602081905260409091200154819060ff1661113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600082815260016020526040812060040180549161115883612851565b91905055505050565b611169611472565b73ffffffffffffffffffffffffffffffffffffffff81166111b9576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610569565b610a1381611508565b6111ca6114c5565b60008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611256576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c6964207265717565737420494400000000000000000000000000006044820152606401610569565b81511561129a57837f61982c98cbc49d11759a948f460b92bca26bdf12ceee12c310f117eb2ca9a9cb8360405161128d91906124fb565b60405180910390a26112d3565b837f1f4509cd59b6c74633bed4200a8e35803ebaa37d5d0e229640ed5fce1200b053846040516112ca91906124fb565b60405180910390a25b60008481526007602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555173ffffffffffffffffffffffffffffffffffffffff83169061133390879087908790602401612889565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe3afe37200000000000000000000000000000000000000000000000000000000179052516113b491906128be565b6000604051808303816000865af19150503d80600081146113f1576040519150601f19603f3d011682016040523d82523d6000602084013e6113f6565b606091505b5050905080611461576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f43616c6c6261636b206661696c656400000000000000000000000000000000006044820152606401610569565b505061146d6001600355565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ab3576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610569565b600260035403611501576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600355565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000818152600160208190526040909120015460609060ff166115fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600082815260016020526040902080546116159061253d565b80601f01602080910402602001604051908101604052809291908181526020018280546116419061253d565b801561168e5780601f106116635761010080835404028352916020019161168e565b820191906000526020600020905b81548152906001019060200180831161167157829003601f168201915b50505050509050919050565b80516000036116d5576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838360028111156116e8576116e86121de565b908160028111156116fb576116fb6121de565b90525060408401828015611711576117116121de565b90818015611721576117216121de565b9052506060909301929092525050565b805160000361176c576040517ffe936cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a090910152565b60606000611783610100611bd2565b90506117cd6040518060400160405280600c81526020017f636f64654c6f636174696f6e000000000000000000000000000000000000000081525082611bf390919063ffffffff16565b82516117eb9060028111156117e4576117e46121de565b8290611c0c565b60408051808201909152600881527f6c616e6775616765000000000000000000000000000000000000000000000000602082015261182a908290611bf3565b60408301516118419080156117e4576117e46121de565b60408051808201909152600681527f736f7572636500000000000000000000000000000000000000000000000000006020820152611880908290611bf3565b6060830151611890908290611bf3565b60a0830151511561193d5760408051808201909152600481527f617267730000000000000000000000000000000000000000000000000000000060208201526118da908290611bf3565b6118e381611c49565b60005b8360a0015151811015611933576119238460a00151828151811061190c5761190c61250e565b602002602001015183611bf390919063ffffffff16565b61192c81612851565b90506118e6565b5061193d81611c6d565b60808301515115611a3e57600083602001516002811115611960576119606121de565b03611997576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152600f81527f736563726574734c6f636174696f6e000000000000000000000000000000000060208201526119d6908290611bf3565b6119ef836020015160028111156117e4576117e46121de565b60408051808201909152600781527f73656372657473000000000000000000000000000000000000000000000000006020820152611a2e908290611bf3565b6080830151611a3e908290611c8b565b60c08301515115611aeb5760408051808201909152600981527f62797465734172677300000000000000000000000000000000000000000000006020820152611a88908290611bf3565b611a9181611c49565b60005b8360c0015151811015611ae157611ad18460c001518281518110611aba57611aba61250e565b602002602001015183611c8b90919063ffffffff16565b611ada81612851565b9050611a94565b50611aeb81611c6d565b515192915050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663461d27628688600188886040518663ffffffff1660e01b8152600401611b589594939291906128da565b6020604051808303816000875af1158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b9190612924565b60405190915081907f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db890600090a295945050505050565b611bda612062565b8051611be69083611c98565b5060006020820152919050565b611c008260038351611d0f565b815161146d9082611e36565b8151611c199060c2611e57565b50611c458282604051602001611c3191815260200190565b604051602081830303815290604052611c8b565b5050565b611c54816004611ec0565b600181602001818151611c67919061293d565b90525050565b611c78816007611ec0565b600181602001818151611c679190612950565b611c008260028351611d0f565b604080518082019091526060815260006020820152611cb8602083612963565b15611ce057611cc8602083612963565b611cd3906020612950565b611cdd908361293d565b91505b602080840183905260405180855260008152908184010181811015611d0457600080fd5b604052509192915050565b60178167ffffffffffffffff1611611d3c578251611d369060e0600585901b168317611e57565b50505050565b60ff8167ffffffffffffffff1611611d7e578251611d65906018611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166001611ed7565b61ffff8167ffffffffffffffff1611611dc1578251611da8906019611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166002611ed7565b63ffffffff8167ffffffffffffffff1611611e06578251611ded90601a611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166004611ed7565b8251611e1d90601b611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166008611ed7565b604080518082019091526060815260006020820152610f3e83838451611f5c565b6040805180820190915260608152600060208201528251516000611e7c82600161293d565b905084602001518210611e9d57611e9d85611e9883600261299e565b61204b565b8451602083820101858153508051821115611eb6578181525b5093949350505050565b815161146d90601f611fe0600585901b1617611e57565b6040805180820190915260608152600060208201528351516000611efb828561293d565b90508560200151811115611f1857611f1886611e9883600261299e565b60006001611f2886610100612ad5565b611f329190612950565b90508651828101878319825116178152508051831115611f50578281525b50959695505050505050565b6040805180820190915260608152600060208201528251821115611f7f57600080fd5b8351516000611f8e848361293d565b90508560200151811115611fab57611fab86611e9883600261299e565b855180518382016020019160009180851115611fc5578482525b505050602086015b602086106120055780518252611fe460208361293d565b9150611ff160208261293d565b9050611ffe602087612950565b9550611fcd565b5181517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208890036101000a0190811690199190911617905250849150509392505050565b81516120578383611c98565b50611d368382611e36565b604051806040016040528061208a604051806040016040528060608152602001600081525090565b8152602001600081525090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126120d757600080fd5b813567ffffffffffffffff808211156120f2576120f2612097565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561213857612138612097565b8160405283815286602085880101111561215157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561218657600080fd5b83359250602084013567ffffffffffffffff808211156121a557600080fd5b6121b1878388016120c6565b935060408601359150808211156121c757600080fd5b506121d4868287016120c6565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310612248577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60006020828403121561226057600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f3e57600080fd5b60006020828403121561229657600080fd5b5035919050565b60005b838110156122b85781810151838201526020016122a0565b50506000910152565b600081518084526122d981602086016020860161229d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60a08152600061231e60a08301886122c1565b95151560208301525060408101939093526060830191909152608090910152919050565b60008083601f84011261235457600080fd5b50813567ffffffffffffffff81111561236c57600080fd5b60208301915083602082850101111561238457600080fd5b9250929050565b6000806020838503121561239e57600080fd5b823567ffffffffffffffff8111156123b557600080fd5b6123c185828601612342565b90969095509350505050565b6000806000806000608086880312156123e557600080fd5b853567ffffffffffffffff80821682146123fe57600080fd5b90955060208701359063ffffffff8216821461241957600080fd5b9094506040870135906003821061242f57600080fd5b9093506060870135908082111561244557600080fd5b5061245288828901612342565b969995985093965092949392505050565b60008060006040848603121561247857600080fd5b83359250602084013567ffffffffffffffff81111561249657600080fd5b6124a286828701612342565b9497909650939450505050565b6000806000604084860312156124c457600080fd5b833567ffffffffffffffff8111156124db57600080fd5b6124e786828701612342565b909790965060209590950135949350505050565b602081526000610f3e60208301846122c1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061255157607f821691505b60208210810361258a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b601f82111561146d57600081815260208120601f850160051c810160208610156125c75750805b601f850160051c820191505b818110156125e6578281556001016125d3565b505050505050565b815167ffffffffffffffff81111561260857612608612097565b61261c81612616845461253d565b846125a0565b602080601f83116001811461266f57600084156126395750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556125e6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156126bc5788860151825594840194600190910190840161269d565b50858210156126f857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83111561272057612720612097565b6127348361272e835461253d565b836125a0565b6000601f84116001811461278657600085156127505750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561097e565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156127d557868501358255602094850194600190920191016127b5565b5086821015612810577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361288257612882612822565b5060010190565b8381526060602082015260006128a260608301856122c1565b82810360408401526128b481856122c1565b9695505050505050565b600082516128d081846020870161229d565b9190910192915050565b67ffffffffffffffff8616815260a0602082015260006128fd60a08301876122c1565b61ffff9590951660408301525063ffffffff92909216606083015260809091015292915050565b60006020828403121561293657600080fd5b5051919050565b80820180821115610b1657610b16612822565b81810381811115610b1657610b16612822565b600082612999577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b8082028115828204841417610b1657610b16612822565b600181815b80851115612a0e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156129f4576129f4612822565b80851615612a0157918102915b93841c93908002906129ba565b509250929050565b600082612a2557506001610b16565b81612a3257506000610b16565b8160018114612a485760028114612a5257612a6e565b6001915050610b16565b60ff841115612a6357612a63612822565b50506001821b610b16565b5060208310610133831016604e8410600b8410161715612a91575081810a610b16565b612a9b83836129b5565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612acd57612acd612822565b029392505050565b6000610f3e8383612a1656fea26469706673582212204a59c2c94091df94e912671f7857f939625a9341b267ee98ae19778cdf89ae7664736f6c63430008140033000000000000000000000000b83e47c2bc239b3bf370bc41e1459a34b41238d066756e2d657468657265756d2d7365706f6c69612d3100000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101985760003560e01c80636e861c0e116100e3578063b9bdccf31161008c578063d5b9221b11610066578063d5b9221b1461040c578063e93ce74f1461042f578063f2fde38b1461044257600080fd5b8063b9bdccf3146103d1578063bf8a793f146103e4578063cdc634f1146103f757600080fd5b80638da5cb5b116100bd5780638da5cb5b146103975780638dbe7b9d146103b5578063abb08b3f146103be57600080fd5b80636e861c0e14610369578063715018a61461037c57806388405e6c1461038457600080fd5b806333c0950a1161014557806346ce41751161011f57806346ce41751461033b578063603ea4981461034357806367561d931461035657600080fd5b806333c0950a146102a95780633f66286a146102cd57806345e1fa0d1461032857600080fd5b8063103aeda711610176578063103aeda71461020e57806324f74697146102575780632f73bab81461028857600080fd5b806309c1ba2e1461019d5780630ca76175146101cf5780630e599a73146101e4575b600080fd5b6005546101b19067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6101e26101dd366004612171565b610455565b005b600554610201906c01000000000000000000000000900460ff1681565b6040516101c6919061220d565b61024761021c36600461224e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205460ff1690565b60405190151581526020016101c6565b6005546102739068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016101c6565b61029b610296366004612284565b6104ff565b6040519081526020016101c6565b6102bc6102b7366004612284565b610597565b6040516101c695949392919061230b565b6103036102db366004612284565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c6565b6101e261033636600461238b565b6106b9565b60025461029b565b6101e26103513660046123cd565b6108c2565b6101e261036436600461224e565b610985565b6101e261037736600461224e565b610a16565b6101e2610aa1565b61024761039236600461238b565b610ab5565b60005473ffffffffffffffffffffffffffffffffffffffff16610303565b61029b60045481565b6101e26103cc366004612463565b610b1c565b61029b6103df3660046124af565b610bf5565b6101e26103f2366004612284565b610f45565b6103ff61102f565b6040516101c691906124fb565b61024761041a36600461224e565b60086020526000908152604090205460ff1681565b6101e261043d366004612284565b6110bd565b6101e261045036600461224e565b611161565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b83e47c2bc239b3bf370bc41e1459a34b41238d016146104c4576040517fc6829f8300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104cf8383836111c2565b60405183907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a2505050565b6002546000908210610572576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496e646578206f7574206f6620626f756e64730000000000000000000000000060448201526064015b60405180910390fd5b600282815481106105855761058561250e565b90600052602060002001549050919050565b60606000806000806000600160008881526020019081526020016000206040518060a00160405290816000820180546105cf9061253d565b80601f01602080910402602001604051908101604052809291908181526020018280546105fb9061253d565b80156106485780601f1061061d57610100808354040283529160200191610648565b820191906000526020600020905b81548152906001019060200180831161062b57829003601f168201915b505050505081526020016001820160009054906101000a900460ff161515151581526020016002820154815260200160038201548152602001600482015481525050905080600001518160200151826040015183606001518460800151955095509550955095505091939590929450565b6106c1611472565b600082826040516020016106d6929190612590565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600193849052919091209091015490915060ff161561078c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f50726f766964657220616c7265616479207265676973746572656400000000006044820152606401610569565b6040518060a0016040528084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060016020808501829052426040808701829052606087019190915260809095018490528684525250208151819061080590826125ee565b506020820151600182810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001692151592909217909155604080840151600280850191909155606085015160038501556080909401516004909301929092558254908101835560009283527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace018390555182917f32dfc590cafade73cbba6680180fc790a94eb0cfa92a3186559d6fb8864101dd91a2505050565b6108ca6114c5565b6108d2611472565b6005805463ffffffff861668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911667ffffffffffffffff881617178082558491907fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff166c01000000000000000000000000836002811115610961576109616121de565b02179055506006610973828483612708565b5061097e6001600355565b5050505050565b61098d6114c5565b610995611472565b73ffffffffffffffffffffffffffffffffffffffff811660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f8983a1f3c3cb45c24c8226b5b805e3b6eb49686530b808534b2a920129eff6519190a2610a136001600355565b50565b610a1e6114c5565b610a26611472565b73ffffffffffffffffffffffffffffffffffffffff811660008181526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f54142b7cb3ceaa9e564243ce4cc2303723c842a1144192de6b3c594f68b16a9a9190a2610a136001600355565b610aa9611472565b610ab36000611508565b565b6000808383604051602001610acb929190612590565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181528151602092830120600090815260019283905220015460ff169150505b92915050565b610b24611472565b60008381526001602081905260409091200154839060ff16610ba2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600084815260016020526040902080610bbc848683612708565b5042600382015560405185907f04ed8331e86b605a92965a0cf623cd7bf9a5cd75ca23c4a139245bca110b59f390600090a25050505050565b6000610bff6114c5565b3360009081526008602052604090205460ff16610c4a576040517fe195aa13000000000000000000000000000000000000000000000000000000008152336004820152602401610569565b6000610c558361157d565b9050610c986040805160e0810190915280600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b610ca5816000808561169a565b60055460208201906c01000000000000000000000000900460ff166002811115610cd157610cd16121de565b90816002811115610ce457610ce46121de565b90525060068054610cf49061253d565b80601f0160208091040260200160405190810160405280929190818152602001828054610d209061253d565b8015610d6d5780601f10610d4257610100808354040283529160200191610d6d565b820191906000526020600020905b815481529060010190602001808311610d5057829003601f168201915b50505050506080820152604080516001808252818301909252600091816020015b6060815260200190600190039081610d8e57905050905086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250855186945090925015159050610def57610def61250e565b6020908102919091010152610e048282611731565b6000610e3c610e1284611774565b60055460045467ffffffffffffffff82169168010000000000000000900463ffffffff1690611af3565b6040517fe93ce74f00000000000000000000000000000000000000000000000000000000815260048101889052909150309063e93ce74f90602401600060405180830381600087803b158015610e9157600080fd5b505af1158015610ea5573d6000803e3d6000fd5b505050600082815260076020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905583517f7843201bc61dabd0c5d1ae50c3c5f42890f52e0e4499eb70174606c2b6686dab9250849190610f1257610f1261250e565b6020026020010151604051610f2791906124fb565b60405180910390a19350505050610f3e6001600355565b9392505050565b610f4d611472565b60008181526001602081905260409091200154819060ff16610fcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600082815260016020819052604080832090910180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555183917fd1983ea33649b47070f29135589ec31ac5dc7eab4e3882668d50929807b6f68691a25050565b6006805461103c9061253d565b80601f01602080910402602001604051908101604052809291908181526020018280546110689061253d565b80156110b55780601f1061108a576101008083540402835291602001916110b5565b820191906000526020600020905b81548152906001019060200180831161109857829003601f168201915b505050505081565b60008181526001602081905260409091200154819060ff1661113b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600082815260016020526040812060040180549161115883612851565b91905055505050565b611169611472565b73ffffffffffffffffffffffffffffffffffffffff81166111b9576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610569565b610a1381611508565b6111ca6114c5565b60008381526007602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611256576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c6964207265717565737420494400000000000000000000000000006044820152606401610569565b81511561129a57837f61982c98cbc49d11759a948f460b92bca26bdf12ceee12c310f117eb2ca9a9cb8360405161128d91906124fb565b60405180910390a26112d3565b837f1f4509cd59b6c74633bed4200a8e35803ebaa37d5d0e229640ed5fce1200b053846040516112ca91906124fb565b60405180910390a25b60008481526007602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555173ffffffffffffffffffffffffffffffffffffffff83169061133390879087908790602401612889565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe3afe37200000000000000000000000000000000000000000000000000000000179052516113b491906128be565b6000604051808303816000865af19150503d80600081146113f1576040519150601f19603f3d011682016040523d82523d6000602084013e6113f6565b606091505b5050905080611461576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f43616c6c6261636b206661696c656400000000000000000000000000000000006044820152606401610569565b505061146d6001600355565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ab3576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610569565b600260035403611501576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600355565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000818152600160208190526040909120015460609060ff166115fc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f50726f7669646572206e6f7420726567697374657265640000000000000000006044820152606401610569565b600082815260016020526040902080546116159061253d565b80601f01602080910402602001604051908101604052809291908181526020018280546116419061253d565b801561168e5780601f106116635761010080835404028352916020019161168e565b820191906000526020600020905b81548152906001019060200180831161167157829003601f168201915b50505050509050919050565b80516000036116d5576040517f22ce3edd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b838360028111156116e8576116e86121de565b908160028111156116fb576116fb6121de565b90525060408401828015611711576117116121de565b90818015611721576117216121de565b9052506060909301929092525050565b805160000361176c576040517ffe936cb700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a090910152565b60606000611783610100611bd2565b90506117cd6040518060400160405280600c81526020017f636f64654c6f636174696f6e000000000000000000000000000000000000000081525082611bf390919063ffffffff16565b82516117eb9060028111156117e4576117e46121de565b8290611c0c565b60408051808201909152600881527f6c616e6775616765000000000000000000000000000000000000000000000000602082015261182a908290611bf3565b60408301516118419080156117e4576117e46121de565b60408051808201909152600681527f736f7572636500000000000000000000000000000000000000000000000000006020820152611880908290611bf3565b6060830151611890908290611bf3565b60a0830151511561193d5760408051808201909152600481527f617267730000000000000000000000000000000000000000000000000000000060208201526118da908290611bf3565b6118e381611c49565b60005b8360a0015151811015611933576119238460a00151828151811061190c5761190c61250e565b602002602001015183611bf390919063ffffffff16565b61192c81612851565b90506118e6565b5061193d81611c6d565b60808301515115611a3e57600083602001516002811115611960576119606121de565b03611997576040517fa80d31f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201909152600f81527f736563726574734c6f636174696f6e000000000000000000000000000000000060208201526119d6908290611bf3565b6119ef836020015160028111156117e4576117e46121de565b60408051808201909152600781527f73656372657473000000000000000000000000000000000000000000000000006020820152611a2e908290611bf3565b6080830151611a3e908290611c8b565b60c08301515115611aeb5760408051808201909152600981527f62797465734172677300000000000000000000000000000000000000000000006020820152611a88908290611bf3565b611a9181611c49565b60005b8360c0015151811015611ae157611ad18460c001518281518110611aba57611aba61250e565b602002602001015183611c8b90919063ffffffff16565b611ada81612851565b9050611a94565b50611aeb81611c6d565b515192915050565b6000807f000000000000000000000000b83e47c2bc239b3bf370bc41e1459a34b41238d073ffffffffffffffffffffffffffffffffffffffff1663461d27628688600188886040518663ffffffff1660e01b8152600401611b589594939291906128da565b6020604051808303816000875af1158015611b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b9b9190612924565b60405190915081907f1131472297a800fee664d1d89cfa8f7676ff07189ecc53f80bbb5f4969099db890600090a295945050505050565b611bda612062565b8051611be69083611c98565b5060006020820152919050565b611c008260038351611d0f565b815161146d9082611e36565b8151611c199060c2611e57565b50611c458282604051602001611c3191815260200190565b604051602081830303815290604052611c8b565b5050565b611c54816004611ec0565b600181602001818151611c67919061293d565b90525050565b611c78816007611ec0565b600181602001818151611c679190612950565b611c008260028351611d0f565b604080518082019091526060815260006020820152611cb8602083612963565b15611ce057611cc8602083612963565b611cd3906020612950565b611cdd908361293d565b91505b602080840183905260405180855260008152908184010181811015611d0457600080fd5b604052509192915050565b60178167ffffffffffffffff1611611d3c578251611d369060e0600585901b168317611e57565b50505050565b60ff8167ffffffffffffffff1611611d7e578251611d65906018611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166001611ed7565b61ffff8167ffffffffffffffff1611611dc1578251611da8906019611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166002611ed7565b63ffffffff8167ffffffffffffffff1611611e06578251611ded90601a611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166004611ed7565b8251611e1d90601b611fe0600586901b1617611e57565b508251611d369067ffffffffffffffff83166008611ed7565b604080518082019091526060815260006020820152610f3e83838451611f5c565b6040805180820190915260608152600060208201528251516000611e7c82600161293d565b905084602001518210611e9d57611e9d85611e9883600261299e565b61204b565b8451602083820101858153508051821115611eb6578181525b5093949350505050565b815161146d90601f611fe0600585901b1617611e57565b6040805180820190915260608152600060208201528351516000611efb828561293d565b90508560200151811115611f1857611f1886611e9883600261299e565b60006001611f2886610100612ad5565b611f329190612950565b90508651828101878319825116178152508051831115611f50578281525b50959695505050505050565b6040805180820190915260608152600060208201528251821115611f7f57600080fd5b8351516000611f8e848361293d565b90508560200151811115611fab57611fab86611e9883600261299e565b855180518382016020019160009180851115611fc5578482525b505050602086015b602086106120055780518252611fe460208361293d565b9150611ff160208261293d565b9050611ffe602087612950565b9550611fcd565b5181517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60208890036101000a0190811690199190911617905250849150509392505050565b81516120578383611c98565b50611d368382611e36565b604051806040016040528061208a604051806040016040528060608152602001600081525090565b8152602001600081525090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126120d757600080fd5b813567ffffffffffffffff808211156120f2576120f2612097565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561213857612138612097565b8160405283815286602085880101111561215157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561218657600080fd5b83359250602084013567ffffffffffffffff808211156121a557600080fd5b6121b1878388016120c6565b935060408601359150808211156121c757600080fd5b506121d4868287016120c6565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310612248577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60006020828403121561226057600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f3e57600080fd5b60006020828403121561229657600080fd5b5035919050565b60005b838110156122b85781810151838201526020016122a0565b50506000910152565b600081518084526122d981602086016020860161229d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60a08152600061231e60a08301886122c1565b95151560208301525060408101939093526060830191909152608090910152919050565b60008083601f84011261235457600080fd5b50813567ffffffffffffffff81111561236c57600080fd5b60208301915083602082850101111561238457600080fd5b9250929050565b6000806020838503121561239e57600080fd5b823567ffffffffffffffff8111156123b557600080fd5b6123c185828601612342565b90969095509350505050565b6000806000806000608086880312156123e557600080fd5b853567ffffffffffffffff80821682146123fe57600080fd5b90955060208701359063ffffffff8216821461241957600080fd5b9094506040870135906003821061242f57600080fd5b9093506060870135908082111561244557600080fd5b5061245288828901612342565b969995985093965092949392505050565b60008060006040848603121561247857600080fd5b83359250602084013567ffffffffffffffff81111561249657600080fd5b6124a286828701612342565b9497909650939450505050565b6000806000604084860312156124c457600080fd5b833567ffffffffffffffff8111156124db57600080fd5b6124e786828701612342565b909790965060209590950135949350505050565b602081526000610f3e60208301846122c1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061255157607f821691505b60208210810361258a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b601f82111561146d57600081815260208120601f850160051c810160208610156125c75750805b601f850160051c820191505b818110156125e6578281556001016125d3565b505050505050565b815167ffffffffffffffff81111561260857612608612097565b61261c81612616845461253d565b846125a0565b602080601f83116001811461266f57600084156126395750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556125e6565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156126bc5788860151825594840194600190910190840161269d565b50858210156126f857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83111561272057612720612097565b6127348361272e835461253d565b836125a0565b6000601f84116001811461278657600085156127505750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561097e565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156127d557868501358255602094850194600190920191016127b5565b5086821015612810577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361288257612882612822565b5060010190565b8381526060602082015260006128a260608301856122c1565b82810360408401526128b481856122c1565b9695505050505050565b600082516128d081846020870161229d565b9190910192915050565b67ffffffffffffffff8616815260a0602082015260006128fd60a08301876122c1565b61ffff9590951660408301525063ffffffff92909216606083015260809091015292915050565b60006020828403121561293657600080fd5b5051919050565b80820180821115610b1657610b16612822565b81810381811115610b1657610b16612822565b600082612999577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b8082028115828204841417610b1657610b16612822565b600181815b80851115612a0e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156129f4576129f4612822565b80851615612a0157918102915b93841c93908002906129ba565b509250929050565b600082612a2557506001610b16565b81612a3257506000610b16565b8160018114612a485760028114612a5257612a6e565b6001915050610b16565b60ff841115612a6357612a63612822565b50506001821b610b16565b5060208310610133831016604e8410600b8410161715612a91575081810a610b16565b612a9b83836129b5565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612acd57612acd612822565b029392505050565b6000610f3e8383612a1656fea26469706673582212204a59c2c94091df94e912671f7857f939625a9341b267ee98ae19778cdf89ae7664736f6c63430008140033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000b83e47c2bc239b3bf370bc41e1459a34b41238d066756e2d657468657265756d2d7365706f6c69612d3100000000000000000000

-----Decoded View---------------
Arg [0] : router (address): 0xb83E47C2bC239B3bf370bc41e1459A34b41238D0
Arg [1] : _donId (bytes32): 0x66756e2d657468657265756d2d7365706f6c69612d3100000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b83e47c2bc239b3bf370bc41e1459a34b41238d0
Arg [1] : 66756e2d657468657265756d2d7365706f6c69612d3100000000000000000000


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
0x996C2D45D53C393fC7Eb6E00a3950061F54b26e7
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.