Building dapps

Solidity on Citrate

We built Citrate's Lattice Virtual Machine (LVM) to provide full EVM compatibility, meaning any Solidity contract that compiles for Ethereum will deploy and execute on Citrate without modification. The LVM extends the standard EVM with AI-native precompiled contracts, but the base instruction set, storage model, and ABI encoding remain identical to Ethereum.

This guide covers the practical steps for setting up your development environment, writing contracts, deploying them, and understanding the key differences between Citrate and Ethereum.

EVM Compatibility

The LVM supports Solidity compiler versions up to 0.8.x and implements all standard EVM opcodes through the Shanghai upgrade. This means you can use familiar patterns such as OpenZeppelin libraries, proxy contracts, and CREATE2 deterministic deployments without changes.

Key compatibility points:

  • ABI encoding follows the standard Ethereum ABI specification
  • Gas metering uses the same opcode costs as Ethereum post-Shanghai, with additional gas schedules for AI precompile calls
  • Storage layout is slot-based and compatible with tools like forge inspect
  • Events and logs work identically, and standard indexers can parse Citrate event data

The primary difference is that Citrate provides seven AI precompile addresses (0x0100 through 0x0106) that give contracts native access to model deployment, inference, batch processing, metadata, proof verification, benchmarking, and model encryption. These are optional -- you can deploy a purely financial DeFi contract on Citrate with zero AI interaction.

Hardhat Setup

To configure Hardhat for Citrate, install the standard Hardhat package and add a network entry to your configuration:

npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
npx hardhat init

Then update hardhat.config.js:

require("@nomicfoundation/hardhat-toolbox");
 
module.exports = {
  solidity: "0.8.24",
  networks: {
    "citrate-testnet": {
      url: "https://testnet-rpc.cnidarian.cloud",
      chainId: 1338,
      accounts: [process.env.PRIVATE_KEY],
    },
    "citrate-mainnet": {
      url: "https://rpc.cnidarian.cloud",
      chainId: 1337,
      accounts: [process.env.PRIVATE_KEY],
    },
  },
};

Deploy your contracts with the standard Hardhat deploy command:

npx hardhat run scripts/deploy.js --network citrate-testnet

Foundry Setup

Foundry provides faster compilation and more powerful testing. Install Foundry and create a new project:

curl -L https://foundry.paradigm.xyz | bash
foundryup
forge init my-citrate-project
cd my-citrate-project

Add Citrate RPC endpoints to your foundry.toml:

[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.24"
 
[rpc_endpoints]
citrate_testnet = "https://testnet-rpc.cnidarian.cloud"
citrate_mainnet = "https://rpc.cnidarian.cloud"

Deploy with forge create:

forge create --rpc-url citrate_testnet --private-key $PRIVATE_KEY src/MyContract.sol:MyContract

Deployment Scripts

For production deployments, use scripted deployments that handle verification and multi-contract setups. Here is a Foundry deployment script example:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
import "forge-std/Script.sol";
import "../src/MyAIApp.sol";
 
contract DeployMyAIApp is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);
 
        MyAIApp app = new MyAIApp();
 
        // Verify the AI precompiles are accessible
        require(address(0x0100).code.length > 0, "ModelRegistry not available");
 
        vm.stopBroadcast();
    }
}

Run the script:

forge script script/DeployMyAIApp.s.sol:DeployMyAIApp --rpc-url citrate_testnet --broadcast

Differences from Ethereum

While Citrate maintains EVM compatibility, there are important differences developers should understand:

FeatureEthereumCitrate
Block time~12 seconds~1 second (GhostDAG parallel blocks)
Finality~15 minutes (probabilistic)~10 seconds (checkpoint-based)
Gas tokenETHSALT
Precompiles0x01-0x0a (cryptographic)0x01-0x0a + 0x0100-0x0106 (AI)
Block structureSingle chainDAG of parallel blocks
ConsensusProof of StakeGhostDAG + Paraconsistent BFT

The GhostDAG block structure means transactions can be confirmed in parallel across multiple block producers, resulting in significantly higher throughput. Your contracts do not need to account for this -- the LVM presents a consistent sequential execution view to smart contracts, just as Ethereum does. I'd suggest deploying to testnet first and confirming your contract behaves identically before moving to mainnet.

Further Reading