Closed sherlock-admin3 closed 1 month ago
Escalate
The issue is valid, in scope and the trusted role rule is not applied here because the creator can steal fees stored by OTHER collections.
The attacker can basically wait until there are any ETH in FeeManager
and then create a new edition that will allow them to steal the ETH. It is especially important since this issue affects not only the excessive Ether/tokens sent by the user, but also the holdings and approvals of FeeManager.
Escalate
The issue is valid, in scope and the trusted role rule is not applied here because the creator can steal fees stored by OTHER collections. The attacker can basically wait until there are any ETH in
FeeManager
and then create a new edition that will allow them to steal the ETH. It is especially important since this issue affects not only the excessive Ether/tokens sent by the user, but also the holdings and approvals of FeeManager.
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
@ComposableSecurityTeam to clarify, as I understand the FeeManager isn't intended to hold any ETH and it can only happen if previous minter/publisher sends to much msg.value
and the excess fee is trappen in FeeManager or users send it directly. If there are other ways, could you please share if there are other ways the funds are inside the FeeManager or not, as cause I understand during the mint function or publish function, we call collectMintFee
and collectCreatioFee
, respectively, and non-excess ETH is sent to the fee recepients?
@WangSecurity The excessive amount of Ether sent when minting would be refunded when the other issue is fixed.
However, the existence of receive
function means that there are business flows that require such transfers. That said, the direct transfers would not be only by mistake and could be back-run.
/// @notice Allows the contract to receive ETH.
receive() external payable {}
Thank you for that clarification, but you might have to show and explain these specific business flows which require just sending ETH to FeeManager. Otherwise, the existence of receive
function itself doesn't proof there are such flows. The report doesn't show how there will be excess fees in the contract by excess msg.value
during minting. Hence, this issue is invalid due to user mistake. Planning to reject the escalation and leave the issue as it is.
The receive
function is not default behavior is a specially added function that does not have to appear in contracts unless it is to support some business flow or the contract is to collect funds. So if the risk after further investigation is considered limited then it could be MEDIUM impact on risk finding, but not invalidated one.
Additionally, we draw your attention to the note included in the description, which shows further risks if ERC20 were in the range:
Note: The vulnerability will have an even greater impact on ERC20 tokens, which, although they were excluded from the scope after the start of the contest, the team still plans to support. Then it will be possible not only to steal them, but also the amount approved for FeeManager by the user.
Regardless of the final verdict, we recommend that the team fix the issue in accordance with the described recommendation for user safety.
@WangSecurity Thank you for your support and thorough investigation.
I agree that receive
function is not default, but still if there are no specific business flows in the code, then it doesn't neglect the fact that direct transfers would be a user mistake. I understand that it also has impact for ERC20 tokens, but they're out of scope for this contest. Therefore, my decision remains the same, this is possible only via direct transfer which would be a user mistake, cause specific business flows requiring this behaviour are not seen in the code.
Planning to reject the escalation and leave the issue as it is.
Result: Invalid Unique
ComposableSecurity
high
Unvalidated
mintFee
that leads to stealing fromFeeManager
Summary
The mintFee variable is not validated and allows the edition creator to set over 100% and steal excessively sent Ether and Ether kept on fee manager.
The
mintFee
variable is not validated and allows the edition creator to set high fee and steal excessively sent Ether or Ether kept on fee manager.Vulnerability Detail
The creator of edition can steal funds stored on
FeeManager
by setting highmintFee
(close toFeeManager
's balance) and mint a token without anymsg.value
sent.Even though the EDITION_MANAGER_ROLE is considered trusted, it is only trusted within the scope of their own edition. This trust cannot be applied here, as the funds will be stolen from another contract that kept Ether from different mints. This particular scenario opens a way for attacker to easily steal the Ether sent by the user and the holdings and approvals of
FeeManager
.Note: The vulnerability will have an even greater impact on ERC20 tokens, which, although they were excluded from the scope after the start of the contest, the team still plans to support. Then it will be possible not only to steal them, but also the amount approved for
FeeManager
by the user.Important: The funds on
FeeManager
contract can appear from different sources, including direct call because it hasreceive()
function and thewithdraw()
function that is used by the admin to rescue tokens.The POC scenario shows the following situation:
FeeManager
.msg.value
.FeeManager
covers the cost of attacker's mint and sends him the mint fee.PoC results
Balances of the fee manager and creator before the mint and after the mint:
PoC file
Impact
Theft of the excessive Ether/tokens sent by the user and the holdings and approvals of
FeeManager
.Code Snippet
https://github.com/sherlock-audit/2024-04-titles/blob/d7f60952df22da00b772db5d3a8272a988546089/wallflower-contract-v2/src/fees/FeeManager.sol#L322-L342
Tool used
Manual Review
Recommendation
The fee manager should validate whether the sent
msg.value
is sufficient to cover the fees (that would protect from scenarios 1 and 3).The strategy update should be timelocked (that would protect from scenarios 2).
Consider setting a limit for mint fee.