Skip to content

Latest commit

 

History

History
109 lines (74 loc) · 6.18 KB

task_240626_0b.md

File metadata and controls

109 lines (74 loc) · 6.18 KB

Task for — Robbert Abimbola

ID: task_240626_0b
Assigned to: Robbert Abimbola
Created: 2026-06-24
Status: Open (PR#13 submitted — pending merge)
Roadmap ref: P3 — Security, Integration, and Testnet Readiness (contract upgrade flows)
Option chosen: Option A — Upgradeable platform contracts
PR: #13 (robertocarlous:feature/platform-upgradeable)


1. Project Summary

DIN (InfiniteZero) is a federated-learning network coordinated by Solidity contracts on Optimism Sepolia. Raw training data never leaves a participant's machine — only model artifacts (pinned to IPFS) and on-chain coordination state are shared. Participants run dincli, a Python/Typer CLI, to act as clients (local training), auditors (scoring), or aggregators (combining models).

The contract layer has two tiers:

  • Platform-level contracts (deployed once by the DIN-Representative): DinCoordinator, DinToken, DinValidatorStake, DINModelRegistry — all under hardhat/contracts/.
  • Task-level contracts (deployed per model by the model owner): DINTaskCoordinator, DINTaskAuditor.

2. What Was Already Done (baseline)

  • All 4 platform contracts exist, are deployed, and work as plain (non-upgradeable) contracts: constructor-based init, Ownable (or a bespoke daoAdmin field on DINModelRegistry), some immutable cross-contract references (e.g. DinValidatorStake holds immutable DIN_TOKEN/DIN_COORDINATOR addresses).
  • Test coverage on the 4 contracts was thin — only hardhat/test/DinValidatorStake.test.ts existed. The other 3 had no dedicated tests.
  • Working-draft design doc: Developer/issues/upgradable-contracts.md (treat as draft — call out stale/inconsistent items).

3. Task — Option A: Upgradeable platform contracts

Convert the 4 platform-level contracts from plain/constructor-based to an upgradeable pattern, with tests proving upgrades preserve state and access control.

Required pieces

  1. Pick a proxy pattern (UUPS or Transparent Proxy) — document why.
  2. Convert all 4 contracts: replace constructors with initialize() functions (Initializable), remove/relocate any immutable cross-contract references, audit storage layout (document the rules followed).
  3. Add Hardhat deploy scripts for proxy deployment of each contract (initial deploy + upgrade flow).
  4. Add upgrade-safety tests per contract: state persists across an upgrade, access control still holds post-upgrade, storage-layout regressions caught (via hardhat-upgrades validateUpgrade()).
  5. Short write-up: what changed per contract, the proxy pattern chosen and why, and any deviation from the existing Ownable/daoAdmin access model.

Explicitly out of scope

  • Governance/DAO redesign, task-level contracts (DINTaskCoordinator/DINTaskAuditor), changes to dincli.

4. Deliverables Checklist

  • Proxy pattern chosen and justified — Transparent Proxy (OpenZeppelin @openzeppelin/hardhat-upgrades, PROXY_KIND = "transparent")
  • All 4 contracts converted to initializer pattern, storage-layout-safe
  • Hardhat deploy scripts for proxy deploy + upgrade — hardhat/scripts/deploy-platform.ts, hardhat/scripts/upgrade-platform.ts
  • Upgrade-safety tests per contract — 12 tests (3 per contract): state persistence, access control, validateUpgrade() storage check
    • hardhat/test/DinToken.upgrade.test.ts
    • hardhat/test/DinCoordinator.upgrade.test.ts
    • hardhat/test/DinValidatorStake.upgrade.test.ts
    • hardhat/test/DINModelRegistry.upgrade.test.ts
  • Write-up of changes and proxy pattern rationale — in PR#13 description
  • Doc-inaccuracy notes from upgradable-contracts.md — listed in PR#13 description

5. Key Design Decisions (from PR#13)

Proxy pattern: Transparent Proxy over UUPS because upgrade authority is separated from implementation logic — a bad V2 cannot brick the proxy by omitting upgrade functions. Fits the current model where the DIN-Representative controls upgrades; ProxyAdmin ownership can transfer to a multisig later.

Deployment order (proxies cannot use nested new Contract()):

  1. Deploy DinToken proxy → initialize()
  2. Deploy DinCoordinator proxy → initialize(dinTokenAddress)
  3. DinToken.setCoordinator(dinCoordinatorAddress)
  4. Deploy DinValidatorStake proxy → initialize(dinTokenAddress, dinCoordinatorAddress)
  5. DinCoordinator.updateValidatorStakeContract(stakeAddress)
  6. Deploy DINModelRegistry proxy → initialize(stakeAddress)

Access model deviation: DINModelRegistry's bespoke daoAdmin / setDAOAdmin / DAOAdminUpdated removed in favour of standard OZ OwnableUpgradeable (owner() / transferOwnership()). dincli ABIs referencing the old interface will need a follow-up update when testnet is redeployed (out of scope for this PR).

Storage layout rules: no reordering/removal of existing variables; new variables only appended; immutable cross-contract refs replaced with regular storage; hardhat-upgrades validateUpgrade() run in tests before each upgrade.


6. Doc Inaccuracies Found (Developer/issues/upgradable-contracts.md)

  • Platform contracts used constructors — now converted to initialize().
  • DinToken immutable OWNER — now coordinator storage.
  • DinCoordinator immutable dinToken + inline new DinToken() — now external token proxy + storage ref.
  • DinValidatorStake immutable DIN_TOKEN/DIN_COORDINATOR — now storage.
  • DINModelRegistry uses mutable daoAdmin but is not proxy-based — now proxy + OwnableUpgradeable.
  • hardhat/test/DinValidatorStake.test.ts described as existing — it did not exist on develop; PR#13 adds the first test suite.
  • hardhat-upgrades toolchain missing from doc — added in PR#13.
  • Deploy scripts for platform proxies missing from doc — added deploy-platform.ts and upgrade-platform.ts.

7. Running the Tests

cd hardhat && npm test

Expected: 12 passing upgrade-safety tests (3 per platform contract).


8. Submission

PR#13 open against develop: #13
Branch: robertocarlous:feature/platform-upgradeable