> ## Documentation Index
> Fetch the complete documentation index at: https://thrackle.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate Your Smart Contract

> How to integrate your smart contract with the Forte Rules Engine

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

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](/v2/guides/policy-configuration).

```json
{
  "Policy": "Claire's Policy",
  "PolicyType": "open",
  "CallingFunctions": [
    {
      "name": "mint(uint256 amount)",
      "functionSignature": "mint(address to, uint256 quantity)",
      "encodedValues": "address to, uint256 quantity, address owner"
    }
  ],
  "ForeignCalls": [
    {
      "name": "GetAllowedMintAmount",
      "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
      "function": "allowedMintAmount(address)",
      "returnType": "uint256",
      "valuesToPass": "0"
    },
    {
      "name": "DecrementAllowedMintAmount",
      "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
      "function": "removeOneMint(address)",
      "returnType": "",
      "valuesToPass": "0"
    }
  ],
  "Trackers": [],
  "MappedTrackers": [],
  "Rules": [
    {
      "Name": "Mint restrictions",
      "Description": "Limits mints",
      "condition": "FC:GetAllowedMintAmount > 0 OR to == owner",
      "positiveEffects": ["emit NFTMinted"],
      "negativeEffects": ["revert(\"Address not allowed to mint.\")"],
      "callingFunction": "mint(address to, uint256 quantity)"
    },
    {
      "Name": "Decrement mint amount",
      "Description": "Decrements allowed mint amount",
      "condition": "FC:GetAllowedMintAmount > 0",
      "positiveEffects": ["FC:DecrementAllowedMintAmount(to)"],
      "negativeEffects": [],
      "callingFunction": "mint(address to, uint256 quantity)"
    }
  ]
}
```

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 Modifiers

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

<Note>
  You will need to have the SDK installed in your project. Check the [installation
  guide](/v2/guides/installation) for details.{" "}
</Note>

```typescript 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.

```bash
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.

<CodeGroup>
  ```solidity ClaireNFT.sol (Original)
  // 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);
          }
      }
  }
  ```

  ```solidity RulesEngineClientCustom.sol
  // SPDX-License-Identifier: BUSL-1.1
  pragma solidity ^0.8.24;

  import "@thrackle-io/forte-rules-engine/src/client/RulesEngineClient.sol";

  abstract contract RulesEngineClientCustom is RulesEngineClient {
      modifier checkRulesBeforemint(address to, uint256 quantity, address owner) {
  		bytes memory encoded = abi.encodeWithSelector(msg.sig, to, quantity, owner);
  		_invokeRulesEngine(encoded);
  		_;
  	}

  	modifier checkRulesAftermint(address to, uint256 quantity, address owner) {
  		bytes memory encoded = abi.encodeWithSelector(msg.sig, to, quantity, owner);
  		_;
  		_invokeRulesEngine(encoded);
  	}
  }
  ```

  ```solidity ClaireNFT.sol (Updated) {6, 14}
  // 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";
  import "src/RulesEngineClientCustom.sol";

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

      function mint(
          address to,
          uint256 quantity
      ) public checkRulesBeforemint(to, quantity, owner()) {
          for (uint256 i = 0; i < quantity; i++) {
              _safeMint(to, totalSupply() + i);
          }
      }
  }
  ```
</CodeGroup>

<Check>
  The `diff.diff` file will show exactly what was changed in the `ClaireNFT.sol` file for your
  reference.
</Check>

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

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

## Passing Additional Values to the Rules Engine

In the example above the rule condition requires the address of the contract owner to bypass the rule condition. The `owner` value is not a function argument and must be explicitly added to the modifier attached to the `mint` function. This was accomplished by manually editing the `RulesEngineClientCustom.sol` and `ClaireNFT.sol (Updated)` files to include this extra function argument.

Refer to the code examples in the tabs above to see exactly how to do this. You can include any extra state variables in your smart contract that you want to leverage in your rule condition using this method.
