Skip to content

Deployment Guide

Contracts must be deployed in strict order. Each contract’s initializer requires addresses from previously deployed contracts. Do not skip steps or deploy out of order.

Before running any deployment script:

  • MANTLE_RPC_URL set to https://rpc.mantle.xyz
  • DEPLOYER_PRIVATE_KEY loaded (deployer wallet, never commit)
  • Deployer wallet holds sufficient MNT for gas (~0.1 MNT is more than enough)
  • All environment variables in .env populated
  • Fonbnk sandbox test: deposit Celo USDC → disburse to Uganda MTN
  • INDEPENDENT_AGGREGATOR_ADDRESS set to AsiliChain multisig in .env
  • Alchemy webhook URL set and tested on Sepolia
Step 1: FarmerRegistry.sol → no dependencies
Step 2: CreditScore.sol → requires FarmerRegistry address
Step 3: BatchToken.sol → requires FarmerRegistry address
Step 4: TraceLog.sol → requires BatchToken address
Step 5: PurchaseOrder.sol → requires BatchToken + TraceLog addresses
Step 6: ProtocolFee.sol → no dependencies
Step 7: LendingVault.sol → requires all of the above
Step 8: Post-deploy: grant roles
├── Grant VAULT_ROLE to LendingVault proxy
├── Grant PURCHASE_ORDER_ROLE to PurchaseOrder proxy
├── Grant COOP_ROLE to cooperative wallet(s)
└── Grant AGENT_ROLE is handled by COOP_ROLE holders via _setRoleAdmin
Step 8a: Set INDEPENDENT_AGGREGATOR in FarmerRegistry
→ farmerRegistry.setIndependentAggregator(MULTISIG_ADDRESS)
Must run before any independent farmer is registered.
MULTISIG_ADDRESS = INDEPENDENT_AGGREGATOR_ADDRESS from .env
Step 8b: IdentityRegistry.sol → ERC-8004 agent identity (no dependencies)
Register AI agents via `registerFor()`: risk-monitor (id=0), anomaly-detector (id=1)
Step 8c: Grant MULTISIG_ROLE on LendingVault to deployer (or multisig wallet)
→ lendingVault.grantRole(MULTISIG_ROLE, address)
Used for `deployReserve()` — deploying credit loss reserve on defaults
:::caution Rotating INDEPENDENT_AGGREGATOR post-launch
If you ever call `setIndependentAggregator()` with a new address after
independent farmers have been registered, their existing records are **not**
updated. `isIndependent()` reads each farmer's stored `cooperativeWallet`,
not the current global value. You must call `migrateFarmer()` for each
affected farmer individually, or batch the migration in an upgrade.
:::
Step 9: Post-deploy: set env → copy all deployed addresses to .env
Step 10: Verify contracts → Mantle Explorer source verification
  • Added nationalId, farmerName, phoneNumber to Farmer struct (append only — storage safe)
  • Added _setRoleAdmin(AGENT_ROLE, COOP_ROLE) — cooperatives self-manage agents
  • Added getFarmerCount(address cooperativeWallet) — API enforces agent cap
  • Updated registerFarmer() signature to accept new fields
  • Added getFarmerWallet(uint256 tokenId) — reads farmer address from batch storage
  • Extended IBatchToken interface
  • Added farmerRegistry address via initializeV2() reinitializer
  • Modified _checkStageRole() to accept tokenId parameter
  • Independent farmer batches: AGENT_ROLE can advance all stages
  • Cooperative farmer batches: unchanged (COOP_ROLE still required)
Terminal window
cd packages/contracts
# Deploy to Mantle Sepolia (test first)
npx hardhat run scripts/deploy.ts --network mantleSepolia
# Deploy to Mantle mainnet (after Sepolia validation)
npx hardhat run scripts/deploy.ts --network mantle

Sprint 3 — Deployed Addresses (Mantle Sepolia, 2026-06-06)

Section titled “Sprint 3 — Deployed Addresses (Mantle Sepolia, 2026-06-06)”
FarmerRegistry 0xa2F5Bb2Aa25deC5c7F8e1fE9455E725F6CBb15F1
CreditScore 0xd8b18B874F58C7adef805f5Efb02433febc41Ad2
BatchToken 0x9e5B886b4dB39b8C86a75Ae139d28376EF32694c
TraceLog 0x99280b9B1D7c07B144b32DBa192a89781d6c872D
PurchaseOrder 0xea62E8dFA98eF3E2eBD1f6dcBC839302984a3eDA
ProtocolFee 0x687D03c79125eD82E19CcBA377FaA8f49b47d971
IdentityRegistry 0xA31AE6917C1C9A746d71b0475Ca211F44D2135F4
LendingVault 0x069b761A76778e5f4bb39B130e304F3183F8b858
USDC (Mock) 0x987758676f7c2219754039AF65FCBB218b707BD4
VersionWhat ChangedNew Impl Address
v3Credit loss reserve (2%), deployReserve(), MULTISIG_ROLE0xb6E50B3d00FbB45b6ebDD292aEB0755FCc28aB94
v4APR-based fees (was flat % of totalDue, now APR on principal)0x3BF681FDa168Dc28B81E3E38a87b33295A443cA7

Proxy remains at 0x069b761A76778e5f4bb39B130e304F3183F8b858 through both upgrades.

AgentIdentityRegistry Token IDOwner
Risk Monitor0Deployer (0xB70f...)
Anomaly Detector1Deployer (0xB70f...)