-
-
Notifications
You must be signed in to change notification settings - Fork 111
/
LilOpenSea.t.sol
180 lines (139 loc) · 4.97 KB
/
LilOpenSea.t.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
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.10;
import { Vm } from 'forge-std/Vm.sol';
import { DSTest } from 'ds-test/test.sol';
import { LilOpenSea } from '../LilOpenSea.sol';
import { ERC721 } from 'solmate/tokens/ERC721.sol';
contract User {
receive() external payable {}
}
contract TestNFT is ERC721('Test NFT', 'TEST') {
uint256 public tokenId = 1;
function tokenURI(uint256) public pure override returns (string memory) {
return 'test';
}
function mint() public payable returns (uint256) {
_mint(msg.sender, tokenId);
return tokenId++;
}
}
contract LilOpenSeaTest is DSTest {
uint256 nftId;
User internal user;
TestNFT internal nft;
LilOpenSea internal lilOpenSea;
Vm internal hevm = Vm(HEVM_ADDRESS);
event NewListing(LilOpenSea.Listing listing);
event ListingRemoved(LilOpenSea.Listing listing);
event ListingBought(address indexed buyer, LilOpenSea.Listing listing);
function setUp() public {
user = new User();
nft = new TestNFT();
lilOpenSea = new LilOpenSea();
// Ensure marketplace can access tokens
nft.setApprovalForAll(address(lilOpenSea), true);
// Ensure marketplace can access user's tokens
hevm.prank(address(user));
nft.setApprovalForAll(address(lilOpenSea), true);
nftId = nft.mint();
}
function testCanCreateSale() public {
assertEq(nft.ownerOf(nftId), address(this));
hevm.expectEmit(false, false, false, true);
emit NewListing(
LilOpenSea.Listing({
tokenContract: nft,
tokenId: nftId,
askPrice: 1 ether,
creator: address(this)
})
);
uint256 listingId = lilOpenSea.list(nft, nftId, 1 ether);
assertEq(nft.ownerOf(nftId), address(lilOpenSea));
(ERC721 tokenContract, uint256 tokenId, address creator, uint256 askPrice) = lilOpenSea
.getListing(listingId);
assertEq(address(tokenContract), address(nft));
assertEq(tokenId, nftId);
assertEq(creator, address(this));
assertEq(askPrice, 1 ether);
}
function testNonOwnerCannotCreateSale() public {
assertEq(nft.ownerOf(nftId), address(this));
hevm.prank(address(user));
hevm.expectRevert('WRONG_FROM'); // error comes from ERC721 impl. (solmate in this test)
lilOpenSea.list(nft, nftId, 1 ether);
assertEq(nft.ownerOf(nftId), address(this));
}
function testCannotListWhenTokenIsNotApproved() public {
assertEq(nft.ownerOf(nftId), address(this));
nft.setApprovalForAll(address(lilOpenSea), false);
hevm.expectRevert('NOT_AUTHORIZED'); // error comes from ERC721 impl. (solmate in this test)
lilOpenSea.list(nft, nftId, 1 ether);
assertEq(nft.ownerOf(nftId), address(this));
}
function testCanCancelSale() public {
uint256 listingId = lilOpenSea.list(nft, nftId, 1 ether);
(, , address creator, ) = lilOpenSea.getListing(listingId);
assertEq(creator, address(this));
assertEq(nft.ownerOf(nftId), address(lilOpenSea));
hevm.expectEmit(false, false, false, true);
emit ListingRemoved(
LilOpenSea.Listing({
tokenContract: nft,
tokenId: nftId,
askPrice: 1 ether,
creator: address(this)
})
);
lilOpenSea.cancelListing(listingId);
assertEq(nft.ownerOf(nftId), address(this));
(, , address newCreator, ) = lilOpenSea.getListing(listingId);
assertEq(newCreator, address(0));
}
function testNonOwnerCannotCancelSale() public {
uint256 listingId = lilOpenSea.list(nft, nftId, 1 ether);
(, , address creator, ) = lilOpenSea.getListing(listingId);
assertEq(creator, address(this));
assertEq(nft.ownerOf(nftId), address(lilOpenSea));
hevm.prank(address(user));
hevm.expectRevert(abi.encodeWithSignature('Unauthorized()'));
lilOpenSea.cancelListing(listingId);
assertEq(nft.ownerOf(nftId), address(lilOpenSea));
(, , address newCreator, ) = lilOpenSea.getListing(listingId);
assertEq(newCreator, address(this));
}
function testCannotBuyNotExistingValue() public {
hevm.expectRevert(abi.encodeWithSignature('ListingNotFound()'));
lilOpenSea.buyListing(1);
}
function testCannotBuyWithWrongValue() public {
uint256 listingId = lilOpenSea.list(nft, nftId, 1 ether);
hevm.expectRevert(abi.encodeWithSignature('WrongValueSent()'));
lilOpenSea.buyListing{ value: 0.1 ether }(listingId);
assertEq(nft.ownerOf(nftId), address(lilOpenSea));
}
function testCanBuyListing() public {
uint256 buyerBalance = address(this).balance;
nft.transferFrom(address(this), address(user), nftId);
hevm.prank(address(user));
uint256 listingId = lilOpenSea.list(nft, nftId, 1 ether);
assertEq(address(user).balance, 0);
assertEq(nft.ownerOf(nftId), address(lilOpenSea));
hevm.expectEmit(true, false, false, true);
emit ListingBought(
address(this),
LilOpenSea.Listing({
tokenContract: nft,
tokenId: nftId,
askPrice: 1 ether,
creator: address(user)
})
);
lilOpenSea.buyListing{ value: 1 ether }(listingId);
assertEq(nft.ownerOf(nftId), address(this));
assertEq(address(user).balance, 1 ether);
assertEq(address(this).balance, buyerBalance - 1 ether);
(, , address creator, ) = lilOpenSea.getListing(listingId);
assertEq(creator, address(0));
}
}