Category: Coding Mistakes
Balance-offset check uses requested amount
Informational Severity
Informational Impact
N/A Likelihood
Description
When depositWithERC20
is called to deposit an ERC-20 token,
function depositWithERC20(address _token, uint256 _amount, address _referral) public whenNotPaused nonReentrant returns (uint256) {
require(isTokenWhitelisted(_token), "token is not whitelisted"); crossover
uint256 balance = tokenAmountToEthAmount(_token, IERC20(_token).balanceOf(address(this)));
bool sent = IERC20(_token).transferFrom(msg.sender, address(this), _amount);
require(sent, "erc20 transfer failed");
uint256 newBalance = tokenAmountToEthAmount(_token, IERC20(_token).balanceOf(address(this)));
uint256 dx = newBalance - balance;
require(!isDepositCapReached(dx), "Deposit cap reached");
require(_amount > BALANCE_OFFSET, "amount is too small");
dx -= BALANCE_OFFSET;
the variable dx
properly captures the amount of value actually received by the contract, because the ERC-20 might have a fee on send. However, the check against BALANCE_OFFSET
is made against _amount
rather than dx
. This means that the next subtraction may underflow and revert.
Impact
There is currently no impact because BALANCE_OFFSET
is zero.
Recommendations
Replace the _amount
with dx
or remove BALANCE_OFFSET
if it is unused.
Additionally, for the transfer, we recommend using a wrapper such as SafeERC20 so that noncompliant ERC-20 tokens that do not return a boolean, such as USDT, can still work.
Remediation
This issue has been acknowledged by Gadze Finance SEZC, and a fix was implemented in commit 614b59d1↗.