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
/// @notice Allows contract to receive native $FLOWreceive() externalpayable {}
to avoid accidental native FLOW token transfers to the contract, as it is not necessary for the contract's operation.
Introduced a new recoverTokens(to, tokenAddress, amount) Solidity function which allows only the contract's owner, to recover any ERC20 tokens through accidental user transfers.
Added some more unit tests, to verify that all 3 payable functions (createYieldVault / depositToYieldVault / completeProcessing), cannot receive any non-supported ERC20 tokens. All tokens transferred to these functions, are claimable by the users, even in the case of failures.
Reviewed the totalAccountedBalance invariant, all ERC20 token flow paths, and the recoverTokens excess-guard logic. No material issues found.
Invariant verification
totalAccountedBalance[token] is incremented/decremented at exactly the right sites:
_validateDeposit (ERC20 escrow in): += amount
_startProcessingInternal (ERC20 out to COA): -= amount
completeProcessing failure (ERC20 re-enters from COA): += amount
_transferFunds (ERC20 out to user via claimRefund): -= amount
cancelRequest / _dropRequestsInternal: no change (funds stay in contract, just re-categorised to claimableRefunds)
recoverTokens: no change (correct - excess was never accounted for)
The invariant totalAccountedBalance[token] == sum(pendingUserBalances) + sum(claimableRefunds) holds across all paths.
receive() removal
Without receive() or fallback(), the only ways native FLOW can enter the contract are the three explicit payable functions (createYieldVault, depositToYieldVault, completeProcessing). Accidental bare-transfers of native FLOW now revert. The COA refund path for native FLOW goes through completeProcessing{value: amount}(...), which remains payable - no regression there.
recoverTokens correctness
The excess guard is correct and cannot be manipulated to drain accounted user funds. The ternary prevents underflow if fee-on-transfer tokens ever caused totalAccountedBalance > contractBalance. nonReentrant covers malicious ERC20 callbacks during safeTransfer.
Minor nits (no, action required)
InvalidRecoveryUserAddress fires for both to == address(0) and to == address(this). Slightly misleading for the self-transfer guard, but the behaviour is correct.
No test exercises WFLOW as the stray token, but MockDAI tests are structurally equivalent. Coverage is adequate.
Overall: accounting is sound, tests are thorough, and the design cleanly prevents both accidental native-FLOW trapping and owner theft of legitimate user funds.
m-Peter
changed the title
fix(FLOW-8): Ensure FlowYieldVaultsRequests accepts no stray tokens or native funds
fix(FLOW-8): Ensure FlowYieldVaultsRequests recovers stray ERC20 tokens
Mar 25, 2026
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.
Closes: #23
Removed the special
receive()Solidity function:to avoid accidental native FLOW token transfers to the contract, as it is not necessary for the contract's operation.
Introduced a new
recoverTokens(to, tokenAddress, amount)Solidity function which allows only the contract's owner, to recover any ERC20 tokens through accidental user transfers.Added some more unit tests, to verify that all 3 payable functions (
createYieldVault/depositToYieldVault/completeProcessing), cannot receive any non-supported ERC20 tokens. All tokens transferred to these functions, are claimable by the users, even in the case of failures.