feat(escrow_manager): reclaim idle escrow via thaw and withdraw - #21
Conversation
Signed-off-by: Tomás Migone <tomas@edgeandnode.com>
Coverage Report for CI Build 35750383409Coverage decreased (-2.0%) to 44.122%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
Signed-off-by: Tomás Migone <tomas@edgeandnode.com>
Signed-off-by: Tomás Migone <tomas@edgeandnode.com>
Signed-off-by: Tomás Migone <tomas@thegraph.foundation>
Signed-off-by: Tomás Migone <tomas@thegraph.foundation>
Signed-off-by: Tomás Migone <tomas@thegraph.foundation>
aac87b1 to
71c72d1
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Subgraph state correctness, collector scoping, and unbounded transaction batches can cause incorrect deposits or indefinitely failing reclamation.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 4
Open (5)
Unbounded thaw multicall can exceed block gas limit · New Unbounded withdrawal multicall can exceed block gas limit · New Filter escrow accounts by collector before receiver map collapse · New Stale subgraph thaw state causes invalid withdrawals · New Status color overrides do not match legend series names · New
What changed in this PR
Adds opt-in escrow reclamation through thawing and withdrawal while preserving deposit-only defaults.
Changes:
- Adds reclamation configuration and decision logic.
- Adds contract operations, subgraph state, metrics, tests, and documentation.
- Extends the Grafana dashboard with reclamation monitoring.
| File | Description |
|---|---|
grafana/escrow_manager.json |
Adds reclamation panels and layout. |
crates/bin/escrow_manager/src/subgraphs.rs |
Queries thawing account state. |
crates/bin/escrow_manager/src/metrics.rs |
Adds thaw and withdrawal metrics. |
crates/bin/escrow_manager/src/main.rs |
Plans and executes reclamation actions. |
crates/bin/escrow_manager/src/contracts.rs |
Implements thaw and withdrawal calls. |
crates/bin/escrow_manager/src/config.rs |
Adds reclamation settings and defaults. |
crates/bin/escrow_manager/README.md |
Documents behavior, configuration, and metrics. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Signed-off-by: Tomás Migone <tomas@thegraph.foundation>
Signed-off-by: Tomás Migone <tomas@thegraph.foundation>
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It introduces irreversible protocol transactions with an unverified deployed-subgraph dependency, and the identified dashboard and operational-guidance issues remain unresolved.
Review effort: Balanced
Findings: None
Resolved since last review (5)
Signed-off-by: Tomás Migone <tomas@thegraph.foundation>


Overview
The manager only deposited, so balances were a high-water mark of past debt. It can now reclaim idle escrow to the payer wallet, behind
withdraw_enabled(defaultfalse).One action per receiver per cycle, first match wins:
Approach
adjustThawandcancelThawstay unused. These are new interfaces in the contract but for simplicity thaws only start from zero, so plainthawsuffices.Configuration
withdraw_enabled— new, defaults tofalse. No action needed; settrueto reclaim escrow.withdraw_margin— new, defaults to0.25. No action needed.min_withdraw_grt— new, defaults to500. No action needed.Motivation
#18 measured the escrow at ~2.87M GRT against ~1M GRT of debt and noted the algorithm targets ~1.67x but has no way to withdraw. This closes that gap.
Cross-component
The escrow accounts query now selects
totalAmountThawingandthawEndTimestamp— an upstream dependency on the network subgraph exposing both. The query fails if a deployed version lacks them. Not verified; confirm against the deployed subgraph before merging.Risk assessment
blast_radius: protocol— thaws and withdrawals are on-chain state receivers observe on their own escrow accounts; the default keeps it off until deliberately enabled.reviewer_effort: deep— the decision logic is small and tested, but its correctness rests onPaymentsEscrowsemantics this repo only vendors an ABI for.primary_concern— with no cancel path, a thaw's full amount leaves at maturity, so the compensating deposit must fit the payer allowance and the 10,000 GRTMAX_ADJUSTMENTcap.irreversible— not the merge, which is deposit-only at the defaults, but the enablement: a thaw is a 28-day on-chain commitment that reverting the code does not cancel.