This guide will walk you through how to integrate your smart contract with the Forte Rules Engine.

In the Quickstart guide, we provided you with a template contract and used the SDK to add a modifier to it in step 3. We will do the same thing this time, but with some modifications to enable more complex use cases.

For this guide, we will use the following scenario: You are releasing an NFT series using the ERC-721 standard, using your contract ClaireNFT.sol. You have a list of people who are allowed to mint stored in an on-chain oracle, along with how many they’re each allowed to mint. However, the owner of the NFT contract (you) should be able to bypass this limitation. These minting restrictions will be enforced with the Rules Engine.

Policy Definition

Now, we will create our policy.json file that defines our Policy. We have pre-created it for you here to match the described scenario. For more information on how to configure policies yourself, check out the Policy Configuration Guide.

{
  "Policy": "Claire's Policy",
  "ForeignCalls": [
    {
      "name": "GetAllowedMintAmount(x)",
      "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
      "signature": "allowedMintAmount(address)",
      "returnType": "uint256",
      "parameterTypes": "address",
      "encodedIndices": "0"
    },
    {
      "name": "DecrementAllowedMintAmount(x)",
      "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
      "signature": "removeOneMint(address)",
      "returnType": "",
      "parameterTypes": "address",
      "encodedIndices": "0"
    }
  ],
  "RulesJSON": [
    {
      "condition": "FC:GetAllowedMintAmount(x) > 0 OR to == owner",
      "positiveEffects": ["emit NFTMinted"],
      "negativeEffects": ["revert(\"Address not allowed to mint.\")"],
      "functionSignature": "mint(address to, uint256 quantity)",
      "encodedValues": "address to, uint256 quantity, address owner"
    },
    {
      "condition": "FC:GetAllowedMintAmount(x) > 0",
      "positiveEffects": ["FC:DecrementAllowedMintAmount(x)"],
      "negativeEffects": [],
      "functionSignature": "mint(address to, uint256 quantity)",
      "encodedValues": "address to, uint256 quantity, address owner"
    }
  ]
}

Notice that the function calling the policy is mint(address to, uint256 quantity), but the encodedValues also includes an address owner field. So, in this case we need to pack in additional data to send from the calling contract to the policy.

Also note the ForeignCalls defined in the policy, which are used in the rule evaluation as well as an effect for the positive mint outcome path.

Generate and Add Modifers

To add the modifiers to your ClaireNFT.sol contract, create a new file named injectModifiers.ts and add the content below.

You will need to have the SDK installed in your project. Check the installation guide for details.

injectModifiers.ts
import { policyModifierGeneration } from "@thrackle-io/forte-rules-engine-sdk";

const modifiersPath = "src/RulesEngineClientCustom.sol";
const yourContract = "src/ClaireNFT.sol";

policyModifierGeneration("policy.json", modifiersPath, [yourContract]);

Run this script within your project directory to prepare your contract for deployment.

npx tsx injectModifiers.ts

This will create two new files in your project, src/RulesEngineClientCustom.sol and diff.diff. It will also update the existing ClaireNFT.sol file by adding the modifier to the mint function.

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

import {ERC721} from "@openzeppelin/contracts/token/721/721.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract ClaireNFT is RulesEngineClientCustom, ERC721, Ownable {
    constructor() ERC721("Claire NFT", "CLR") {}

    function mint(
        address to,
        uint256 quantity
    ) public {
        for (uint256 i = 0; i < quantity; i++) {
            _safeMint(to, totalSupply() + i);
        }
    }
}

The diff.diff file will show exactly what was changed in the ClaireNFT.sol file for your reference.

Because it was specified in the policy.json file, the modifier automatically added in the owner field into the modifer file for you.

(show the modified ClaireNFT.sol relevant piece of code).

And that’s it! The ClaireNFT.sol contract is now ready to use for this policy.