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.
Pre-Deployment Checklist
Section titled “Pre-Deployment Checklist”Before running any deployment script:
-
MANTLE_RPC_URLset tohttps://rpc.mantle.xyz -
DEPLOYER_PRIVATE_KEYloaded (deployer wallet, never commit) - Deployer wallet holds sufficient MNT for gas (~0.1 MNT is more than enough)
- All environment variables in
.envpopulated - Fonbnk sandbox test: deposit Celo USDC → disburse to Uganda MTN
-
INDEPENDENT_AGGREGATOR_ADDRESSset to AsiliChain multisig in.env - Alchemy webhook URL set and tested on Sepolia
Deployment Order
Section titled “Deployment Order”Step 1: FarmerRegistry.sol → no dependenciesStep 2: CreditScore.sol → requires FarmerRegistry addressStep 3: BatchToken.sol → requires FarmerRegistry addressStep 4: TraceLog.sol → requires BatchToken addressStep 5: PurchaseOrder.sol → requires BatchToken + TraceLog addressesStep 6: ProtocolFee.sol → no dependenciesStep 7: LendingVault.sol → requires all of the aboveStep 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 _setRoleAdminStep 8a: Set INDEPENDENT_AGGREGATOR in FarmerRegistry → farmerRegistry.setIndependentAggregator(MULTISIG_ADDRESS) Must run before any independent farmer is registered. MULTISIG_ADDRESS = INDEPENDENT_AGGREGATOR_ADDRESS from .envStep 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-launchIf you ever call `setIndependentAggregator()` with a new address afterindependent 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 eachaffected farmer individually, or batch the migration in an upgrade.:::
Step 9: Post-deploy: set env → copy all deployed addresses to .envStep 10: Verify contracts → Mantle Explorer source verificationSprint 1 Contract Changes
Section titled “Sprint 1 Contract Changes”FarmerRegistry
Section titled “FarmerRegistry”- Added
nationalId,farmerName,phoneNumbertoFarmerstruct (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
BatchToken
Section titled “BatchToken”- Added
getFarmerWallet(uint256 tokenId)— reads farmer address from batch storage - Extended
IBatchTokeninterface
TraceLog
Section titled “TraceLog”- Added
farmerRegistryaddress viainitializeV2()reinitializer - Modified
_checkStageRole()to accepttokenIdparameter - Independent farmer batches:
AGENT_ROLEcan advance all stages - Cooperative farmer batches: unchanged (COOP_ROLE still required)
Running the Deployment Script
Section titled “Running the Deployment Script”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 mantleSprint 3 — Deployed Addresses (Mantle Sepolia, 2026-06-06)
Section titled “Sprint 3 — Deployed Addresses (Mantle Sepolia, 2026-06-06)”FarmerRegistry 0xa2F5Bb2Aa25deC5c7F8e1fE9455E725F6CBb15F1CreditScore 0xd8b18B874F58C7adef805f5Efb02433febc41Ad2BatchToken 0x9e5B886b4dB39b8C86a75Ae139d28376EF32694cTraceLog 0x99280b9B1D7c07B144b32DBa192a89781d6c872DPurchaseOrder 0xea62E8dFA98eF3E2eBD1f6dcBC839302984a3eDAProtocolFee 0x687D03c79125eD82E19CcBA377FaA8f49b47d971IdentityRegistry 0xA31AE6917C1C9A746d71b0475Ca211F44D2135F4LendingVault 0x069b761A76778e5f4bb39B130e304F3183F8b858USDC (Mock) 0x987758676f7c2219754039AF65FCBB218b707BD4LendingVault Upgrades (In-Place UUPS)
Section titled “LendingVault Upgrades (In-Place UUPS)”| Version | What Changed | New Impl Address |
|---|---|---|
| v3 | Credit loss reserve (2%), deployReserve(), MULTISIG_ROLE | 0xb6E50B3d00FbB45b6ebDD292aEB0755FCc28aB94 |
| v4 | APR-based fees (was flat % of totalDue, now APR on principal) | 0x3BF681FDa168Dc28B81E3E38a87b33295A443cA7 |
Proxy remains at 0x069b761A76778e5f4bb39B130e304F3183F8b858 through both upgrades.
Deployed AI Agents
Section titled “Deployed AI Agents”| Agent | IdentityRegistry Token ID | Owner |
|---|---|---|
| Risk Monitor | 0 | Deployer (0xB70f...) |
| Anomaly Detector | 1 | Deployer (0xB70f...) |