Skip to content

fix: KEEP-393 drop stale ethValue when target function is non-payable#1092

Merged
suisuss merged 3 commits intostagingfrom
fix/KEEP-393-stale-ethvalue-not-payable
May 3, 2026
Merged

fix: KEEP-393 drop stale ethValue when target function is non-payable#1092
suisuss merged 3 commits intostagingfrom
fix/KEEP-393-stale-ethvalue-not-payable

Conversation

@suisuss
Copy link
Copy Markdown

@suisuss suisuss commented May 2, 2026

Summary

When an action node is reconfigured (e.g. from a Wrap WETH deposit to a Uniswap V3 swap), the form retains stale ethValue and abiFunction fields from the previous configuration. The stale ethValue reaches writeContractCore, which rejects the call against the (correctly) non-payable exactInputSingle ABI:

Function 'exactInputSingle' is not payable - cannot send a non-zero value with this call

protocol-write now drops ethValue when the resolved function ABI declares a non-payable mutability. When the function is missing from the ABI or its mutability cannot be determined, the value passes through unchanged so writeContractCore's existing errors are preserved.

This is the server-side defense in depth. The companion UI fix (clear ethValue / abiFunction / contract overrides on action-type change) is tracked separately in KEEP-393.

Linear

KEEP-393

Test plan

  • pnpm vitest run tests/unit/protocol-write-step.test.ts - 23/23 pass (4 new cases for KEEP-393)
  • pnpm check - clean on changed files
  • pnpm type-check - clean
  • Manual verification on staging: reconfigure a node from Wrap WETH to Uniswap V3 Swap Exact Input, confirm swap succeeds without "function not payable" error
  • Manual regression: confirm Wrap WETH (payable) still receives ethValue

Form state can retain ethValue from a previous action configuration
(e.g. WETH.deposit) when the action type is changed to a non-payable
function (e.g. Uniswap V3 exactInputSingle). The stale value caused
writeContractCore to surface "Function 'X' is not payable" instead of
the swap succeeding.

protocol-write now drops ethValue when the resolved function ABI
declares a non-payable mutability. When the function is missing from
the ABI or its mutability cannot be determined, the value passes
through so writeContractCore's existing errors are unchanged.
Silently dropping ethValue could mask user intent (e.g. a fork exposing
a payable variant the reduced ABI does not). Emit a CONFIGURATION
warning via logUserError when the drop fires, with the function name,
protocol slug, and the dropped value as labels. Surfaces in console
(warn level) and Prometheus, no DevOps alert.
Cover the conservative-pass-through contract:
- ABI is valid JSON but not an array (e.g. wrapped {abi: [...]})
- function ABI item has no stateMutability field (pre-0.5 ABIs)
- function is view or pure (parameterised case via it.each)

The view/pure cases also assert the drop logs with the matching
state_mutability label so downstream metrics can distinguish causes.
@suisuss suisuss merged commit 650ef0f into staging May 3, 2026
33 checks passed
@suisuss suisuss deleted the fix/KEEP-393-stale-ethvalue-not-payable branch May 3, 2026 03:02
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

🧹 PR Environment Cleaned Up

The PR environment has been successfully deleted.

Deleted Resources:

  • Namespace: pr-1092
  • All Helm releases (Keeperhub, Scheduler, Event services)
  • PostgreSQL Database (including data)
  • LocalStack, Redis
  • All associated secrets and configs

All resources have been cleaned up and will no longer incur costs.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 3, 2026

ℹ️ No PR Environment to Clean Up

No PR environment was found for this PR. This is expected if:

  • The PR never had the deploy-pr-environment label
  • The environment was already cleaned up
  • The deployment never completed successfully

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant