Platform: Code4rena
Start Date: 03/05/2022
Pot Size: $30,000 USDC
Total HM: 6
Participants: 93
Period: 3 days
Judge: gzeon
Id: 118
League: ETH
Rank: 40/93
Findings: 3
Award: $94.32
🌟 Selected for report: 0
🚀 Solo Findings: 0
48.5872 USDC - $48.59
https://github.com/code-423n4/2022-05-runes/blob/main/contracts/ForgottenRunesWarriorsMinter.sol#L608-L619 https://github.com/code-423n4/2022-05-runes/blob/main/contracts/ForgottenRunesWarriorsGuild.sol#L164
To withdraw ETH, it uses send()
, this transaction will fail inevitably when:
/** * @notice Withdraw funds to the vault * @param _amount uint256 the amount to withdraw */ function withdraw(uint256 _amount) public onlyOwner { require(address(vault) != address(0), 'no vault'); require(payable(vault).send(_amount)); } /** * @notice Withdraw all funds to the vault */ function withdrawAll() public payable onlyOwner { require(address(vault) != address(0), 'no vault'); require(payable(vault).send(address(this).balance)); }
So if vault
has one of above conditions. sending funds will fail. because vault address can be updated, I don't send this as High issue.
/** * @notice Withdraw funds to the vault * @param _amount uint256 the amount to withdraw */ function withdraw(uint256 _amount) public onlyOwner { require(address(vault) != address(0), 'no vault'); (bool success, ) = vault.call{value: _amount}(""); require(success); } /** * @notice Withdraw all funds to the vault */ function withdrawAll() public payable onlyOwner { require(address(vault) != address(0), 'no vault'); (bool success, ) = vault.call{value: address(this).balance}(""); require(success); }
And here same problem:
ForgottenRunesWarriorsGuild.sol 164,9: require(payable(msg.sender).send(address(this).balance));
If owner
has one of above conditions, too. owner can't withdraw wrongly sent eths.
ForgottenRunesWarriorsGuild.sol:
function withdrawAll() public payable onlyOwner { (bool success, ) = msg.sender.call{value: address(this).balance}(""); require(success); }
#0 - wagmiwiz
2022-05-05T10:05:28Z
#1 - KenzoAgada
2022-06-06T12:49:20Z
Duplicate of #254
#2 - gzeoneth
2022-06-18T17:23:40Z
This is true but also these are onlyOwner
function where the owner have full control of the destination address to mitigate any issue in production. Downgrading to Low / QA.
🌟 Selected for report: defsec
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0x52, 0xDjango, 0xf15ers, 0xkatana, 0xliumin, AuditsAreUS, BowTiedWardens, CertoraInc, Cr4ckM3, Funen, GimelSec, Hawkeye, IllIllI, Kulk0, M0ndoHEHE, MaratCerby, Picodes, Ruhum, TerrierLover, TrungOre, VAD37, WatchPug, berndartmueller, broccolirob, catchup, cccz, cryptphi, csanuragjain, delfin454000, dirk_y, eccentricexit, ellahi, fatherOfBlocks, gzeon, hake, hansfriese, hickuphh3, horsefacts, hubble, hyh, ilan, joestakey, kebabsec, kenta, kenzo, leastwood, m9800, marximimus, minhquanym, oyc_109, p4st13r4, pauliax, pedroais, peritoflores, plotchy, rajatbeladiya, reassor, rfa, robee, rotcivegaf, samruna, shenwilly, shung, simon135, sorrynotsorry, sseefried, teddav, throttle, tintin, unforgiven, z3s
30.2807 USDC - $30.28
payable
from withdrawAll()
:withdrawAll()
do not use msg.value
and just withdraw eth so it doesn't need to be payable
.
- function withdrawAll() public payable onlyOwner { + function withdrawAll() public onlyOwner { ForgottenRunesWarriorsMinter.sol:616 - function withdrawAll() public payable onlyOwner { + function withdrawAll() public onlyOwner {
.transfer()
return's value:It is good to add a require()
statement that checks the return value of token transfers or to use something like OpenZeppelin’s safeTransfer
unless one is sure the given token reverts in case of a failure. Failure to do so will cause silent failures.
ForgottenRunesWarriorsGuild.sol 175,9: token.transfer(msg.sender, amount); ForgottenRunesWarriorsMinter.sol 629,9: token.transfer(msg.sender, amount); ForgottenRunesWarriorsMinter.sol 402,13: IERC20(weth).transfer(to, amount);
Consider using safeTransfer or check transfer's return with require().
type(uint256).max
is more readable than hex version of the number:ForgottenRunesWarriorsMinter.sol 18,9: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; 23,9: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; 27,9: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; 31,9: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; 35,9: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
Use type(uint256).max
instead of 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
.
#0 - cryppadotta
2022-05-05T02:22:40Z
[N01] you're right. I don't know why these are payable. Thanks
🌟 Selected for report: BowTiedWardens
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xProf, 0xc0ffEE, 0xf15ers, 0xkatana, 0xliumin, ACai, AlleyCat, CertoraInc, Cityscape, Cr4ckM3, DavidGialdi, Dinddle, FSchmoede, Funen, GimelSec, Hawkeye, IllIllI, Kulk0, M0ndoHEHE, MaratCerby, MiloTruck, Picodes, RoiEvenHaim, Tadashi, TerrierLover, TrungOre, VAD37, WatchPug, antonttc, catchup, defsec, delfin454000, dirk_y, eccentricexit, ellahi, fatherOfBlocks, gzeon, hake, hansfriese, hickuphh3, horsefacts, ilan, joestakey, kebabsec, kenta, kenzo, marximimus, minhquanym, noobie, oyc_109, p4st13r4, pauliax, rajatbeladiya, reassor, rfa, robee, rotcivegaf, saian, samruna, shenwilly, shung, simon135, slywaters, sorrynotsorry, throttle, unforgiven, z3s
15.4498 USDC - $15.45
Custom errors from Solidity 0.8.4 are cheaper than require
messages.
https://blog.soliditylang.org/2021/04/21/custom-errors/