AGENTS.md
Guidelines for AI coding agents working in this repository.
Project Overview
This is a Hardhat 3 Beta project implementing and comparing two smart contract upgrade patterns:
- Constellation Pattern - Router-based architecture with built-in rollback, temporal auditing, and multi-layer support
- Diamond Pattern (EIP-2535) - Standard facet-based proxy pattern for comparison/benchmarking
Languages: Solidity (contracts) + TypeScript (tests, scripts, config)
Build/Test/Lint Commands
Compile Contracts
npx hardhat compile # Development build
npx hardhat compile --profile production # Optimized build (optimizer enabled)
Run Tests
npx hardhat test # Run all tests
npx hardhat test nodejs # Run only TypeScript tests
npx hardhat test solidity # Run only Solidity tests (Foundry-style)
npx hardhat test --test-files test/Constellation.test.ts # Run a single test file
Deployment
npx hardhat ignition deploy ignition/modules/Counter.ts # Local
npx hardhat ignition deploy --network sepolia ignition/modules/Counter.ts # Sepolia
npx hardhat keystore set SEPOLIA_PRIVATE_KEY # Set deployment key
Scripts
npx hardhat run scripts/send-op-tx.ts
Project Structure
contracts/ # Solidity smart contracts
ConstellationRouter.sol # Main router with governance and upgrades
ConstellationContext.sol # Abstract context middleware for identity forwarding
Diamond.sol # Full Diamond implementation (EIP-2535)
TraceabilityShard*.sol # Microservice shards for testing
test/ # TypeScript integration tests (node:test runner)
scripts/ # Utility scripts
ignition/modules/ # Hardhat Ignition deployment modules
Code Style Guidelines
Solidity
Version: ^0.8.28
License Headers: Always include SPDX identifier
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;
Naming Conventions:
| Element | Convention | Example |
|---|---|---|
| Contracts | PascalCase | ConstellationRouter |
| Functions | camelCase | commitUpgrade, executeScheduledUpgrade |
| Private/internal functions | _camelCase | _performUpdate, _msgSender |
| Function parameters | _camelCase | _sig, _newLoc, _layer |
| Events | PascalCase | ServiceUpgraded, CrossLayerDispatch |
| State variables | camelCase | activeServices, currentMode |
| Constants | UPPER_SNAKE_CASE | TIMELOCK_WINDOW, DIAMOND_STORAGE_POSITION |
| Structs | PascalCase | ServiceMetadata, Certificate |
| Enums | PascalCase | GovMode { Standard, Institutional } |
Documentation: Use NatSpec comments for contracts and public functions
/**
* @title ConstellationRouter
* @dev High-integrity router featuring dual-mode governance
*/
contract ConstellationRouter {
/**
* @dev Primary entry point. Routes calls based on the active pointer.
*/
function execute(bytes4 _sig, bytes calldata _data) external payable returns (bytes memory) {
Error Handling: Use require with contract-prefixed messages
require(condition, "Constellation: Error message");
require(condition, "LibDiamond: Error message");
require(condition, "Timelock: Error message");
TypeScript
Module System: ES Modules ("type": "module" in package.json)
Target: ES2022 with strict mode enabled
Import Order: Group imports by source
// 1. Hardhat imports
import { network } from "hardhat";
// 2. Library imports (viem, chai, etc.)
import { expect } from "chai";
import { keccak256, toBytes, encodeAbiParameters } from "viem";
// 3. Node built-in imports
import { describe, it, beforeEach } from "node:test";
Naming Conventions:
- Variables and functions:
camelCase - Types and interfaces:
PascalCase - Use
anyfor dynamic contract instances (Hardhat/viem typing limitation)
Testing Framework: Node.js native test runner (node:test) with Chai assertions
describe("Test Suite Name", function () {
let router: any, owner: any;
beforeEach(async function () {
// Setup
});
it("should do something", async function () {
expect(value).to.equal(expected);
});
});
Async Patterns: Always use async/await
Error Handling Patterns
Solidity
// Require with descriptive prefixed message
require(msg.sender == governor, "Constellation: Unauthorised Governor");
// Revert for explicit failures
revert("Compliance Error: Critical Logic Failure in V2");
// Assembly for propagating low-level call errors
if (!success) {
if (result.length > 0) {
assembly {
let result_size := mload(result)
revert(add(32, result), result_size)
}
} else {
revert("Constellation: L1 Execution failed");
}
}
TypeScript
// Try-catch for expected reverts
try {
await contract.write.execute([args]);
expect.fail("Execution should have reverted");
} catch (error: any) {
expect(JSON.stringify(error)).to.contain("Expected error message");
}
Key Dependencies
hardhat(^3.1.3) - Ethereum development environment (Beta)@nomicfoundation/hardhat-toolbox-viem- Viem integrationviem(^2.44.0) - TypeScript Ethereum librarychai(^6.2.2) - Assertion libraryforge-std- Foundry standard library for Solidity tests
Network Configuration
| Network | Type | Description |
|---|---|---|
hardhatMainnet | EDR simulated | L1 chain for testing |
hardhatOp | EDR simulated | Optimism chain for testing |
sepolia | HTTP | Testnet (requires env vars) |
Architecture Notes
Constellation Pattern
- Router-based with single entry point forwarding to microservices ("shards")
- Original
msg.senderappended to calldata and extracted viaConstellationContext - Each shard has isolated storage (no collision risk)
- Built-in service history for LIFO rollback
- Dual governance: Standard (instant) and Institutional (timelock-enforced)
Diamond Pattern (EIP-2535)
- Single proxy with delegatecall to facets
- Shared storage via diamond storage pattern (
keccak256("storage.position")) - Function selectors mapped to facet addresses
Common Utilities
// 4-byte function selector
const getSelector = (sig: string) => keccak256(toBytes(sig)).slice(0, 10) as `0x${string}`;
// ABI encode string parameter
const encodeString = (str: string) => encodeAbiParameters(parseAbiParameters('string'), [str]);
Notes for Agents
- No linting configured - ESLint/Prettier/Solhint are not set up
- Hardhat 3 Beta - Some APIs may differ from Hardhat 2
- Viem over Ethers - This project uses viem, not ethers.js
- Test output - Tests include console.log for benchmark visualization; this is intentional
- Gas tracking - Receipt analysis is used for gas comparisons between patterns