Some residual recipients would now have their residues stuck in SwapAction
after swap
#69
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
🤖_primary
AI based primary recommendation
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2024-10-loopfi/blob/d219f0132005b00a68f505edc22b34f9a8b49766/src/proxy/SwapAction.sol#L36-L50
https://github.com/code-423n4/2024-10-loopfi/blob/d219f0132005b00a68f505edc22b34f9a8b49766/src/proxy/SwapAction.sol#L113-L158
Vulnerability details
Proof of Concept
In the current scope a new addition has been made to the swapParams: https://github.com/code-423n4/2024-10-loopfi/blob/d219f0132005b00a68f505edc22b34f9a8b49766/src/proxy/SwapAction.sol#L36-L50
struct SwapParams { SwapProtocol swapProtocol; SwapType swapType; address assetIn; uint256 amount; // Exact amount in or exact amount out depending on swapType uint256 limit; // Min amount out or max amount in depending on swapType address recipient; + address residualRecipient; // Address to send any residual tokens to uint256 deadline; /// @dev `args` can be used for protocol specific parameters /// For Balancer, it is the `poolIds` and `assetPath` /// For Uniswap v3, it is the `path` for the swap bytes args; }
As hinted the
residualRecipient
is the address to send any residual tokens to after a swap, also from the above we can see that the logic allows forrecipient
to not be the same asresidualRecipient
, which is why regardless of what happens in as much asresidualRecipient
is set we should transfer the residues post swap to it.In the previous scope when we didn't have any param as residual recipient this is how transfers of residual tokens are executed https://github.com/code-423n4/2024-07-loopfi/blob/57871f64bdea450c1f04c9a53dc1a78223719164/src/proxy/SwapAction.sol#L107C1-L144C1:
That is a check is made that if the
SwapAction.sol
is not the recipient and the swapType isEXACT_OUT
then we should transfer the remaining tokens to the real recipient, however ifaddress(this)
is the real recipient then there is no need for us to make a transfer fromaddress(this)
->address(this)
for a token.Now in the current scope here is how it's implemented https://github.com/code-423n4/2024-10-loopfi/blob/d219f0132005b00a68f505edc22b34f9a8b49766/src/proxy/SwapAction.sol#L113-L158
The check above is wrong however, considering there is a valid case where even if the
residualRecipient
is set the remaining tokens from the swap are stuck in the contract.POC:
residualRecipient
, which a user has set to themselvesSwapType.EXACT_OUT
swapParams.recipient
asaddress(this)
msg.sender
since they've set themselves as theresidualRecipient
, however this doesn't happen, and instead the tokens would be stuck in the contract due to this check.Impact
User tokens would be stuck since its not being sent to the
residualRecipient
, and in this case since it's stuck in the contract the user can't query to withdraw the tokens.Also this new approach seem to have been deployed to sort out this issue from the previous scope, where after conducting
leverParams.auxSwap
some tokens may be leftover, so they should be sent to the residual recipient, however this is not being correctly done as shown above.Recommended Mitigation Steps
Apply these changes:
https://github.com/code-423n4/2024-10-loopfi/blob/d219f0132005b00a68f505edc22b34f9a8b49766/src/proxy/SwapAction.sol#L149-L157
The above ensures regardless of who the recipient is the, the remaining tokens are always transferred to the
residualRecipient
.Also note that per the documentation and readMe, the action contracts are meant to be contracts via which users can bundle transactions, see https://github.com/code-423n4/2024-10-loopfi/blob/d219f0132005b00a68f505edc22b34f9a8b49766/README.md#L80-L88
Which in our case would then mean that with the normal flow users should be allowed to bundle one tx with another, in regards to swapAction, if a user was attempting to transfer out their received residual amount post swap, this would fail in the case shown in this report.
Assessed type
Token-Transfer
The text was updated successfully, but these errors were encountered: