Platform: Code4rena
Start Date: 07/07/2022
Pot Size: $75,000 USDC
Total HM: 32
Participants: 141
Period: 7 days
Judge: HardlyDifficult
Total Solo HM: 4
Id: 144
League: ETH
Rank: 107/141
Findings: 1
Award: $61.94
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: xiaoming90
Also found by: 0x1f8b, 0x29A, 0x52, 0xA5DF, 0xDjango, 0xNazgul, 0xNineDec, 0xf15ers, 0xsanson, 0xsolstars, 242, 8olidity, Amithuddar, Aymen0909, Bnke0x0, BowTiedWardens, David_, Deivitto, ElKu, Funen, Hawkeye, IllIllI, JC, Kaiziron, Keen_Sheen, Kthere, Kulk0, Kumpa, Lambda, MEP, ReyAdmirado, Rohan16, Ruhum, Sm4rty, TomJ, Tomio, Treasure-Seeker, TrungOre, Tutturu, Viksaa39, Waze, _Adam, __141345__, ak1, apostle0x01, asutorufos, async, ayeslick, aysha, bbrho, benbaessler, berndartmueller, c3phas, cccz, chatch, cloudjunky, codexploder, cryptphi, delfin454000, dipp, durianSausage, dy, exd0tpy, fatherOfBlocks, hake, hansfriese, horsefacts, hubble, joestakey, jonatascm, kebabsec, kenzo, kyteg, mektigboy, neumo, oyc_109, pashov, pedr02b2, peritoflores, rajatbeladiya, rbserver, robee, rokinot, s3cunda, sach1r0, sahar, sashik_eth, scaraven, shenwilly, simon135, sorrynotsorry, sseefried, svskaushik, unforgiven, z3s, zzzitron
61.9379 USDC - $61.94
https://github.com/code-423n4/2022-07-fractional/blob/main/src/modules/protoforms/BaseVault.sol#L65
L65 in BaseVault.sol transfers ERC20 tokens using .transferFrom()
and doesn’t verify that the transfer is successful. Some tokens like ZRX don’t revert on failure but rather return false
. If the BaseVault.sol is used to create a vault the attacker can specify ERC20 tokens they don’t own as collateral.
batchDepositERC20()
attempts to transfer the tokens and the ERC20 contract (e.g. ZRX) returns false and this is not checked. The vault is created as if the ERC20 tokens were transferred.Vim
ERC20 tokens should be transferred using the SafeERC20 library from OpenZeppelin which includes the .safeTransferFrom()
function. This would ensure that the ERC token transfer reverts in conditions where the attacker doesn’t possess the ERC20 tokens (i.e. when the ERC20 contract returns false
).
To achieve this you could delete the line importing IERC20;
import {IERC20} from "../../interfaces/IERC20.sol";
And then import SafeERC20 from the OpenZeppelin contracts and use it for IERC20’s;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; using SafeERC20 for IERC20;
Lastly change .transferFrom()
to .safeTransferFrom()
;
IERC20(_tokens[i]).safeTransferFrom(_from, _to, _amounts[i]);
Then you can run all tests with forge test
and they pass.
#0 - stevennevins
2022-07-18T15:35:54Z
0 (Non-critical)
Fails silently (if the user transfers tokens they don't own), no users would see this as a balance in the Vault to consider the tokens as a part of the Vault, and no event is emitted indicating that these tokens are in the Vault.
We will be updating to safeTransferFrom because it's an excellent practice to revert on this failure to transfer tokens
#1 - HardlyDifficult
2022-07-26T17:38:17Z
Agree with the sponsor that this is a non-critical best practice. Transfers may fail but no events are emitted, balance doesn't change, and no other negative consequences were identified.
Lowing risk and making this a QA report for the warden.