Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: medium
Likelihood: high
Invalid

dependency of collector.

collector dependency , easy compromise hack

Description

  • in ideal case collect fee must be decentralized with EIP712 signatures from 1-3 addresses OR split fee on 3-4 address

  • potencial key compromise easy hack

modifier onlyCollector() {
@> if (msg.sender != s_collector) {
revert S__NotAllowed();
}
_;
}
@> function collectFee() external onlyCollector {
uint256 collection = i_weth.balanceOf(address(this));
i_weth.transfer(s_collector, collection);
(bool collected,) = payable(s_collector).call{value: address(this).balance}("");
require(collected, "Fee collection failed!!!");
}

Risk

Likelihood:

  • key compromise

  • social engenering

Impact:

  • los all fee.

Proof of Concept

// SPDX-License-Identifier: MIT
pragma solidity 0.8.29;
import {Test} from "forge-std/Test.sol";
import {Snow} from "../src/Snow.sol";
import {MockWETH} from "../src/mock/MockWETH.sol";
contract TestSnowPoC is Test {
Snow private _snow ;
MockWETH private _weth ;
address private colect = makeAddr("vanya") ;
function setUp() public {
_weth = new MockWETH() ;
_snow = new Snow(address(_weth) , 1 , colect);
}
function testETHbuySnow() public {
_snow.buySnow{value: 1 ether}(1);
assertEq(_snow.balanceOf(address(this)) , 1);
}
function testCompromisedColector() public {
testETHbuySnow();
assertEq(address(_snow).balance, 1 ether);
vm.prank(colect);
_snow.collectFee() ;
assertEq(address(colect).balance , 1 ether);
}
}

Recommended Mitigation

- function collectFee() external onlyCollector {
uint256 collection = i_weth.balanceOf(address(this));
i_weth.transfer(s_collector, collection);
(bool collected,) = payable(s_collector).call{value: address(this).balance}("");
require(collected, "Fee collection failed!!!");
}
+ address[] private feesCollector ;
constructor(address[] memory collectors) {
for(uint256 i = 0 ; i <= collectors.length ; i++) {
require(collectors[i] != address(0) , "zeroAddressCollector");
feesCollector.push(collectors[i]);
}
}
function collectFee() internal {
uint256 tosendETH = address(this).balance / feesCollector.length ;
uint256 tosendWETH = _weth.balanceOf(address(this)) / feesCollector.length ;
for(uint256 i = 0 ; i <= feesCollector.length ; i++) {
feesCollector[i].call{value: tosendETH}("");
try _weth.transfer(feesCollector[i] , tosendWETH) {
} catch {
}
}
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 2 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!