-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy path12-flash-loaner.ts
More file actions
95 lines (73 loc) · 3.34 KB
/
Copy path12-flash-loaner.ts
File metadata and controls
95 lines (73 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { expect } from "chai";
import { Contract, Signer, BigNumber } from "ethers";
import { ethers } from "hardhat";
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 BN = BigNumber;
let precision = BN.from(10).pow(18);
let accounts: Signer[];
let attacker: Signer;
let o1: Signer;
let o2: Signer;
let admin: Signer; // should not be used
let adminUser: Signer; // should not be used
let flashLoaner: Contract; // flashloan contract
let usdc: Contract; // token contracts
let dai: Contract;
let uniFactory: Contract; // uniswap contracts
let uniRouter: Contract;
let uniPair: Contract; // DAI-USDC pool
let weth: Contract;
/// preliminary state
before(async () => {
accounts = await ethers.getSigners();
[attacker, o1, o2, admin, adminUser] = accounts;
// deploying token contracts:
let usdcFactory = await ethers.getContractFactory('Token')
usdc = await usdcFactory.connect(admin).deploy('USDC','USDC')
await usdc.connect(admin).mintPerUser(
[await admin.getAddress(), await adminUser.getAddress()],
[precision.mul(1_000_000), precision.mul(100_000)],
)
let daiFactory = await ethers.getContractFactory('Token')
dai = await daiFactory.connect(admin).deploy('DAI','DAI')
await dai.connect(admin).mintPerUser(
[await admin.getAddress()],[precision.mul(1_000_000)]
)
// deploying uniswap contracts:
let wethFactory = await ethers.getContractFactory('WETH9')
weth = await wethFactory.connect(admin).deploy()
let uniFactoryFactory = new ethers.ContractFactory(factoryJson.abi, factoryJson.bytecode)
uniFactory = await uniFactoryFactory.connect(admin).deploy(await admin.getAddress())
let uniRouterFactory = new ethers.ContractFactory(routerJson.abi, routerJson.bytecode)
uniRouter = await uniRouterFactory.connect(admin).deploy(uniFactory.address,weth.address)
// --adding initial liquidity for DAI
await usdc.connect(admin).approve(uniRouter.address,ethers.constants.MaxUint256)
await dai.connect(admin).approve(uniRouter.address,ethers.constants.MaxUint256)
await uniRouter.connect(admin).addLiquidity( // creates pair
usdc.address,dai.address,
precision.mul(1_000_000),
precision.mul(1_000_000),
0,0,
await admin.getAddress(),
(await ethers.provider.getBlock('latest')).timestamp*2
)
let pairAddress = await uniFactory.getPair(usdc.address,dai.address)
let uniPairFactory = new ethers.ContractFactory(pairJson.abi, pairJson.bytecode, admin)
uniPair = uniPairFactory.attach(pairAddress)
// initializing core contracts:
let flashLoanerFactory = await ethers.getContractFactory('FlashLoaner')
flashLoaner = await flashLoanerFactory.connect(admin).deploy(usdc.address,"fUSDC","fUSDC")
await usdc.connect(adminUser).approve(flashLoaner.address,ethers.constants.MaxUint256)
await flashLoaner.connect(adminUser).deposit(precision.mul(100_000),await adminUser.getAddress())
});
it("solves the challenge", async function () {
// implement solution here
});
/// expected final state
after(async () => {
// attacker drains >= 99% of funds
expect(await usdc.balanceOf(await attacker.getAddress())).to.be.gte(precision.mul(99_000));
expect(await usdc.balanceOf(flashLoaner.address)).to.be.lte(precision.mul(1_000));
});