Skip to content

[Refactor] Timestamp-based deployment metadata & automated governance tracking#186

Open
clement-ux wants to merge 7 commits intoclement/refactor-deploymentfrom
clement/timestamp-deployment-replay
Open

[Refactor] Timestamp-based deployment metadata & automated governance tracking#186
clement-ux wants to merge 7 commits intoclement/refactor-deploymentfrom
clement/timestamp-deployment-replay

Conversation

@clement-ux
Copy link
Contributor

@clement-ux clement-ux commented Feb 5, 2026

Summary

Replaces the manual proposalExecuted boolean with a timestamp-based metadata system, enabling historical fork replays, automated governance tracking, and removing the need for developers to manually update deployment scripts after governance passes.

Deployment Metadata Format

The Execution struct in DeploymentTypes.sol was redesigned from {name, timestamp} to:

struct Execution {
    string name;
    uint256 proposalId;    // 0 = pending, 1 = no governance needed, >1 = on-chain proposal ID
    uint256 tsDeployment;  // block timestamp when deployment script executed
    uint256 tsGovernance;  // 0 = pending, 1 = no governance needed, >0 = execution timestamp
}

All entries in build/deployments-1.json and build/deployments-146.json migrated to this format with actual on-chain proposal IDs and execution timestamps filled in.

Resolver Changes

Three new mappings added for O(1) lookups: proposalIds, tsDeployments, tsGovernances. The addExecution() signature updated to accept all four metadata fields.

DeployManager Rewrite

  • Removed maxDeploymentFiles — now iterates ALL files, using new _canSkipDeployFile() to efficiently skip completed scripts without compilation
  • Skip logic based on timestamps: skip if proposalId == 1 (no governance) or tsGovernance != 0 && tsGovernance <= block.timestamp (governance executed)
  • _preDeployment() filters historical forks: entries with tsDeployment > block.timestamp are excluded, entries with tsGovernance > block.timestamp are reset to pending
  • _postDeployment() serializes the three new fields instead of single timestamp

AbstractDeployScript Changes

  • Removed proposalExecuted() virtual function
  • Split _storeDeployedContract() into _storeContracts() (persists addresses) and _recordExecution() (records metadata)
  • _recordExecution() must be called after _buildGovernanceProposal() — uses govProposal.actions.length to determine sentinel values
  • Added public buildGovernanceProposal() for external proposal ID computation (used by UpdateGovernanceMetadata)
  • Reordered execution steps: store contracts → build governance → record execution → handle proposal → fork logic

Removed proposalExecuted from All Scripts

The bool public override proposalExecuted = true/false declaration removed from all 19 deployment scripts (14 mainnet + 5 Sonic). Metadata now lives in the JSON files and is automatically maintained.

Automated Governance Metadata Updates

  • script/UpdateGovernanceMetadata.s.sol — Standalone script that auto-fills pending governance metadata:
    • Case A (proposalId == 0): Deploys script artifact via vm.deployCode(), calls buildGovernanceProposal() to compute expected proposal ID, verifies it exists on-chain
    • Case B (proposalId > 1 && tsGovernance == 0): Uses FFI to query ProposalExecuted events and find execution timestamp
  • find_gov_prop_execution_timestamp.sh — Bash helper using cast logs/cast find-block/cast block to locate proposal execution timestamps
  • .github/workflows/update-deployments.yml — CI job running every hour (+ manual trigger), auto-commits updated build/deployments-*.json
  • Makefile — New update-deployments target for local execution

Smoke Test Refactor

  • Moved initialization from constructor() to setUp() so logs are visible on test failure
  • All four concrete smoke tests updated to function setUp() public override with super.setUp() call

Other Changes

  • Script 017_UpgradeLidoARMScript.s.sol fixed to use resolver.implementations("LIDO_ARM_IMPL") in governance proposal (works when called externally by UpdateGovernanceMetadata)
  • New contract entries: MORPHO_MARKET_ORIGIN and MORPHO_MARKET_ORIGIN_IMPL
  • Added missing execution entry for 013_UpgradeOETHARMScript
  • Updated OETH_ARM_IMPL implementation address

Test plan

  • make test-smoke passes with MAINNET_URL
  • make simulate replays deployment history successfully
  • make simulate with FORK_BLOCK_NUMBER_MAINNET set to a historical block replays correctly
  • make update-deployments resolves pending governance metadata on mainnet fork
  • CI workflow update-deployments.yml triggers and auto-commits correctly

Replace the manual `proposalExecuted` flag and `maxDeploymentFiles` limit
with timestamp-based metadata (tsDeployment, proposalId, tsGovernance) in
the deployment JSON. This enables DeployManager to deterministically replay
deployments for any historical fork block by filtering on timestamps.

Key changes:
- Execution struct now carries proposalId, tsDeployment, tsGovernance
- Resolver stores per-script governance metadata mappings
- DeployManager iterates all scripts, skipping completed ones via
  _canSkipDeployFile() instead of limiting to last N files
- _preDeployment() filters future deployments and adjusts governance
  timestamps for historical forks
- AbstractDeployScript splits contract storage from execution recording
  and removes proposalExecuted() virtual function
- All 20 deploy scripts cleaned of proposalExecuted overrides
- Added missing 013_UpgradeOETHARMScript entry to deployments-1.json

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@clement-ux clement-ux changed the base branch from main to clement/refactor-deployment February 5, 2026 11:18
@clement-ux clement-ux changed the title Replace proposalExecuted with timestamp-based deployment metadata [Refactor] Replace proposalExecuted with timestamp-based deployment Feb 5, 2026
Constructor logs are not printed on test failure, making debugging
difficult. Moving initialization to setUp() ensures all logs are
visible when a smoke test fails.
@clement-ux clement-ux self-assigned this Feb 9, 2026
@clement-ux clement-ux added Feature Introduces new functionality. Tooling Scripts, automation, and utilities. Deployment script Deployment script for smart contract. labels Feb 9, 2026
clement-ux and others added 3 commits February 11, 2026 08:26
* Add automated governance metadata updates for deployments JSON

Add a standalone Foundry script and CI workflow that automatically fills
in proposalId and tsGovernance in build/deployments-1.json after
governance proposals are submitted and executed on-chain.

- script/UpdateGovernanceMetadata.s.sol: core script handling two cases
  - Case A (proposalId == 0): finds proposalId via buildGovernanceProposal()
  - Case B (tsGovernance == 0): finds execution timestamp via FFI + cast logs
- script/deploy/helpers/find_execution_timestamp.sh: FFI helper querying ProposalExecuted events
- .github/workflows/update-deployments.yml: CI job running every 6 hours
- Makefile: add update-deployments target
- AbstractDeployScript: add buildGovernanceProposal() external entry point

* Run forge fmt

* Rename find_execution_timestamp.sh to find_gov_prop_execution_timestamp.sh
@clement-ux clement-ux changed the title [Refactor] Replace proposalExecuted with timestamp-based deployment [Refactor] Timestamp-based deployment metadata & automated governance tracking Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Deployment script Deployment script for smart contract. Feature Introduces new functionality. Tooling Scripts, automation, and utilities.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant