-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy path19-fatality.ts
More file actions
161 lines (130 loc) · 5.53 KB
/
Copy path19-fatality.ts
File metadata and controls
161 lines (130 loc) · 5.53 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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 vault: Contract; // core contracts
let bunnyMinter: Contract;
let zapBSC: Contract;
let usdc: Contract; // token contracts
let dai: Contract;
let bunny: Contract;
let bnb: Contract;
let uniFactory: Contract; // uniswap contracts
let uniRouter: Contract;
let weth: Contract;
let usdcBnbPair: Contract;
let bnbBunnyPair: Contract;
let startBlock: Number;
/// 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()],[precision.mul(1_900_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_900_000)]
)
let bunnyFactory = await ethers.getContractFactory('Token')
bunny = await bunnyFactory.connect(admin).deploy('BUNNY','BUNNY')
await bunny.connect(admin).mintPerUser(
[await admin.getAddress()],[precision.mul(9_000)]
)
let bnbFactory = await ethers.getContractFactory('Token')
bnb = await bnbFactory.connect(admin).deploy('BNB','BNB')
await bnb.connect(admin).mintPerUser(
[await admin.getAddress()],[precision.mul(9_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
await usdc.connect(admin).approve(uniRouter.address,ethers.constants.MaxUint256)
await dai.connect(admin).approve(uniRouter.address,ethers.constants.MaxUint256)
await bunny.connect(admin).approve(uniRouter.address,ethers.constants.MaxUint256)
await bnb.connect(admin).approve(uniRouter.address,ethers.constants.MaxUint256)
await uniRouter.connect(admin).addLiquidity( // creates USDC-DAI 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
)
await uniRouter.connect(admin).addLiquidity( // creates USDC-BNB pair
usdc.address,bnb.address,
precision.mul(900_000),
precision.mul(3_000),
0,0,
await admin.getAddress(),
(await ethers.provider.getBlock('latest')).timestamp*2
)
await uniRouter.connect(admin).addLiquidity( // creates DAI-BNB pair
dai.address,bnb.address,
precision.mul(900_000),
precision.mul(3_000),
0,0,
await admin.getAddress(),
(await ethers.provider.getBlock('latest')).timestamp*2
)
await uniRouter.connect(admin).addLiquidity( // creates BUNNY-BNB pair
bunny.address,bnb.address,
precision.mul(9_000), // 3x bunny per 1x bnb
precision.mul(3_000),
0,0,
await admin.getAddress(),
(await ethers.provider.getBlock('latest')).timestamp*2
)
let pairAddress = await uniFactory.getPair(usdc.address,bnb.address)
let uniPairFactory = new ethers.ContractFactory(pairJson.abi, pairJson.bytecode, admin)
usdcBnbPair = uniPairFactory.attach(pairAddress)
pairAddress = await uniFactory.getPair(bnb.address,bunny.address)
bnbBunnyPair = uniPairFactory.attach(pairAddress)
// deploying core contracts
let zapBSCFactory = await ethers.getContractFactory('ZapBSC')
zapBSC = await zapBSCFactory.connect(admin).deploy(
uniRouter.address,bnb.address,usdc.address,bunny.address
)
let bunnyMinterFactory = await ethers.getContractFactory('BunnyMinter')
bunnyMinter = await bunnyMinterFactory.connect(admin).deploy(
zapBSC.address,uniRouter.address,bnb.address,bunny.address,
await uniFactory.getPair(bnb.address,bunny.address)
)
let vaultFactory = await ethers.getContractFactory('AutoCompoundVault')
vault = await vaultFactory.connect(admin).deploy(
await uniFactory.getPair(bnb.address,usdc.address),bunnyMinter.address
)
// --required updates to contract state
await zapBSC.connect(admin).setMinter(bunnyMinter.address)
await bunnyMinter.connect(admin).setMinter(vault.address)
await bunny.connect(admin).transferOwnership(bunnyMinter.address) // bunnyMinter given mint rights
startBlock = await ethers.provider.getBlockNumber()
});
it("solves the challenge", async function () {
// implement solution here
});
/// expected final state
after(async () => {
// attacker steals at least 1100 BNB - only allowed 2 blocks to run exploit
expect(await bnb.balanceOf(await attacker.getAddress())).to.be.gte(precision.mul(1_100))
expect(await ethers.provider.getBlockNumber()).to.be.lte(startBlock+2)
});