Interaction with OAO - Tutorial
This tutorial will help you understand the structure of Onchain AI Oracle (OAO), guide you through the process of building a simple Prompt contract that interacts with OAO. We will implement the contract step by step. At the end we will deploy the contract to the blockchain network and interact with it.
If you prefer a video version of the tutorial, check it here.
Final version of the code can be found here.
Learning Objectives
Setup development environment
Understand the project setup and template repository structure
Learn how to interact with the OAO and build an AI powered smart contract
Prerequisites
To follow this tutorial you need to have Foundry and git installed.
Setup
Clone template repository and install submodules
Move into the cloned repository
Copy .env.example, rename it to .env. We will need these env variables later for the deployment and testing. You can leave them empty for now.
Install foundry dependencies
Creating Prompt contract
1. Import dependencies
At the beginning we need to import several dependencies which our smart contract will use.
IAIOracle - interface that defines a requestCallback
method that needs to be implemented in the Prompt contract
AIOracleCallbackReceiver - an abstract contract that contains an instance of AIOracle and implements a callback method that needs to be overridden in the Prompt contract
2. Write the code
We'll start by implementing the constructor, which accepts the address of the deployed AIOracle contract.
Now let’s define a method that will interact with the OAO. This method takes 2 parameters, id of the model and input prompt data. It also needs to be payable, because a user needs to pass the fee for the callback execution.
In the code above we do the following:
Convert input to bytes
Call the requestCallback function with the following parameters:
modelId: ID of the AI model in use.
input: User-provided prompt.
callbackAddress: The address of the contract that will receive OAO's callback.
callbackGasLimit[modelId]: Maximum amount of that that can be spent on the callback, yet to be defined.
callbackData: Callback data that is used in the callback.
Next step is to define the mapping that keeps track of the callback gas limit for each model and set the initial values inside the constructor. We’ll also define a modifier so that only the contract owner can change these values.
We want to store all the requests that happened, so we create a data structure for the request data and the mapping between requestId and the request data.
In the code snippet above we added prompt, sender and the modelId to the request and also emitted an event.
Now that we implemented a method for interaction with the OAO, let's define a callback that will be invoked by the OAO after the computation of the result.
We've overridden the callback function from the AIOracleCallbackReceiver.sol
. It's important to use the modifier, so that only OAO can callback into our contract.
Function flow:
First we check if the request with provided id exists. If it does we add the output value to the request.
Then we define
prompts
mapping that stores all the prompts and outputs for each model that we use.At the end we emit an event that the prompt has been updated.
Notice that this function takes callbackData as the last parameter. This parameter can be used to execute arbitrary logic during the callback. It is passed during requestCallback
call. In our simple example, we left it empty.
Finally let's add the method that will estimate the fee for the callback call.
With this we finished with the source code for our contract. The final version should look like this:
Deployment and interaction with the contract
Foundry version
Add your
PRIVATE_KEY
,RPC_URL
andETHERSCAN_KEY
to .env file. Then source variables in the terminal.Create a deployment script
Go to Reference page and find the OAO_PROXY address for the network you want to deploy to.
Then open script/Prompt.s.sol and add the following code:
Run the deployment script
Once the contract is deployed and verified, you can interact with it. Go to blockchain explorer for your chosen network (eg. Etherscan), and paste the address of the deployed Prompt contract.
Let's use Stable Diffusion model (id = 50).
First call
estimateFee
method to calculate fee for the callback.Then request AI inference from OAO by calling calculateAIResult method. Pass the model id and the prompt for the image generation. Remember to provide estimated fee as a value for the transaction.
After the transaction is executed, and the OAO calculates the result, you can check it by calling prompts method. Simply input model id and the prompt you used for image generation. In the case of Stable Diffusion, the output will be a CID (content identifier on ipfs). To check the image go to https://ipfs.io/ipfs/[Replace_your_CID].
Remix version
Install the browser wallet if you haven't already (eg. Metamask)
Open your solidity development environment. We'll use Remix IDE.
Copy the contract along with necessary dependencies to Remix.
Choose the solidity compiler version and compile the contract to the bytecode
Deploy the compiled bytecode Once we compiled our contract, we can deploy it.
First go to the wallet and choose the blockchain network for the deployment.
To deploy the Prompt contract we need to provide the address of already deployed AIOracle contract. You can find this address on the reference page. We are looking for OAO_PROXY address.
Deploy the contract by signing the transaction in the wallet.
Once the contract is deployed, you can interact with it. Remix supports API for interaction, but you can also use blockchain explorers like Etherscan. Let's use Stable Diffusion model (id = 50).
Conclusion
In this tutorial we covered a step by step writing of a solidity smart contract that interacts with ORA's Onchain AI Oracle. Then we compiled and deployed our contract to the live network and interacted with it. In the next tutorial, we will extend the functionality of the Prompt contract to support AI generated NFT collections.
Last updated