Tiny Licorice Loris
Medium
Malicious actors can prevent executeMintUnbacked()
from setting minted Atokens as collateral for first time supply users.
returned isFirstSupply
bool relies on users Atoken balance. A malicious user can transfer a minuscule amount of Atokens to user who is just minting Atokens via BridgeLogic.executeMintUnbacked()
for the first time... preventing the function from setting minted Atokens as collateral for the user.
The root cause of this issue can be found in ScaledBalanceTokenBase._mintScaled()
which is used by Atoken.mint()
. In the function, the returned boolean value depends on the balance of the user whom the tokens are being minted for.
function _mintScaled(
address caller,
address onBehalfOf,
uint256 amount,
uint256 index
) internal returns (bool) {
uint256 amountScaled = amount.rayDiv(index);
require(amountScaled != 0, Errors.INVALID_MINT_AMOUNT);
uint256 scaledBalance = super.balanceOf(onBehalfOf);//@audit
uint256 balanceIncrease = scaledBalance.rayMul(index) -
scaledBalance.rayMul(_userState[onBehalfOf].additionalData);
_userState[onBehalfOf].additionalData = index.toUint128();
_mint(onBehalfOf, amountScaled.toUint128());
uint256 amountToMint = amount + balanceIncrease;
emit Transfer(address(0), onBehalfOf, amountToMint);
emit Mint(caller, onBehalfOf, amountToMint, balanceIncrease, index);
return (scaledBalance == 0);
}
so if scaledBalance != 0 for any reason, isFirstSupply
will be false
function mint(
address caller,
address onBehalfOf,
uint256 amount,
uint256 index
) external virtual override onlyPool returns (bool) {
return _mintScaled(caller, onBehalfOf, amount, index);
}
This will prevent BridgeLogic.executeMintUnbacked()
from setting the minted Atokens as collateral for the user even though it is his first time minting.
bool isFirstSupply = IAToken(reserveCache.aTokenAddress).mint(//@audit-issue `executeMintUnbacked()` can fail to `setUsingAsCollateral()` for first-time supply user. (A malicious user can prevent this by transferring a very minuscule amount to `onBehalfOf`)
msg.sender,
onBehalfOf,
amount,
reserveCache.nextLiquidityIndex
);
if (isFirstSupply) {
if (
ValidationLogic.validateAutomaticUseAsCollateral(
reservesData,
reservesList,
userConfig,
reserveCache.reserveConfiguration,
reserveCache.aTokenAddress
)
) {
userConfig.setUsingAsCollateral(reserve.id, true);
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
}
}
emit MintUnbacked(asset, msg.sender, onBehalfOf, amount, referralCode);
}
A malicious user can transfer a minuscule amount of Atokens to user who is just minting Atokens via BridgeLogic.executeMintUnbacked()
for the first time... preventing the function from setting minted Atokens as collateral for the user.
- Atokens need to be transferrable. Which they are https://aave.com/docs/developers/smart-contracts/tokenization#atoken
- User is indeed minting Atokens for the first time
- Attacker needs to be able to monitor the user.. either via observing the mempool and frontrunning users tx or knowing user in person.
- A user Alice is minting Atokens for the first time via
BridgeLogic.executeMintUnbacked()
- Attacker notices and sends Alice a minuscule amount of the Atoken(e.g 1 cent of the token)... so that Alice's balance will != 0
BridgeLogic.executeMintUnbacked()
will fail to set minted Atokens as collateral for Alice even though it is her first time of minting collaterals via the function
Attacker can prevent Atokens minted for users via BridgeLogic.executeMintUnbacked()
for the first time from being used as collateral for the users.
The minted Atokens wont be used as collateral
No response
To determine if a user is minting Atokens for the first time don't depend on user's balance.
You can use the same method used for 'initialized'....where it is set on first call and recorded per user
External parties can influence the balance of tokens.