Open hats-bug-reporter[bot] opened 5 months ago
When the transfer fails and reverts, the entire transaction for minting will revert due to the way the call chain works.
let's check again the transferFrom()
function in the CVX
contract.
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
we can see that when _transfer()
fails the transferFrom()
returns false
so doesn't revert. in this case the mint()
function in CVX1
contract should handles return value of transferFrom()
function.
Checking the return value is a requirement, as written in the EIP-20 specification:
Callers MUST handle false from returns (bool success). Callers MUST NOT assume that false is never returned!
the severity of this issue should be medium because if it happens, the caller gains profit and other depositors lose funds.
consider this scenario:
mint()
function and deposits 100 CVX
token and get 100 CVX1
tokenmint()
function and transferFrom()
got fails and Alice gets 100 CVX1
because returned value not handled.withdraw()
function and get 100 CVX
token for free.CVX
tokens were withdrawn by Alice.transferFrom
internally calls _transfer
which has 4 conditions to fail (technically they are 3):
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance")
will revert with the message "ERC20: transfer amount exceeds balance". The same revert would happen to the allowance.The call chain is mint
-> transferFrom
-> _transfer
-> revert if low balance, and the entire call chain would revert so no tokens get minted.
Provide a PoC if I am missing something.
sorry for the late response
I couldn't find technically any condition where transferFrom()
returns a false
value but as I mentioned above as written in the EIP-20 specification, the caller must not assume the false
value never returned. I think the possibility of this issue is rare but still can lead to loss of funds so severity can be low.
need to consider that might I miss something, if it's impossible for transferFrom()
to return a false
value why would return a true
value at the end of the function?
Github username: -- Twitter username: -- Submission hash (on-chain): 0xd8585463c47cc8b6b94a9465e85a5acbeb9b16e7dd1e0ae095beebf8fcaba578 Severity: medium
Description:
Description
we can see that the
mint()
function transfersCVX
tokens from the user to theCVX1
contract and then mintsCVX1
but the issue is this function doesn't check the return value of the transfer, so if the transfer fails user able to mintCVX1
which is exchangeable withCVX
token.this scenario also can happen for
withdraw()
function. user will lose funds iftransfer()
fails inCVX
because userCVX1
tokens will burn.Impact
loss of funds for users who deposited
CVX
.PoC
this is the mint function in
CVX1
and this is the transfer function in
CVX
contractwe can see that the
transfer()
function in theCVX
contract just returnsbool
value so themint()
function should revert when transfer fails.Reccomendation
checks return value of transfer with
bool
or use OP safeTransfer.