Summary
If burnTaxRate != 0, the corresponding RAACToken are burned during the balance change regardless of the operation.
Vunerability Details
The RAACToken::_update function is defined as below :
File: https:
function _update(
address from,
address to,
uint256 amount
) internal virtual override {
uint256 baseTax = swapTaxRate + burnTaxRate;
if (baseTax == 0 || from == address(0) || to == address(0) || whitelistAddress[from] || whitelistAddress[to] || feeCollector == address(0)) {
super._update(from, to, amount);
return;
}
uint256 totalTax = amount.percentMul(baseTax);
uint256 burnAmount = totalTax * burnTaxRate / baseTax;
super._update(from, feeCollector, totalTax - burnAmount);
super._update(from, address(0), burnAmount);
super._update(from, to, amount - totalTax);
}
As one can see, part of the amount being moved is transferred to address(0) meaning it is burned instead of being transferred to the protocol or even to the receiver.
Impact
As a result, the address from which the funds are transferred loses part of it tokens since there not sent to address(0);
Tools Used
Manual review.
Recommendations
Also send burnAmount to feeCollector.
function _update(
address from,
address to,
uint256 amount
) internal virtual override {
uint256 baseTax = swapTaxRate + burnTaxRate;
// Skip tax for whitelisted addresses or when fee collector disabled
if (baseTax == 0 || from == address(0) || to == address(0) || whitelistAddress[from] || whitelistAddress[to] || feeCollector == address(0)) {
super._update(from, to, amount);
return;
}
// All other cases where tax is applied
uint256 totalTax = amount.percentMul(baseTax);
- uint256 burnAmount = totalTax * burnTaxRate / baseTax;
- super._update(from, feeCollector, totalTax - burnAmount);
+ super._update(from, feeCollector, totalTax);
- super._update(from, address(0), burnAmount);
super._update(from, to, amount - totalTax);
}