Inherits all rules from root AGENTS.md. Only overrides and additions below.
Solidity smart contracts for the Lineth protocol: L1 rollup (LineaRollup), messaging services (L1/L2MessageService), token bridge (TokenBridge), and supporting libraries. Built with Hardhat and Foundry.
# Install dependencies
pnpm install
# Build (compile contracts)
pnpm -F contracts run build
# Run tests
pnpm -F contracts run test
# Run tests with gas reporting
pnpm -F contracts run test:reportgas
# Coverage
pnpm -F contracts run coverage
# Lint Solidity
pnpm -F contracts run lint:sol
pnpm -F contracts run lint:sol:fix
# Lint TypeScript (test/deploy scripts)
pnpm -F contracts run lint:ts
pnpm -F contracts run lint:ts:fix
# Format Solidity
pnpm -F contracts run prettier:sol
pnpm -F contracts run prettier:sol:fix
# Full lint + format
pnpm -F contracts run lint:fix
# Generate Solidity docs (requires Foundry)
pnpm -F contracts run solidity:docgen- Solidity version:
0.8.33(exact for contracts, caret^0.8.33for interfaces/abstract/libraries) - EVM version: osaka (Hardhat), cancun (Foundry)
- OpenZeppelin contracts: 4.9.6
- Interfaces:
// SPDX-License-Identifier: Apache-2.0 - Contracts:
// SPDX-License-Identifier: AGPL-3.0
Every public/external function, event, and error MUST have NatSpec:
@noticeon every public/external function@paramfor every parameter (in signature order)@returnfor every return value (named)@author Consensys Software Inc.and@custom:security-contact security-report@linea.buildon every contract/interface@devfor non-obvious implementation detailsDEPRECATEDin NatSpec for deprecated items
| Item | Convention | Example |
|---|---|---|
| Public state | camelCase | uint256 messageCount |
| Private/internal state | _camelCase | uint256 _internalCounter |
| Constants | UPPER_SNAKE_CASE | bytes32 DEFAULT_ADMIN_ROLE |
| Function params | _camelCase | function send(address _to) |
| Return variables | camelCase (named) | returns (bytes32 messageHash) |
| Mappings | descriptive keys | mapping(uint256 id => bytes32 hash) |
| Init functions | __Contract_init | __PauseManager_init() |
Interface: Structs -> Enums -> Events -> Errors -> External Functions
Contract: Using statements -> Constants -> State variables -> Structs -> Enums -> Events -> Errors -> Modifiers -> Functions
Named imports only. Explicit inheritance of key ancestors. Blank line after import block.
external+calldatafor functions accepting arrays/structs- Cache storage values read multiple times
- Custom errors over revert strings
uncheckedonly with proven safe arithmetic (with comment)- Short-circuit: cheap checks before expensive ones
- Explicit batch limits for loops
- Constants:
internalunless explicitly needed public - Overridable functions:
public virtual(notexternal virtual) - Minimize public surface area
- Explicit visibility on all state variables
- Upgradeable contracts use ERC-7201 namespaced storage (not storage gaps)
- Both
initializeandreinitializeVNusereinitializer(N)(neverinitializer) - Zero-value checks via
ErrorUtils.revertIfZeroAddress()/ErrorUtils.revertIfZeroHash() - Assembly: hex for memory offsets (
mstore(add(mPtr, 0x20), _var)) - Repeated checks extracted into modifiers
- No magic numbers — use named constants
- Never deploy without
VERIFY_CONTRACT=truefor block explorer verification - Contract modifications from audited code require independent audit
- Hardhat tests:
test/hardhat/— TypeScript test files - Foundry tests:
test/foundry/— Solidity test files - Coverage:
SOLIDITY_COVERAGE=trueflag with.solcover.jsconfig - CI runs coverage and uploads to Codecov with
hardhatflag
- Always read the existing interface before modifying a contract
- Check storage layout compatibility before changing state variables in upgradeable contracts
- Run
pnpm -F contracts run lint:fixbefore committing any Solidity changes - For detailed rules, see
.agents/skills/developing-smart-contracts/and.cursor/rules/smart-contract-guidelines/
- Default: deployments use
DEPLOYER_PRIVATE_KEY(andnamedAccounts) like any standard Hardhat project. - Opt-in UI: set
HARDHAT_SIGNER_UI=trueto sign in a browser via the local Next.js app undercontracts/signer-ui/, driven bycontracts/scripts/hardhat/signer-ui-bridge.ts. Deploy scripts usewithSignerUiSession,getUiSigner, and helpers inscripts/hardhat/utils.tsthat callsetUiTransactionContextfor richer UI labels. Selected operational tasks userunWithSignerUiSession+getUiSigner.HARDHAT_SIGNER_UI=trueandDEPLOYER_PRIVATE_KEYare mutually exclusive; Hardhat errors if both are set. After a fullhardhat deploy, the bridge reports a terminal outcome and stops Next.js by default (seeHARDHAT_SIGNER_UI_LEAVE_NEXT_DEV_AFTER_DEPLOY/HARDHAT_SIGNER_UI_SHUTDOWN_NEXT_DEVin deployment docs). - Docs: contracts/docs/deployment/README.md (overview), contracts/signer-ui/README.md (operator walkthrough), contracts/docs/deployment/signer-ui-removal.md (how to delete the feature).
- Lint:
contracts/eslint.config.mjsignoressigner-ui/**so Next’s.nextoutput is not parsed by the contracts ESLint project.
Hardhat compilation artifacts consumed by the E2E test pipeline (e2e/scripts/generateAbi.ts).
| Subdirectory | Contents |
|---|---|
deployed-artifacts/ |
Artifacts for production on-chain deployments |
static-artifacts/ |
Artifacts for non-upgradeable contracts used in E2E tests |
dynamic-artifacts/ |
Artifacts for upgradeable contracts |
- Run
pnpm hardhat compilein/contracts(requirespnpm ifirst). - Find the JSON build artifact in
contracts/build/src/. - Copy it to the appropriate subdirectory above.