You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Validates ERC20 call return semantics in the Cadence worker so EVM-level call success is not treated as token-operation success when ERC20 methods explicitly return false.
Key points:
completeProcessing() now validates ERC20 approve(address,uint256) return data when present
bridgeERC20ToEVM() now validates ERC20 transfer(address,uint256) return data when present
Empty return data is still accepted for compatibility with non-standard ERC20 tokens
Malformed/non-boolean return payloads are treated as failure
On failed refund path, approve that returns false (or invalid bool data) now emits RequestFailed and aborts completion
ERC20 transfer to recipient now panics if return data indicates semantic failure
Updated function docs to clarify return-data validation behavior
Test plan
env FOUNDRY_OFFLINE=true forge test --match-contract FlowYieldVaultsRequestsTest --threads 1
flow test cadence/tests/evm_bridge_lifecycle_test.cdc(fails in current environment due unresolved Cadence dependency/import setup, e.g. missing DeFiActions declaration in imported FlowYieldVaults)
This fix correctly addresses the semantic gap between EVM-level call success and ERC20 boolean return values. The overall approach is sound. Below are observations from most to least significant.
Issues
1. Requests can get stuck in PROCESSING state when approve returns false
Severity: Medium (pre-existing behavior extended to a new path)
When approve returns false at line 1108–1119, completeProcessing() returns falsewithout ever calling the Solidity completeProcessing(). But startProcessing() was already called earlier in the flow, leaving the request in PROCESSING state permanently on the Solidity side.
// If this returns false, the request is stuck in PROCESSING on the Solidity sideif!FlowYieldVaultsEVM.isERC20BoolReturnSuccess(approveResult.data) {
emitRequestFailed(...)
returnfalse// Solidity completeProcessing() never called
}
The existing EVM-level approveResult.status check at line 1094 has the same behavior, so this PR doesn't introduce a regression — but it adds a second code path with the same silent-stuck-request risk. Consider whether completeProcessing() should call the Solidity contract with success: false even when the refund mechanism fails, so requests never get stranded.
2. Approved allowance leaks on downstream failure
Severity: Low (pre-existing, unrelated to this PR)
If approve passes (both EVM status and bool check), but the subsequent Solidity completeProcessing() call fails at line 1130, the token allowance for flowYieldVaultsRequestsAddress remains set. An attacker who can craft a transaction that passes the approve check but fails completeProcessing() gains an unspent allowance. Worth noting for future hardening (e.g., approve(..., 0) cleanup on failure).
3. Error-handling asymmetry between completeProcessing and bridgeERC20ToEVM
Severity: Informational
completeProcessing uses graceful return false when approve returns false; bridgeERC20ToEVM uses panic when transfer returns false. This is internally consistent (panic already existed for EVM-level transferResult.status failures), but it's worth documenting why panic is correct here.
Since depositTokens (line 1246) and coaRef.call (line 1256) are both EVM operations within the same Cadence transaction, a panic atomically reverts both — so the tokens aren't lost. The doc comment could note this explicitly to avoid future confusion.
ABI-encoded bool true is 0x0000...0001 (32 bytes, big-endian), and the loop correctly validates bytes 0–30 are zero and byte 31 is exactly 1. The access(self) contract-level placement is appropriate for a pure utility function.
Minor style note: the while loop could use for i in 0..<31 in newer Cadence, but the current form is readable and correct.
Test Coverage Gap
This is the most actionable concern. Neither evm_bridge_lifecycle_test.cdc nor error_handling_test.cdc contains any test for:
The PR notes the Cadence test environment is broken. Before merge, at minimum isERC20BoolReturnSuccess should have unit tests since it's pure logic with no external dependencies. Suggested cases:
The fix is directionally correct and the validation logic is sound. Main ask: add unit tests for isERC20BoolReturnSuccess and integration tests for the new failure paths before merging.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #28
Validates ERC20 call return semantics in the Cadence worker so EVM-level call success is not treated as token-operation success when ERC20 methods explicitly return
false.Key points:
completeProcessing()now validates ERC20approve(address,uint256)return data when presentbridgeERC20ToEVM()now validates ERC20transfer(address,uint256)return data when presentChanges:
isERC20BoolReturnSuccess(_ data: [UInt8]): Boolapprovethat returnsfalse(or invalid bool data) now emitsRequestFailedand aborts completionTest plan
env FOUNDRY_OFFLINE=true forge test --match-contract FlowYieldVaultsRequestsTest --threads 1flow test cadence/tests/evm_bridge_lifecycle_test.cdc(fails in current environment due unresolved Cadence dependency/import setup, e.g. missingDeFiActionsdeclaration in importedFlowYieldVaults)