Conversation
…n-state fix & RPC E2E proof) (#624) Co-authored-by: Antriksh Gwal <antrikshgwal@gmail.com> Co-authored-by: Will Zimmerman <will@avaprotocol.org>
…dler URLs resolve
The renamed config/test.yaml references the bundler endpoints via
${SEPOLIA_BUNDLER_URL} / ${BASE_SEPOLIA_BUNDLER_URL}, which the config
loader expands from the process environment. testutil only loaded .env,
and both dotenv files are gitignored — so in a fresh git worktree the vars
were unset, expanded to empty, and bundler-dependent tests panicked with
"BundlerURL is empty in test.yaml config".
LoadDotEnv now loads .env.local then .env (local overrides, real env wins
over both), logs when neither is present so a missing dotenv in a worktree
is no longer a silent mystery, and factors single-file parsing into
loadDotEnvFile.
…th B) (#626) Co-authored-by: Will Zimmerman <will@avaprotocol.org>
There was a problem hiding this comment.
Pull request overview
This PR promotes staging → main changes that (1) shift email notification summarization/distribution to Studio’s /api/notify (“Path B”) and (2) add user-supplied erc20_overrides to RunNodeImmediately so isolated contract-write simulations can be seeded with ERC20 balance/allowance state (plus supporting docs/tests and OpenAPI/proto updates).
Changes:
- Route REST notification nodes targeting
/api/notifyto forward raw execution payloads to Studio (gateway no longer does SendGrid-coupled summarization for that path) while preserving summary surfacing to SDK/UI. - Add
erc20_overridesto RunNodeImmediately request flow (proto + OpenAPI + REST handler wiring), implement validation/state seeding, and fix simulation-state propagation so overrides actually reach Tenderly. - Improve test ergonomics and coverage (dotenv auto-load for tests; unit tests for override parsing/validation; E2E proof test for Uniswap swap with/without overrides).
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| protobuf/avs.proto | Adds erc20_overrides + ERC20StateOverride message to RunNodeImmediately request. |
| protobuf/avs.pb.go | Regenerated Go bindings for the proto changes. |
| api/openapi.yaml | Exposes erc20Overrides + ERC20StateOverride schema in REST API spec. |
| aggregator/rest/generated/types.gen.go | Regenerated OpenAPI types including ERC20StateOverride and request field. |
| aggregator/rest/handlers_nodes.go | Wires REST erc20Overrides into proto request; slot widening helper. |
| core/testutil/utils.go | Loads .env.local then .env for tests; adds clearer logging/behavior docs. |
| core/taskengine/run_node_immediately.go | Threads and validates erc20_overrides into VM simulation state (simulation-only). |
| core/taskengine/vm.go | Propagates simulationState into per-node temp VM so overrides reach Tenderly. |
| core/taskengine/simulation_state.go | Adds uint256 parsing + explicit slot validation + ApplyUserERC20Override implementation. |
| core/taskengine/simulation_state_override_test.go | New unit tests for uint256 parsing and ERC20 override validation/application. |
| core/taskengine/run_node_immediately_rpc_test.go | Adds end-to-end RPC test proving overrides flip Uniswap swap outcome. |
| core/taskengine/vm_runner_rest.go | Implements /api/notify “studio-notify” path, payload injection, and summary surfacing. |
| core/taskengine/summarizer_context_memory.go | Adds BuildNotifyPayload to build raw execution-data payload for Studio /api/notify. |
| core/taskengine/summarizer_deterministic.go | Updates notification provider naming/detection to “studio-notify” → “Ava Protocol”. |
| core/taskengine/summarizer_run_node_test.go | Updates expectations for /api/notify provider display name. |
| core/taskengine/vm_runner_contract_write_uniswap_test.go | Clarifies Uniswap quote test intent; tightens assertions and removes stale TODOs. |
| core/taskengine/TENDERLY_STATE_OVERRIDES.md | Updates docs to reflect implemented override paths and user-facing API. |
Files not reviewed (1)
- protobuf/avs.pb.go: Generated file
Comments suppressed due to low confidence (1)
core/testutil/utils.go:142
- The init comment is now incorrect: LoadDotEnv loads .env.local and .env (in that order), not just .env, and the inline comment still says it loads only .env. Please update these comments so future readers don’t assume only .env is supported.
// init loads environment variables from .env file only.
// Test config is now lazily loaded on first use to avoid loading during production binary startup.
func init() {
// Load .env file first (if it exists)
_ = LoadDotEnv()
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Optionally compose summary and inject into provider payloads when enabled via nodeConfig.options.summarize | ||
| // Keep a reference to the composed summary so we can return it to clients even | ||
| // when the external notification provider (e.g., SendGrid) returns an empty body. | ||
| var summaryForClient *Summary |
Code Review — PR #627This PR bundles two independent features: (1) user-facing Findings1. Success is determined solely by HTTP status code ( Fix: After the if isStudioNotify {
if m, ok2 := jsonData.(map[string]interface{}); ok2 {
if okVal, _ := m["ok"].(bool); !okVal {
stepSuccess = false
errorMessage = fmt.Sprintf("notify: %v", m["error"])
}
}
}2. The previous implementation recognised SendGrid URLs and excluded those REST nodes from workflow step counts. The new implementation only matches 3. When 4. When both the target holder and reference addresses ( 5. The proto slice 6. The hardcoded bases (Ethereum 19.5M, Base 11.5M) are from late 2024; as of June 2026 Ethereum mainnet is at ~22.5M and Base at ~26M. These flow into 7. vm.AddVar("aa_sender", "0x5d814Cc9E94B2656f59Ee439D44AA1b6ca21434f")CLAUDE.md states: "Never use 8. return strings.Title(strings.TrimSpace(t)) // deprecatedWill surface in Summary
🤖 Generated with Claude Code |
…) before promotion main carried an unsynced release (#627 Path B /api/notify + erc20_overrides, plus version bumps v3.11.0 / v3.12.0) that never came back to staging, so the staging→main PR (#636) conflicted. Back-merge main into staging to realign. Conflict resolutions: - summarizer_deterministic.go, summarizer_run_node_test.go: kept DELETED — staging removed the deterministic summarizer in #628; main only modified them. - vm_runner_rest.go, summarizer_context_memory.go: kept STAGING's Path-B-only notify rewrite (#628/#629) — it supersedes main's older #627 notify code (removed the duplicate BuildNotifyPayload, legacy telegram branch, summaryForClient). - run_node_immediately_rpc_test.go: kept staging's explicit per-node ChainId (G5 strict). Net effect on staging: brings in main's version bump (3.10.4 → 3.12.0); everything else from #627 was already present (#624/#626) or superseded. Build + affected suites green.
Staging → main release. Storage-check: ✅ no breaking changes (additive-only).
Included
feat: gateway forwards Email-node summaries to Studio /api/notify (Path B) (feat: gateway forwards Email-node summaries to Studio /api/notify (Path B) #626)
Workflow Email/Telegram nodes POST raw execution data to Studio's
/api/notify, which summarizes AND distributes. Replaces the gateway-side SendGrid coupling;detectNotificationProvidernow routes/api/notify→studio-notify. Config:email_url/email_api_token(reusesSUMMARIZER_API_URL/SUMMARIZER_API_KEY).feat: user-facing erc20_overrides for RunNodeImmediately (feat: user-facing erc20_overrides for RunNodeImmediately (+ simulation-state fix & RPC E2E proof) #624)
Adds
erc20_overrides(+ simulation-state fix & RPC E2E proof) — proto additive (protobuf/avs.proto+23), regenerated bindings.test: auto-load .env.local + .env in testutil so
test.yaml${VAR}bundler URLs resolve.Pre-merge checks
make storage-check→ ✅ key templates unchanged, model structs unchanged🤖 Generated with Claude Code