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
Description: Description
When a user attempts to swap ROSE tokens using the exactInputStableSwap function in the StableSwapRouter contract, there is a issue i.e where ROSE tokens will be trapped in the contract(and may be swapped by another user). This occurs if the pool contract does not accept ROSE or stops accepting ROSE
Attack Scenario
lets understand with example
Attachments
Proof of Concept (PoC) File
Here, let's say a user calls exactInputStableSwap with srcToken set to ROSE.
function exactInputStableSwap(
address[] calldatapath,
uint256[] calldataflag,
uint256amountIn,
uint256amountOutMin,
addressto
) externalpayable nonReentrant returns (uint256amountOut) {
require(!isKill, "Contract is killed");
address srcToken= path[0];
address dstToken = path[path.length-1];
// use amountIn == Constants.CONTRACT_BALANCE as a flag to swap the entire balance of the contractbool hasAlreadyPaid;
if (amountIn == Constants.CONTRACT_BALANCE) {
hasAlreadyPaid =true;
if(srcToken==ROSE){
amountIn =address(this).balance;
}else{
amountIn =IERC20(srcToken).balanceOf(address(this));
}
}
if (!hasAlreadyPaid) {
if(srcToken==ROSE){
require(msg.value>=amountIn, "Invalid msg.value");
}else{
pay(srcToken, msg.sender, address(this), amountIn);
}
}
_swap(path, flag);
Now, this function calls the _swap() function internally
,and in the swap function, as we can see, it calls the exchange function at i.e., IStableSwap(swapContract).exchange{value: amountIn}(k, j, amountIn_, 0);.
function exchange(
uint256i,
uint256j,
uint256dx,
uint256min_dy
) externalpayable nonReentrant {
require(!is_killed, "Killed");
if (!support_ROSE) {
require(msg.value==0, "Inconsistent quantity"); // Avoid sending ROSE by mistake.
}
Now, the exchange() function will be invoked here. This function checks i.e., if the pool contract does not accept ROSE or it stops accepting ROSE, then the function will revert. The user's ROSE tokens will be trapped in the StableSwapRouter contract as the call to exchange function is reverted.
steps to reproduce
The user sends a certain amount of ROSE to the StableSwapRouter contract(as contract has logic for this). This increases the contract's balance of ROSE.
The user calls the exactInputStableSwap function with srcToken set to ROSE and amountIn set to Constants.CONTRACT_BALANCE.
This indicates that the user wants to swap the entire balance of ROSE held by the contract.
The function proceeds to call the _swap() function, passing the path and flags for the swap.
Within _swap(), the exchange function is called on the swapContract with the current balance of ROSE as msg.value.
The exchange function checks if the pool supports ROSE using the support_ROSE flag
If support_ROSE is false, the function reverts with "Inconsistent quantity".
If the exchange function reverts, the entire transaction is rolled back. However, since the ROSE was already in the contract, it remains there.
The ROSE tokens remain in the StableSwapRouter contract because the transaction was reverted after the function call and anyone call swap them.
Revised Code File (Optional)
Implement a check before initiating the swap to verify if the pool supports ROSE. If not, revert the transaction early to prevent the trap of ROSE.
The text was updated successfully, but these errors were encountered:
There are many other issues submitted that start with scenarios where users send tokens directly to the router and then lose their tokens. This comment explains why this is not an issue: #22 (comment)
Github username: --
Twitter username: --
Submission hash (on-chain): 0x7c479257717652a3d2d199486505fede4caca754c6f8189f35e689f897585adb
Severity: medium
Description:
Description
When a user attempts to swap
ROSE
tokens using theexactInputStableSwap
function in theStableSwapRouter
contract, there is a issue i.e whereROSE
tokens will be trapped in the contract(and may be swapped by another user). This occurs if thepool contract
does not acceptROSE
or stops acceptingROSE
Attack Scenario
lets understand with example
Attachments
Here, let's say a user calls
exactInputStableSwap
withsrcToken
set toROSE
.Now, this function calls the
_swap()
function internally,and in the swap function, as we can see, it calls the exchange function at i.e., IStableSwap(swapContract).exchange{value: amountIn}(k, j, amountIn_, 0);.
Now, the
exchange()
function will be invoked here. This function checks i.e., if the pool contract does not acceptROSE
or it stops acceptingROSE
, then the function will revert. The user's ROSE tokens will be trapped in theStableSwapRouter
contract as the call to exchange function is reverted.steps to reproduce
ROSE
to theStableSwapRouter
contract(as contract has logic for this). This increases the contract's balance of ROSE.exactInputStableSwap
function withsrcToken
set toROSE
andamountIn
set toConstants.CONTRACT_BALANCE
._swap()
, the exchange function is called on the swapContract with the current balance of ROSE as msg.value.ROSE
using thesupport_ROSE
flagROSE
.The text was updated successfully, but these errors were encountered: