Skip to content

Commit

Permalink
AI comments added
Browse files Browse the repository at this point in the history
  • Loading branch information
zapaz committed Nov 4, 2024
1 parent 7ab5a9f commit ee6b8e9
Showing 1 changed file with 77 additions and 3 deletions.
80 changes: 77 additions & 3 deletions foundry/src/OnChainAIv1.sol
Original file line number Diff line number Diff line change
@@ -1,25 +1,57 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import {FunctionsRequest} from "@chainlink/functions/v1_0_0/libraries/FunctionsRequest.sol";
import {FunctionsClient} from "@chainlink/functions/v1_0_0/FunctionsClient.sol";
import {ConfirmedOwner} from "@chainlink/shared/access/ConfirmedOwner.sol";
import {FunctionsRequest} from "@chainlink/functions/v1_0_0/libraries/FunctionsRequest.sol";

/// @title OnChainAIv1 Contract
/// @notice A smart contract that interacts with Chainlink Functions to process AI requests on-chain.
/// @dev Inherits from FunctionsClient and ConfirmedOwner contracts.
contract OnChainAIv1 is FunctionsClient, ConfirmedOwner {
using FunctionsRequest for FunctionsRequest.Request;

/// @notice Error thrown when there are no valid secrets available.
error NoValidSecrets();

/// @notice Error thrown when the user prompt is empty.
error NoEmptyPrompt();

/// @notice Error thrown when the withdrawal fails.
/// @param receiver The address of the receiver.
/// @param balance The balance attempted to withdraw.
error WithdrawFailed(address receiver, uint256 balance);

/// @notice Error thrown when the payment amount is incorrect.
/// @param expected The expected payment amount.
/// @param actual The actual payment amount received.
error PaymentRequired(uint256 expected, uint256 actual);

/// @notice Error thrown when an unexpected fulfillRequest occurs.
/// @param expected The expected request ID.
/// @param response The response data.
/// @param err The error message.
error UnexpectedFullfillRequest(bytes32 expected, string response, string err);

/// @notice Emitted when the JavaScript code is updated.
/// @param javascript The new JavaScript code.
event JavascriptLog(string javascript);

/// @notice Emitted when the price is updated.
/// @param price The new price.
event PriceLog(uint256 indexed price);

/// @notice Emitted when an interaction occurs (request sent or response received).
/// @param requestId The request ID.
/// @param sender The address of the sender.
/// @param isResponse True if this log is for a response, false for a request.
/// @param prompt The user prompt.
/// @param response The response data.
event InteractionLog(
bytes32 indexed requestId, address indexed sender, bool indexed isResponse, string prompt, string response
);

/// @notice Struct representing an interaction (request and response).
struct Interaction {
bytes32 requestId;
address sender;
Expand All @@ -36,8 +68,16 @@ contract OnChainAIv1 is FunctionsClient, ConfirmedOwner {
uint64 internal _subscriptionId;
uint64 internal _donHostedSecretsVersion;

/// @notice The price required to send a request.
uint256 public price;

/// @notice Constructor to initialize the OnChainAIv1 contract.
/// @param router The address of the Chainlink Functions Router contract.
/// @param javascript_ The JavaScript code to be executed by the Chainlink Function.
/// @param subscriptionId_ The subscription ID for billing purposes.
/// @param gasLimit_ The gas limit for the Chainlink Function request.
/// @param donId_ The DON ID used for routing the request.
/// @param price_ The price required to send a request.
constructor(
address router,
string memory javascript_,
Expand All @@ -53,36 +93,60 @@ contract OnChainAIv1 is FunctionsClient, ConfirmedOwner {
setPrice(price_);
}

/// @notice Retrieves the last interaction for a given sender address.
/// @param sender The address of the sender.
/// @return The last Interaction struct associated with the sender.
function lastInteraction(address sender) external view returns (Interaction memory) {
return _interactions[_lastRequestId[sender]];
}

/// @notice Sets the JavaScript code to be used in the Chainlink Function request.
/// @dev Only the contract owner can call this function.
/// @param javascript_ The JavaScript code as a string.
function setJavascript(string memory javascript_) public onlyOwner {
_javascript = javascript_;
emit JavascriptLog(javascript_);
}

/// @notice Sets the subscription ID for billing purposes.
/// @dev Only the contract owner can call this function.
/// @param subscriptionId_ The subscription ID.
function setSubscriptionId(uint64 subscriptionId_) public onlyOwner {
_subscriptionId = subscriptionId_;
}

/// @notice Sets the gas limit for the Chainlink Function request.
/// @dev Only the contract owner can call this function.
/// @param gasLimit_ The gas limit in units of gas.
function setGasLimit(uint32 gasLimit_) public onlyOwner {
_gasLimit = gasLimit_;
}

/// @notice Sets the DON ID used for routing the request.
/// @dev Only the contract owner can call this function.
/// @param donId_ The DON ID.
function setDonID(bytes32 donId_) public onlyOwner {
_donId = donId_;
}

/// @notice Sets the price required to send a request.
/// @dev Only the contract owner can call this function.
/// @param price_ The new price in wei.
function setPrice(uint256 price_) public onlyOwner {
price = price_;
emit PriceLog(price_);
}

/// @notice Sets the version of the DON-hosted secrets.
/// @dev Only the contract owner can call this function.
/// @param donHostedSecretsVersion_ The version number of the DON-hosted secrets.
function setDonHostedSecretsVersion(uint64 donHostedSecretsVersion_) public onlyOwner {
_donHostedSecretsVersion = donHostedSecretsVersion_;
}

/// @notice Sends a Chainlink Function request with the user's prompt.
/// @param userPrompt The user's prompt to be processed.
/// @return requestId The ID of the Chainlink Function request.
function sendRequest(string memory userPrompt) external payable returns (bytes32 requestId) {
require(_donHostedSecretsVersion > 0, NoValidSecrets());
require(bytes(userPrompt).length > 0, NoEmptyPrompt());
Expand All @@ -105,12 +169,20 @@ contract OnChainAIv1 is FunctionsClient, ConfirmedOwner {
emit InteractionLog(requestId, msg.sender, false, userPrompt, "");
}

/// @notice Callback function invoked when the Chainlink Function request is fulfilled.
/// @dev Overrides the fulfillRequest function from FunctionsClient.
/// @param requestId The ID of the request being fulfilled.
/// @param response The response data from the Chainlink Function.
/// @param err Any error messages from the Chainlink Function.
function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override {
Interaction memory interaction = _interactions[requestId];

require(interaction.requestId == requestId, UnexpectedFullfillRequest(requestId, string(response), string(err)));
require(
(requestId != 0) && (requestId == interaction.requestId),
UnexpectedFullfillRequest(requestId, string(response), string(err))
);

// concat response or/and error
// Concatenate response and/or error
string memory responseError = (err.length == 0)
? (response.length == 0) ? "Empty response" : string(response)
: string.concat("Error: ", string(err), " | ", string(response));
Expand All @@ -120,6 +192,8 @@ contract OnChainAIv1 is FunctionsClient, ConfirmedOwner {
emit InteractionLog(requestId, interaction.sender, true, interaction.prompt, responseError);
}

/// @notice Withdraws the contract's balance to the owner's address.
/// @dev Only the contract owner can call this function.
function withdraw() external onlyOwner {
uint256 bal = address(this).balance;
(bool success,) = payable(msg.sender).call{value: bal}("");
Expand Down

0 comments on commit ee6b8e9

Please sign in to comment.