When claiming owner incentives in the Dispenser contract, if amountETHFromServices< accountRewards, the user's reward balance will get updated, but he won't receive the reward
Proof of Concept
Dispenser#claimOwnerIncentives can be used to claim incentives for the owner of components/agents:
function withdrawToAccount(
address account,
uint256 accountRewards,
uint256 accountTopUps
) external returns (bool success) {
...
if (accountRewards > 0 && amountETHFromServices >= accountRewards) {
amountETHFromServices -= accountRewards;
ETHFromServices = uint96(amountETHFromServices);
emit Withdraw(ETH_TOKEN_ADDRESS, account, accountRewards);
(success, ) = account.call{value: accountRewards}("");
if (!success) {
revert TransferFailed(
address(0),
address(this),
account,
accountRewards
);
}
}
if (accountTopUps > 0) {
// Tokenomics has already accounted for the account's top-up amount,
// thus the the mint does not break the inflation schedule
IOLAS(olas).mint(account, accountTopUps);
success = true;
emit Withdraw(olas, account, accountTopUps);
}
}
We can see that only if accountRewards>0 && amountETHFromServices>=accountRewards, the if block gets executed.
If amountETHFromServices < accountRewards, the if block, which contains logic for sending the rewards won't be executed.
Still looking at the withdrawAccount function, if the topup>0, olas gets minted, and the success return parameter gets set to true.
claimOwnerIncentives would revert if !success. But in our case, it won't revert cos success is true.
This is a problem because in claimOwnerIncentives function, the rewards balance of the user has aleady been updated when calling Tokenomics#accountOwnerIncentives just before withdrawToAccount got called.
This means that the user will receive no rewards, while his reward balance gets updated.
Lines of code
https://github.com/code-423n4/2024-05-olas/blob/main/tokenomics/contracts/Dispenser.sol#L809-L832 https://github.com/code-423n4/2024-05-olas/blob/main/tokenomics/contracts/Treasury.sol#L402-L419
Vulnerability details
Impact
When claiming owner incentives in the Dispenser contract, if amountETHFromServices< accountRewards, the user's reward balance will get updated, but he won't receive the reward
Proof of Concept
Dispenser#claimOwnerIncentives can be used to claim incentives for the owner of components/agents:
Here is Treasury#withdrawToAccount:
We can see that only if accountRewards>0 && amountETHFromServices>=accountRewards, the if block gets executed. If amountETHFromServices < accountRewards, the if block, which contains logic for sending the rewards won't be executed.
Still looking at the withdrawAccount function, if the topup>0, olas gets minted, and the
success
return parameter gets set to true.claimOwnerIncentives would revert if !success. But in our case, it won't revert cos success is true.
This is a problem because in claimOwnerIncentives function, the rewards balance of the user has aleady been updated when calling Tokenomics#accountOwnerIncentives just before withdrawToAccount got called.
This means that the user will receive no rewards, while his reward balance gets updated.
Tools Used
Manual Review
Recommended Mitigation Steps
if amountETHFromServices< accountRewards, revert
Assessed type
Error