While this doesn't cause direct loss of funds, it has several negative consequences:
pragma solidity ^0.8.26;
import "forge-std/Test.sol";
import "forge-std/console.sol";
import {ReFiSwapRebateHook} from "../../src/RebateFiHook.sol";
import {Deployers} from "@uniswap/v4-core/test/utils/Deployers.sol";
import {MockERC20} from "solmate/src/test/utils/mocks/MockERC20.sol";
import {IPoolManager} from "v4-core/interfaces/IPoolManager.sol";
import {Hooks} from "v4-core/libraries/Hooks.sol";
import {HookMiner} from "v4-periphery/src/utils/HookMiner.sol";
contract Vulnerability04_WrongEventParams_PoC is Test, Deployers {
MockERC20 reFiToken;
MockERC20 otherToken;
ReFiSwapRebateHook public rebateHook;
event TokensWithdrawn(address indexed token, address indexed to, uint256 amount);
function setUp() public {
deployFreshManagerAndRouters();
reFiToken = new MockERC20("ReFi Token", "ReFi", 18);
otherToken = new MockERC20("Other Token", "OTHER", 18);
bytes memory creationCode = type(ReFiSwapRebateHook).creationCode;
bytes memory constructorArgs = abi.encode(manager, address(reFiToken));
uint160 flags = uint160(
Hooks.BEFORE_INITIALIZE_FLAG |
Hooks.AFTER_INITIALIZE_FLAG |
Hooks.BEFORE_SWAP_FLAG
);
(address hookAddress, bytes32 salt) = HookMiner.find(
address(this),
flags,
creationCode,
constructorArgs
);
rebateHook = new ReFiSwapRebateHook{salt: salt}(manager, address(reFiToken));
require(address(rebateHook) == hookAddress, "Hook address mismatch");
}
* @notice This test demonstrates the event parameter order is wrong
*/
function test_EventParametersAreSwapped() public {
uint256 withdrawAmount = 100 ether;
otherToken.mint(address(rebateHook), withdrawAmount);
address tokenAddress = address(otherToken);
address recipientAddress = address(0xBEEF);
console.log("\n=== Withdrawal Details ===");
console.log("Token being withdrawn:", tokenAddress);
console.log("Recipient address:", recipientAddress);
console.log("Amount:", withdrawAmount);
vm.expectEmit(true, true, false, true);
emit TokensWithdrawn(recipientAddress, tokenAddress, withdrawAmount);
rebateHook.withdrawTokens(tokenAddress, recipientAddress, withdrawAmount);
console.log("\n=== Event Analysis ===");
console.log("Event 'token' field contains:", recipientAddress);
console.log("Event 'to' field contains:", tokenAddress);
console.log("\nIMPACT: Event parameters are inverted!");
console.log("Off-chain systems will record wrong data!");
}
* @notice Show what the CORRECT event would look like
*/
function test_ShowCorrectEventExpectation() public {
uint256 withdrawAmount = 50 ether;
otherToken.mint(address(rebateHook), withdrawAmount);
address tokenAddress = address(otherToken);
address recipientAddress = address(0xDEAD);
vm.expectEmit(true, true, false, true);
emit TokensWithdrawn(recipientAddress, tokenAddress, withdrawAmount);
rebateHook.withdrawTokens(tokenAddress, recipientAddress, withdrawAmount);
console.log("\n=== Correct vs Actual ===");
console.log("SHOULD emit: TokensWithdrawn(token=%s, to=%s, amount)", tokenAddress, recipientAddress);
console.log("ACTUALLY emits: TokensWithdrawn(token=%s, to=%s, amount)", recipientAddress, tokenAddress);
}
}
forge test --via-ir -vv --match-path test/audit/Vulnerability04_WrongEventParams_PoC.t.sol
Ran 2 tests for test/audit/Vulnerability04_WrongEventParams_PoC.t.sol:Vulnerability04_WrongEventParams_PoC
[PASS] test_EventParametersAreSwapped() (gas: 98290)
Logs:
=== Withdrawal Details ===
Token being withdrawn: 0x212224D2F2d262cd093eE13240ca4873fcCBbA3C
Recipient address: 0x000000000000000000000000000000000000bEEF
Amount: 100000000000000000000
=== Event Analysis ===
Event 'token' field contains: 0x000000000000000000000000000000000000bEEF
Event 'to' field contains: 0x212224D2F2d262cd093eE13240ca4873fcCBbA3C
IMPACT: Event parameters are inverted!
Off-chain systems will record wrong data!
[PASS] test_ShowCorrectEventExpectation() (gas: 90555)
Logs:
=== Correct vs Actual ===
SHOULD emit: TokensWithdrawn(token=0x212224D2F2d262cd093eE13240ca4873fcCBbA3C, to=0x000000000000000000000000000000000000dEaD, amount)
ACTUALLY emits: TokensWithdrawn(token=0x000000000000000000000000000000000000dEaD, to=0x212224D2F2d262cd093eE13240ca4873fcCBbA3C, amount)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.82s (9.43ms CPU time)
The test demonstrates that the event emission has swapped parameters.
This ensures the emitted event matches its definition, with parameters in the correct order: (token, to, amount).