# 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 ```bash npx hardhat compile # Development build npx hardhat compile --profile production # Optimized build (optimizer enabled) ``` ### Run Tests ```bash 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 ```bash 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 ```bash 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 ```solidity // 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 ```solidity /** * @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 ```solidity 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 ```typescript // 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 `any` for dynamic contract instances (Hardhat/viem typing limitation) **Testing Framework:** Node.js native test runner (`node:test`) with Chai assertions ```typescript 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 ```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 ```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 integration - `viem` (^2.44.0) - TypeScript Ethereum library - `chai` (^6.2.2) - Assertion library - `forge-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.sender` appended to calldata and extracted via `ConstellationContext` - 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 ```typescript // 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 1. **No linting configured** - ESLint/Prettier/Solhint are not set up 2. **Hardhat 3 Beta** - Some APIs may differ from Hardhat 2 3. **Viem over Ethers** - This project uses viem, not ethers.js 4. **Test output** - Tests include console.log for benchmark visualization; this is intentional 5. **Gas tracking** - Receipt analysis is used for gas comparisons between patterns