Two separate, both-confirmed gaps in the model-owner tooling, batched here since they're the same area of the codebase (dincli/cli/modelownerd/) and the same root-cause category (dincli not kept in sync with a foundry/src contract change).
Part 1 (BL-27): dincli model-owner deploy is broken against current contracts
dincli/cli/modelownerd/deploy.py calls:
DINTaskCoordinator_contract.constructor(din_validator_stake_address) # 1 arg
DINTaskAuditor_contract.constructor(din_validator_stake_address, task_coordinator_address) # 2 args
but the actual constructors (foundry/src/DINTaskCoordinator.sol:290, foundry/src/DINTaskAuditor.sol:406-410, verified against develop @ 740a613) are:
constructor(address dinvalidatorStakeContract_address, uint256 modelId_)
constructor(address _dinvalidatorStakeContract_address, address _dintaskcoordinator_contract_address, uint256 modelId_)
Both calls are missing modelId_. Verified by inspection against the current ABI — dincli model-owner deploy task-coordinator/task-auditor will fail at ABI encoding today. This is hidden in testing because tests/ deploys task contracts from stale hardhat artifacts, not the bundled foundry-derived ABIs.
This isn't a one-line fix — DINModelRegistry only assigns modelId at approveModel() time, after the task contracts must already exist (the registration flow requires already-deployed, already-owned taskCoordinator/taskAuditor addresses as input). So deploy-time modelId_ doesn't exist yet when these constructors run. Needs a decision: a placeholder/sentinel modelId at deploy time later reconciled at approval, a registry-side pre-assignment step before deploy, or a constructor change removing the dependency — out of scope for me to prescribe here, flagging for whoever picks this up.
Part 2 (BL-28): no dincli command for releaseGIRegistrationSlots
DINTaskCoordinator.releaseGIRegistrationSlots(gi) (L1287-1299) is the only function that decrements validators' activeRegistrationCount after a GI ends — endGI deliberately doesn't, to stay O(1) (BL-10). It's present in the bundled ABI (dincli/abis/DINTaskCoordinator.json) but grepping all of dincli/ turns up zero callers.
Currently harmless: maxConcurrentRegistrationsPerStakeUnit (DinValidatorStake.sol:115) defaults to 0, so the cap it would otherwise enforce (TC_ConcurrentRegistrationCapReached/TA_ConcurrentRegistrationCapReached) never fires. But the moment any network sets that cap above 0, every ended GI permanently consumes its validators' concurrent-registration slots until they hit the cap — with no dincli path to call the one function that frees them.
Suggested approach
- Part 1: fix the constructor args once the
modelId sourcing decision is made; add a dincli-level smoke test that actually deploys against the real foundry artifact (not hardhat) to catch this class of drift going forward.
- Part 2: add
dincli model-owner release-gi-slots <gi> (or fold into an existing model-owner gi ... subcommand), callable any time after the target GI reaches GIended.
References
Two separate, both-confirmed gaps in the model-owner tooling, batched here since they're the same area of the codebase (
dincli/cli/modelownerd/) and the same root-cause category (dincli not kept in sync with afoundry/srccontract change).Part 1 (BL-27):
dincli model-owner deployis broken against current contractsdincli/cli/modelownerd/deploy.pycalls:but the actual constructors (
foundry/src/DINTaskCoordinator.sol:290,foundry/src/DINTaskAuditor.sol:406-410, verified againstdevelop@740a613) are:Both calls are missing
modelId_. Verified by inspection against the current ABI —dincli model-owner deploy task-coordinator/task-auditorwill fail at ABI encoding today. This is hidden in testing becausetests/deploys task contracts from stale hardhat artifacts, not the bundled foundry-derived ABIs.This isn't a one-line fix —
DINModelRegistryonly assignsmodelIdatapproveModel()time, after the task contracts must already exist (the registration flow requires already-deployed, already-ownedtaskCoordinator/taskAuditoraddresses as input). So deploy-timemodelId_doesn't exist yet when these constructors run. Needs a decision: a placeholder/sentinelmodelIdat deploy time later reconciled at approval, a registry-side pre-assignment step before deploy, or a constructor change removing the dependency — out of scope for me to prescribe here, flagging for whoever picks this up.Part 2 (BL-28): no dincli command for
releaseGIRegistrationSlotsDINTaskCoordinator.releaseGIRegistrationSlots(gi)(L1287-1299) is the only function that decrements validators'activeRegistrationCountafter a GI ends —endGIdeliberately doesn't, to stay O(1) (BL-10). It's present in the bundled ABI (dincli/abis/DINTaskCoordinator.json) but grepping all ofdincli/turns up zero callers.Currently harmless:
maxConcurrentRegistrationsPerStakeUnit(DinValidatorStake.sol:115) defaults to0, so the cap it would otherwise enforce (TC_ConcurrentRegistrationCapReached/TA_ConcurrentRegistrationCapReached) never fires. But the moment any network sets that cap above 0, every ended GI permanently consumes its validators' concurrent-registration slots until they hit the cap — with no dincli path to call the one function that frees them.Suggested approach
modelIdsourcing decision is made; add a dincli-level smoke test that actually deploys against the real foundry artifact (not hardhat) to catch this class of drift going forward.dincli model-owner release-gi-slots <gi>(or fold into an existingmodel-owner gi ...subcommand), callable any time after the target GI reachesGIended.References
Developer/BACK_LOG.mdBL-27, BL-28dinrep deploy, fix add-slasher crash; refresh contract docs (#203) #204 review (source of both findings)endGIdoesn't release slots inline)