Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: low
Invalid

The Transfer event is emitted multiple times when the DebtToken is minted and burned.

01. Relevant GitHub Links

02. Summary

The Transfer event is emitted multiple times when the DebtToken is minted and burned.

03. Vulnerability Details

The DebtToken::mint function is emitting the Transfer event at the end. However, that event is emitted in the _update function.

function mint(
address user,
address onBehalfOf,
uint256 amount,
uint256 index
) external override onlyReservePool returns (bool, uint256, uint256) {
if (user == address(0) || onBehalfOf == address(0)) revert InvalidAddress();
if (amount == 0) {
return (false, 0, totalSupply());
}
uint256 amountScaled = amount.rayDiv(index);
if (amountScaled == 0) revert InvalidAmount();
uint256 scaledBalance = balanceOf(onBehalfOf);
bool isFirstMint = scaledBalance == 0;
uint256 balanceIncrease = 0;
if (_userState[onBehalfOf].index != 0 && _userState[onBehalfOf].index < index) {
balanceIncrease = scaledBalance.rayMul(index) - scaledBalance.rayMul(_userState[onBehalfOf].index);
}
_userState[onBehalfOf].index = index.toUint128();
uint256 amountToMint = amount + balanceIncrease;
_mint(onBehalfOf, amountToMint.toUint128());
@> emit Transfer(address(0), onBehalfOf, amountToMint);
emit Mint(user, onBehalfOf, amountToMint, balanceIncrease, index);
return (scaledBalance == 0, amountToMint, totalSupply());
}

The function that overrides the _update function is also emitting a Transfer evnet once again, so there are a total of three Transfer events emitted.

function _update(address from, address to, uint256 amount) internal virtual override {
if (from != address(0) && to != address(0)) {
revert TransfersNotAllowed(); // Only allow minting and burning
}
uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedDebt());
super._update(from, to, scaledAmount);
emit Transfer(from, to, amount);
}

Here we have two cases where we are firing an event with scaledAmount and an event based on the amount value, which may be the intended behavior, but it's still a problem because they have the same event name.

Also, the same problem occurs with burn functions that use the _update function.

If you look at the actual logs, you'll see that the Transfer event is emitted multiple times.

│ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: alice: [0x328809Bc894f92807417D2dAD6b7C998c1aFdac6], value: 48674145964211444886 [4.867e19])
│ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: alice: [0x328809Bc894f92807417D2dAD6b7C998c1aFdac6], value: 50000000000000000000 [5e19])
│ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: alice: [0x328809Bc894f92807417D2dAD6b7C998c1aFdac6], value: 50000000000000000000 [5e19])
│ │ ├─ emit Mint(caller: alice: [0x328809Bc894f92807417D2dAD6b7C998c1aFdac6], onBehalfOf: alice: [0x328809Bc894f92807417D2dAD6b7C998c1aFdac6], amount: 50000000000000000000 [5e19], balanceIncrease: 0, index: 1027239389814120488478727539 [1.027e27])

04. Impact

  • This can be confusing for users and cause problems for off-chain services that rely on events to function.

06. Tools Used

Manual Code Review and Foundry

07. Recommended Mitigation

Rename the event or emit the Transfer event from only one location.

Updates

Lead Judging Commences

inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.