fix: #2308 declare CCIP approve with no outputs and narrow the LayerZero rationale - #2390
Open
suisuss wants to merge 1 commit into
Open
fix: #2308 declare CCIP approve with no outputs and narrow the LayerZero rationale#2390suisuss wants to merge 1 commit into
suisuss wants to merge 1 commit into
Conversation
…ero rationale Follow-up to #2389, from an independent review of it. protocols/abis/ccip-erc20.json carried the same defect that PR fixed one file over: approve declared a bool output. Both contracts bound to it (ccipBridgeToken, ccipFeeToken) take a user-supplied token address, and USDT is a CCIP-supported bridge and fee token, so the EOA preflight staticCall decodes USDT's empty return as a bool and throws BAD_DATA before the approve is broadcast. The coverage suite cannot catch it: its reference tokens are WETH/WBNB/WMATIC/WAVAX, all bool-returning, and both approve actions are skipped there. #2389's replacement comment also overstated the failure in the same direction as the comment it corrected. Only the EOA path decodes; Safe, Safe-role and Turnkey-sponsored sends encode and estimate gas without a staticCall, so a bool declaration survives them. That distinction decides whether a repro reproduces. The regression test #2389 added asserted that a 32-byte bool return decodes, which holds under either declaration and so discriminated nothing. Dropped, and an equivalent guard added for the CCIP ABI, which has no coverage-suite backstop at all. docs/plugins/layerzero.md documented `result | bool` for OFT Approve. Write actions surface success/error/transactionHash/transactionLink - buildOutputFieldsFromAction gates ABI outputs on read actions - so that row was wrong before this change and contradicted the ABI after it.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Follow-up to #2389, from an independent review of that PR. Four fixes, none of which change runtime behaviour for a conforming token.
1.
protocols/abis/ccip-erc20.jsonhad the same defect, one file overapprovedeclared abooloutput. Both contracts bound to that ABI -ccipBridgeTokenandccipFeeToken- areuserSpecifiedAddress: true, and USDT is a CCIP-supported bridge and fee token. So on the EOA path the adapter's preflightstaticCalldecodes USDT's empty return as a bool, throwsBAD_DATA, and the approve fails before it is broadcast - byte for byte the failure #2389 fixed for LayerZero.The coverage suite cannot catch this.
CCIP_ERC20_ADDRESSESpoints at WETH/WBNB/WMATIC/WAVAX, which all returnbool, and both approve actions are skipped in the fixture regardless. Guarded here with a unit test instead; verified it fails when thebooldeclaration is restored.2. #2389's comment overstated the failure, in the same direction as the comment it replaced
It said the mismatch "is not inert on the write path". Only the EOA path decodes:
staticCall?encodeFunctionData+estimateGasencodeFunctionDataonlyThe comment it corrected claimed the write path never decodes; its replacement implied it always does. Both wrong, opposite directions. This matters practically: the same node, ABI and token fails for an EOA connection and succeeds for a Safe one, so a repro that omits the signer mode proves nothing either way.
3. One assertion in #2389's test discriminated nothing
decodeFunctionResult("approve", bool32)not throwing holds underoutputs: [bool]as well asoutputs: [], so it documented rather than tested. Dropped.Worth noting what this test still is not: a guard on the mechanism. Nothing exercises
EvmChainAdapter.executeContractCallagainst a provider returning"0x". A stubbed-provider test there would cover every write ABI at once, includinglib/contracts/abis/erc20.json, which still declaresboolonapprove/transfer/transferFrom. Both are left to the separately tracked ticket rather than widened onto a release branch.4.
docs/plugins/layerzero.mddocumented an output that never existedThe OFT Approve page listed
result | bool | Result.buildOutputFieldsFromActiongates ABI outputs onaction.type === "read", so a write action surfacessuccess,error,transactionHash,transactionLink. That row was wrong before this change and contradicted the shipped ABI after it.Verification
tests/unit/protocol-layerzero.test.ts(22) andtests/unit/protocol-chainlink.test.ts(30) pass;protocol-calldata(508) unaffectedbooldeclaration is restored, so it is a real guardbiome checkclean on all five changed files