collector dependency , easy compromise hack
Description
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:
Proof of Concept
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 {
}
}