Forgotten Runes Warrior Guild contest - teddav's results

16,000 Warrior NFTs sold in a phased Dutch Auction.

General Information

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

Forgotten Runes

Findings Distribution

Researcher Performance

Rank: 14/93

Findings: 2

Award: $891.81

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: gzeon

Also found by: AuditsAreUS, BowTiedWardens, Ruhum, pedroais, shenwilly, teddav

Labels

bug
duplicate
2 (Med Risk)
sponsor acknowledged

Awards

861.5328 USDC - $861.53

External Links

Lines of code

https://github.com/code-423n4/2022-05-runes/blob/main/contracts/ForgottenRunesWarriorsMinter.sol#L616 https://github.com/code-423n4/2022-05-runes/blob/main/contracts/ForgottenRunesWarriorsMinter.sol#L627 https://github.com/code-423n4/2022-05-runes/blob/main/contracts/ForgottenRunesWarriorsMinter.sol#L527

Vulnerability details

Impact

The team (owner of the contract) can rugpull at any time by withdrawing all the funds in the contract. There is no limit to how much can be withdrawn. And the users won't be able to get their refunds.

Proof of Concept

The function setVaultAddress allows the owner of the contract to set the vault to any address. The function withdrawAll allows the owner/the team to withdraw all ETH on the contract. The function forwardERC20s allows the owner/the team to withdraw any ERC20 on the contract.

Tools Used

Manual analysis

Only allow the withdraw functions / forwardERC20s to be called after the refund process is done

#0 - cryppadotta

2022-05-06T15:22:54Z

acknowledged, but this is in the readme

#1 - gzeoneth

2022-06-18T17:20:39Z

Lines of code

https://github.com/code-423n4/2022-05-runes/blob/main/contracts/ForgottenRunesWarriorsMinter.sol#L400

Vulnerability details

Impact

Refunds could end up being stuck for all users.

Proof of Concept

First issue: The function _safeTransferETHWithFallback has a first fallback if to send WETH if the ETH transfer fails. But the WETH transfer can fail (silently) too. You need to check the return value of WETH.transfer and revert if it is false. You can see the code of WETH here: https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code

Second issue: If the user you are trying to refund uses a smart contract, the WETH might end up being lost. If the smart contract doesnt accept ETH, then the call will fallback to WETH. But if the contract doesnt have a method to transfer out the WETH, then the WETH will be lost. Which is terrible for the user.

Tools Used

Manual analysis

Rewrite the _safeTransferETHWithFallback function.

function _safeTransferETHWithFallback(address to, uint256 amount) internal { if (!_safeTransferETH(to, amount)) { IWETH(weth).deposit{value: amount}(); require(IERC20(weth).transfer(to, amount), "failed WETH transfer"); } }

For the second issue. I would recommend maybe having 2 different refund functions. One as ETH, and the other one as WETH

#0 - KenzoAgada

2022-06-06T05:57:08Z

First issue is duplicate of #250 and invalid as WETH can not fail silently. Second issue - I might comment later. I think there's a dup of it somewhere.

#1 - gzeoneth

2022-06-18T20:01:11Z

As warden's QA report.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter