Native tokens are not transferred to the exchange contracts
Description
The vault contracts serve as a management layer for user permissions and staking operations. A user is able to stake tokens or ETH directly. For the first case of token staking, the stakeToken
function is called, transferring the tokens to the exchange contracts — here, for example, in the contract BfxVaultU:
function stakeToken(uint256 amount, address token) public {
require(supportedTokens[token], "UNSUPPORTED_TOKEN");
require(amount >= minStakes[token], "AMOUNT_TOO_SMALL");
string memory stakeId = allocateStakeId();
emit Stake(stakeId, msg.sender, amount, token);
uint256 prevBalance = IERC20(token).balanceOf(bfx);
require(
makeTransferFrom(msg.sender, bfx, amount, token),
"TRANSFER_FAILED"
);
uint256 newBalance = IERC20(token).balanceOf(bfx);
require(newBalance == amount + prevBalance, "NOT_ENOUGH_TRANSFERRED");
}
However, during a stake of ETH to the vault contract, the handleReceivedNative
function is called:
function handleReceivedNative() internal {
address native = address(0);
require(supportedTokens[native], "UNSUPPORTED_TOKEN");
uint256 minDeposit = minDeposits[native];
require(msg.value >= minDeposit, "AMOUNT_TOO_SMALL");
string memory depositId = allocateDepositId();
emit Deposit(depositId, msg.sender, msg.value, native);
}
The ETH amount is received but not transferred to the exchange contracts. It stays in the vault contracts.
Impact
The user funds will not be transferred to the exchange contracts, and thus staking would not happen. The user funds will be locked in the vault contracts until withdrawn by the owner.
Recommendations
We recommend transferring the user ETH to the exchange contracts.
Remediation
This issue has been acknowledged by RabbitX, and a fix was implemented in commit a7fa5c60↗.