The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: low
Invalid

Tokens with more than 18 decimals break liquidation process

Summary

Tokens with more than 18 decimals break liquidation process due to an underflow in distributeAssets function.

Vulnerability Details

If a token with more than 18 decimals will be accepted as collateral in the future it will disrupt the liquidation process.
In distributeAssets function the costInEuros variable scale up assets value to 18 decimals here:

uint256 costInEuros = _portion * 10 ** (18 - asset.token.dec) * uint256(assetPriceUsd) / uint256(priceEurUsd)
* _hundredPC / _collateralRate;

But if a token has more than 18 decimals the expression (18 - asset.token.dec) will underflows and liquidation reverts.

Proof of concept:

In common.js change a token decimals to be more than 18:

const mockTokenManager = async (_) => {
const MockERC20Factory = await ethers.getContractFactory("ERC20Mock");
WBTC = await MockERC20Factory.deploy("Wrapped Bitcoin", "WBTC", 8);
USDC = await MockERC20Factory.deploy("USD Coin", "USDC", 24);

Running liquidationPoolManager tests now give underflow errors:

1) LiquidationPool
claim rewards
allows users to claim their accrued rewards:
Error: VM Exception while processing transaction: reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)
at LiquidationPool.distributeAssets (contracts/LiquidationPool.sol:253)
at LiquidationPoolManager.runLiquidation (contracts/LiquidationPoolManager.sol:80)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at runNextTicks (node:internal/process/task_queues:64:3)
at listOnTimeout (node:internal/timers:538:9)
at processTimers (node:internal/timers:512:7)
at HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1866:23)
at HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:524:16)
at EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1482:18)
2) LiquidationPoolManager
runLiquidation
distributes liquidated assets among stake holders if there is enough EUROs to purchase:
AssertionError: Expected transaction NOT to be reverted, but it reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at runNextTicks (node:internal/process/task_queues:64:3)
at listOnTimeout (node:internal/timers:538:9)
at processTimers (node:internal/timers:512:7)
at Context.<anonymous> (test/liquidationPoolManager.js:238:7)
3) LiquidationPoolManager
runLiquidation
returns unpurchased liquidated assets to protocol address:
Error: VM Exception while processing transaction: reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)
at LiquidationPool.distributeAssets (contracts/LiquidationPool.sol:253)
at LiquidationPoolManager.runLiquidation (contracts/LiquidationPoolManager.sol:80)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at runNextTicks (node:internal/process/task_queues:64:3)
at listOnTimeout (node:internal/timers:538:9)
at processTimers (node:internal/timers:512:7)
at HardhatNode._mineBlockWithPendingTxs (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:1866:23)
at HardhatNode.mineBlock (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:524:16)
at EthModule._sendTransactionAndReturnHash (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:1482:18)
4) LiquidationPoolManager
runLiquidation
increases existing rewards with multiple liquidations:
AssertionError: Expected transaction NOT to be reverted, but it reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at runNextTicks (node:internal/process/task_queues:64:3)
at listOnTimeout (node:internal/timers:538:9)
at processTimers (node:internal/timers:512:7)
at Context.<anonymous> (test/liquidationPoolManager.js:469:7)

Impact

Smart Vaults with a token with more than 24 decimals can't be liquidated.

Tools Used

Manual review.

Recommendations

Check token decimals and scale down if a token has more than 18 decimals.

uint256 costInEuros;
if (asset.token.dec <= 18) {
costInEuros = _portion * 10 ** (18 - asset.token.dec) * uint256(assetPriceUsd)
/ uint256(priceEurUsd) * _hundredPC / _collateralRate;
} else {
costInEuros = _portion / 10 ** (asset.token.dec - 18) * uint256(assetPriceUsd)
/ uint256(priceEurUsd) * _hundredPC / _collateralRate;
}

Update in the same way tokenToEurAvg, tokenToEur and eurToToken functions in PriceCalculator.

Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

informational/invalid

darksnow Submitter
over 1 year ago
hrishibhat Lead Judge
over 1 year ago
hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

informational/invalid

Support

FAQs

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