09.challenge
2023-07-28 20:09:40 # 16.CBSC 2022

09.challenge

分析

1.全局观

四个合约

  • deploy
    • 部署attack2合约
  • attack2
    • 实现了IERC721Receiver,说明可以接收ERC721代币
    • 有选择性的调用EverytingIsArt合约的hopeIsInSight()
  • attack
    • 实现了IERC721Receiver,说明可以接收ERC721代币
    • 有选择性的调用EverytingIsArt合约的hopeIsInSight()theHope()
  • EverytingIsArt
    • 是一个ERC721代币
    • 三个方法可以铸币
    • 初始化题目

2.任务

刚好获得288个NFT

1
2
3
4
function isCompleted() public view returns (bool) {
require(balanceOf(msg.sender) == 288,"You are not yet a good artist, you should keep trying.");
return true;
}

3.分析

有三个方法都可以获得代币,先来看becomeAnArtist()

1
2
3
4
5
6
7
8
9
10
11
function becomeAnArtist(uint256 _count) public returns (bool) {
require(_count >= 288, "Why don't you want to be an artist?");

for (uint256 i = 0; i < _count; i++) {
uint256 tokenId = totalMinted.add(1);
_safeMint(msg.sender, tokenId);
totalMinted = totalMinted.add(1);
}

return true;
}

额这个直接调用就完成题目了,因为题目是_safeMint()因此需要实现onERC721Received(),这个随便骗骗它就好

解题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "../../src/09.challenge/EverytingIsArt.sol";

contract attackTest is Test {
EverytingIsArt everytingIsArt;

function setUp() public{
everytingIsArt = new EverytingIsArt();
}

function test_isComplete() public{
everytingIsArt.becomeAnArtist(288);
assertEq(everytingIsArt.isCompleted(),true);
}

function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data)public returns (bytes4){
return this.onERC721Received.selector;
}
}