Bring AI on-chain with ORA Protocol

Bring AI on-chain with ORA Protocol

Prior to 2022, Web3 + AI seemed like a far fetched ambitious idea. The Web3 ecosystem was still at a very nascent stage with unsatisfactory UX and scalability bottlenecks. On the other hand, reliable AI models were being developed and battle-tested.

But recently, highly-skilled developers working on these issues have brought to light breakthrough applications of zero-knowledge proofs, modular architecture, WASM execution and appchains to solve the biggest road breaks in mass Web3 adoption. On the flip side, products like ChatGPT and Bard have become essential tools that we didn't know we needed.

This has provided the necessary bandwidth for other to work on a projects where Blockchain and AI can be used in unison. One of the biggest projects in this space is ORA Protocol (previously HyperOracle).

So, if anyone ever asked you to choose between Web3 and AI, you know what to tell them now (*whispers shut the __).

About ORA Protocol

ORA Protocol is the world's first Programmable zkOracle allowing developers to bring AI inference on-chain. ORA breaks down the limitations of smart contracts with richer data sources and compute so developers can innovate freely.

ORA Protocol has 2 primary products:

  • AI Oracle (OAO, Onchain AI Oracle): Brings the power of AI onchain (this is what we'll be working on today)

  • ZK Oracle: Brings complex compute and historical data onchain.

https://docs.ora.io/doc/cle/introduction

Learn more about ORA Protocol here

OAO

Lets talk about ORA Protocol's most recent launch the OAO(Onchain AI Oracle). This is a breakthrough technology leveraging the power opML(Optimistic Machine Learning). This means the result generated by the AI model can be cryptographically proven using a technique called Optimistic Proofs.

OAO namely has 2 modes:

  • Llama 2: Brings the famous Llama2 model onchain for text-to-text prompts

  • Stable Diffusion: Allows text-to-image conversion using the Stable Diffusion model.

  • Personalized Data model: Future implementations will allow developers to bring their own data model for further fine tuning.

Learn more about OAO here

Start Building

We'll be creating a ERC721 Smart Contract using Solidity that can call AI models, generate images and create a NFT (all ONCHAIN!)

As you might have guessed, we'll be using OAO for this.

We'll be developing our smart contract in Remix.ide to make the setup process easier.

Or if you prefer a git repo, the source code is available here

Create a file name OAO.sol (or whatever you like) and use the code below

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

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

interface IOAO{
     function calculateAIResult(uint256 modelId, string calldata prompt) external;
     function getAIResult(uint256 modelId, string calldata prompt) external view returns (string memory);
}

contract OAO is ERC721, ERC721URIStorage{
    address iOao;    
    uint256 private _nextTokenId;
    string constant ipfsPrepend="https://ipfs.io/ipfs/";

    event ONFTMinted(address owner,uint256 tokenId,string tokenURI);

    constructor(address _iOao) ERC721("OAONFT", "ONFT"){
        iOao=_iOao;
    }

    function createArt(string memory prompt) public{
        IOAO(iOao).calculateAIResult(1,prompt);
    }

    function fetchIpfsHash(string memory prompt) public view returns(string memory){
         string memory ipfsHash = IOAO(iOao).getAIResult(1,prompt);
         return ipfsHash;
    }

    function safeMint(string memory prompt) public{
        bytes memory uri = abi.encodePacked(ipfsPrepend,fetchIpfsHash(prompt));

        uint256 tokenId = _nextTokenId++;
        _safeMint(msg.sender, tokenId);
        _setTokenURI(tokenId, string(uri));
        tokenId++;

        emit ONFTMinted(msg.sender,tokenId,string(uri));
    }

     function tokenURI(uint256 tokenId)
            public
            view
            override(ERC721, ERC721URIStorage)
            returns (string memory)
        {
            return super.tokenURI(tokenId);
        }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

Let's go over what's going on in this contract:

  • We import Open Zeppelin's ERC721 contract. This is a pretty standard step while developing NFT contracts.

  • We create an interface to define the functions that we will be using from the official OAO contracts by the ORA team. These are simply the functions definitions.

  • Next we start our contract:

  • iOao ,_nextTokenId ,ipfsPrepend are state variables to store the OAO address, current token id and the link prepend respectively.

  • Next we create the constructor, which takes in an address parameter. The ERC721 constructor needs to be initialized as well with name and symbol values respectively. (feel free to use different values)

  • Now, we create the createArt function which takes in any arbitrary input string and passes it to the AI model by OAO. The model configs are as follows:

    • 0 : For Llama 2

    • 1 : For Stable Diffusion

  • For our purpose, we are only interested with text-to-image hence we hardcode it to 1

  • The next function is fetchIpfsHash which is a read-only function. It fetches the result of the prompt sent to the onchain AI. So, the OAO creates an image from the text and stores the resultant image in IPFS. Hence, this function will return an IPFS hash.

  • The previous function returns only the content hash of the image; eg: QmaD2WSUGxouY6yTnbfGoX2sezN6QktUriCczDTPbzhC9j .Unfortunately, we cannot view the image if we put this into the search bar. We need to prepend it with some other sections as well. In this case, https://ipfs.io/ipfs/ ,which is what we store in the variable ipfsPrepend . When concatenating, it forms the entire link:

https://ipfs.io/ipfs/QmaD2WSUGxouY6yTnbfGoX2sezN6QktUriCczDTPbzhC9j

  • Now, the main function called safeMint ,this will retrieve the result from fetchIpfsHash ,create and mint an NFT out of it.

  • The other two functions called, tokenURI and supportsInterface are something you need to write everytime for an ERC721 contract.(no need to worry about these two)

Once you've understood the code, compile it using ctrl + S and then lets deploy it.

Go to the deploy tab, and make sure your contract is selected under the contract option is the side panel. Under the development option select Injected Provider- Metamask and log in to your account when asked to. Make sure it is a dev account. Do not use an account with real funds in it. Next, get some test Sepolia ETH and fund your wallet.

Next to the deploy button, we'll need to put in the address of the OAO contract since we require it in the constructor. Use this address:

0xb880D47D3894D99157B52A7F869aB3B1E2D4349d

Hit DEPLOY

After some time you'll get a confirmation and you'll be able to interact with the contract from the browser itself.

This is how it should look like. Use the createArt function and enter the prompt you want to generate. It can literally be anything (I used "cyberpunk style Madara Uchiha standing at the top of a tower in Tokyo").

Once that function executes, next select safeMint and pass in the exact same prompt. After a while, it'll generate the NFT. You can go to the tokenURI function and pass in your token id(0 if its your first transaction). That will spit out the complete IPFS link and you can view your onchain AI image.

If you're wondering why you cannot view the image in a NFT marketplace like Opensea, thats because this is just a bare bone basic NFT which doesn't follow Opensea's metadata standards. But the point of this was to teach you how to embed prompt-to-text in your smart contracts itself. You can learn how to create a proper structured JSON metadata in IPFS, upload the generated image there and use that as your NFT. Here's a link to Opensea's standards

Read more about the prospect of Blockchain X AI by the founder of Ethereum, Vitalik Buterin

https://vitalik.eth.limo/general/2024/01/30/cryptoai.html

That’s it for this post. I hope you have a better understanding on how to use AI with Web3

For more informative posts, follow me on Twitter

Thank you for reading 🎉