@croptop/core-v6 0.0.37 → 0.0.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/foundry.toml +2 -1
- package/package.json +25 -13
- package/script/ConfigureFeeProject.s.sol +8 -5
- package/src/CTDeployer.sol +52 -51
- package/src/CTPublisher.sol +20 -5
- package/src/interfaces/ICTDeployer.sol +2 -2
- package/ADMINISTRATION.md +0 -94
- package/ARCHITECTURE.md +0 -96
- package/AUDIT_INSTRUCTIONS.md +0 -88
- package/RISKS.md +0 -78
- package/SKILLS.md +0 -46
- package/STYLE_GUIDE.md +0 -610
- package/USER_JOURNEYS.md +0 -134
- package/foundry.lock +0 -11
- package/slither-ci.config.json +0 -10
- package/sphinx.lock +0 -507
- package/test/CTDeployer.t.sol +0 -616
- package/test/CTProjectOwner.t.sol +0 -185
- package/test/CTPublisher.t.sol +0 -869
- package/test/ClaimCollectionOwnership.t.sol +0 -315
- package/test/CroptopAttacks.t.sol +0 -437
- package/test/Fork.t.sol +0 -227
- package/test/TestAuditGaps.sol +0 -696
- package/test/Test_MetadataGeneration.t.sol +0 -79
- package/test/audit/CodexNemesisCroptopPublisherBoundary.t.sol +0 -329
- package/test/audit/CodexNemesisCurrencyPoCs.t.sol +0 -371
- package/test/audit/CodexNemesisFreshRound.t.sol +0 -395
- package/test/audit/CodexNemesisMetadataShadow.t.sol +0 -203
- package/test/audit/CodexNemesisPoCs.t.sol +0 -263
- package/test/audit/CodexNemesisPolicyReuse.t.sol +0 -168
- package/test/audit/CodexNemesisUriDrift.t.sol +0 -252
- package/test/audit/DeployerPermissionBypass.t.sol +0 -213
- package/test/audit/EmptyPostFeeBypass.t.sol +0 -53
- package/test/audit/FeeBeneficiaryReentrancy.t.sol +0 -247
- package/test/audit/FeeFallbackBlackhole.t.sol +0 -263
- package/test/fork/PublishFork.t.sol +0 -440
- package/test/regression/DuplicateUriFeeEvasion.t.sol +0 -312
- package/test/regression/FeeEvasion.t.sol +0 -286
- package/test/regression/StaleTierIdMapping.t.sol +0 -218
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity 0.8.28;
|
|
3
|
-
|
|
4
|
-
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
5
|
-
import "forge-std/Test.sol";
|
|
6
|
-
|
|
7
|
-
import {IJB721TiersHook} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHook.sol";
|
|
8
|
-
import {IJB721TiersHookStore} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHookStore.sol";
|
|
9
|
-
import {JB721Tier} from "@bananapus/721-hook-v6/src/structs/JB721Tier.sol";
|
|
10
|
-
import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfig.sol";
|
|
11
|
-
import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
|
|
12
|
-
import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
13
|
-
import {IJBTerminal} from "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
|
|
14
|
-
import {JBPermissionsData} from "@bananapus/core-v6/src/structs/JBPermissionsData.sol";
|
|
15
|
-
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
16
|
-
|
|
17
|
-
import {CTPublisher} from "../../src/CTPublisher.sol";
|
|
18
|
-
import {CTAllowedPost} from "../../src/structs/CTAllowedPost.sol";
|
|
19
|
-
import {CTPost} from "../../src/structs/CTPost.sol";
|
|
20
|
-
|
|
21
|
-
contract BlackholeMockPermissions is IJBPermissions {
|
|
22
|
-
// forge-lint: disable-next-line(mixed-case-function)
|
|
23
|
-
function WILDCARD_PROJECT_ID() external pure returns (uint256) {
|
|
24
|
-
return 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function permissionsOf(address, address, uint256) external pure returns (uint256) {
|
|
28
|
-
return 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function hasPermission(address, address, uint256, uint256, bool, bool) external pure returns (bool) {
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function hasPermissions(address, address, uint256, uint256[] calldata, bool, bool) external pure returns (bool) {
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function setPermissionsFor(address, JBPermissionsData calldata) external {}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
contract BlackholeMockStore {
|
|
43
|
-
function maxTierIdOf(address) external pure returns (uint256) {
|
|
44
|
-
return 0;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function isTierRemoved(address, uint256) external pure returns (bool) {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function tierOf(address, uint256, bool) external pure returns (JB721Tier memory tier) {
|
|
52
|
-
return tier;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
contract BlackholeMockHook {
|
|
57
|
-
uint256 public immutable PROJECT_ID;
|
|
58
|
-
IJB721TiersHookStore public immutable STORE;
|
|
59
|
-
address public immutable OWNER;
|
|
60
|
-
|
|
61
|
-
constructor(uint256 projectId, IJB721TiersHookStore store_, address owner_) {
|
|
62
|
-
PROJECT_ID = projectId;
|
|
63
|
-
STORE = store_;
|
|
64
|
-
OWNER = owner_;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function adjustTiers(JB721TierConfig[] calldata, uint256[] calldata) external {}
|
|
68
|
-
|
|
69
|
-
function METADATA_ID_TARGET() external view returns (address) {
|
|
70
|
-
return address(this);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function owner() external view returns (address) {
|
|
74
|
-
return OWNER;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
contract AcceptingProjectTerminal {
|
|
79
|
-
uint256 public totalReceived;
|
|
80
|
-
|
|
81
|
-
function pay(
|
|
82
|
-
uint256,
|
|
83
|
-
address,
|
|
84
|
-
uint256,
|
|
85
|
-
address,
|
|
86
|
-
uint256,
|
|
87
|
-
string calldata,
|
|
88
|
-
bytes calldata
|
|
89
|
-
)
|
|
90
|
-
external
|
|
91
|
-
payable
|
|
92
|
-
returns (uint256)
|
|
93
|
-
{
|
|
94
|
-
totalReceived += msg.value;
|
|
95
|
-
return 0;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
contract RevertingFeeTerminal {
|
|
100
|
-
error FeeTerminalDown();
|
|
101
|
-
|
|
102
|
-
function pay(
|
|
103
|
-
uint256,
|
|
104
|
-
address,
|
|
105
|
-
uint256,
|
|
106
|
-
address,
|
|
107
|
-
uint256,
|
|
108
|
-
string calldata,
|
|
109
|
-
bytes calldata
|
|
110
|
-
)
|
|
111
|
-
external
|
|
112
|
-
payable
|
|
113
|
-
returns (uint256)
|
|
114
|
-
{
|
|
115
|
-
revert FeeTerminalDown();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
contract BlackholeDirectory {
|
|
120
|
-
address public projectTerminal;
|
|
121
|
-
address public feeTerminal;
|
|
122
|
-
|
|
123
|
-
function setTerminals(address projectTerminal_, address feeTerminal_) external {
|
|
124
|
-
projectTerminal = projectTerminal_;
|
|
125
|
-
feeTerminal = feeTerminal_;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function primaryTerminalOf(uint256 projectId, address) external view returns (IJBTerminal) {
|
|
129
|
-
return IJBTerminal(projectId == 1 ? feeTerminal : projectTerminal);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
contract RejectingFeeBeneficiary {
|
|
134
|
-
receive() external payable {
|
|
135
|
-
revert("no fee");
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
contract RejectingMintCaller {
|
|
140
|
-
function execute(
|
|
141
|
-
CTPublisher publisher,
|
|
142
|
-
IJB721TiersHook hook,
|
|
143
|
-
CTPost[] memory posts,
|
|
144
|
-
address nftBeneficiary,
|
|
145
|
-
address feeBeneficiary
|
|
146
|
-
)
|
|
147
|
-
external
|
|
148
|
-
payable
|
|
149
|
-
{
|
|
150
|
-
publisher.mintFrom{value: msg.value}(hook, posts, nftBeneficiary, feeBeneficiary, bytes(""), bytes(""));
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
receive() external payable {
|
|
154
|
-
revert("no refund");
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
contract AcceptingMintCaller {
|
|
159
|
-
function execute(
|
|
160
|
-
CTPublisher publisher,
|
|
161
|
-
IJB721TiersHook hook,
|
|
162
|
-
CTPost[] memory posts,
|
|
163
|
-
address nftBeneficiary,
|
|
164
|
-
address feeBeneficiary
|
|
165
|
-
)
|
|
166
|
-
external
|
|
167
|
-
payable
|
|
168
|
-
{
|
|
169
|
-
publisher.mintFrom{value: msg.value}(hook, posts, nftBeneficiary, feeBeneficiary, bytes(""), bytes(""));
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
receive() external payable {}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
contract FeeFallbackBlackholeTest is Test {
|
|
176
|
-
BlackholeMockPermissions permissions;
|
|
177
|
-
BlackholeDirectory directory;
|
|
178
|
-
BlackholeMockStore store;
|
|
179
|
-
BlackholeMockHook hook;
|
|
180
|
-
AcceptingProjectTerminal projectTerminal;
|
|
181
|
-
RevertingFeeTerminal feeTerminal;
|
|
182
|
-
RejectingFeeBeneficiary feeBeneficiary;
|
|
183
|
-
RejectingMintCaller caller;
|
|
184
|
-
AcceptingMintCaller acceptingCaller;
|
|
185
|
-
CTPublisher publisher;
|
|
186
|
-
|
|
187
|
-
function setUp() public {
|
|
188
|
-
permissions = new BlackholeMockPermissions();
|
|
189
|
-
directory = new BlackholeDirectory();
|
|
190
|
-
store = new BlackholeMockStore();
|
|
191
|
-
hook = new BlackholeMockHook(2, IJB721TiersHookStore(address(store)), address(this));
|
|
192
|
-
projectTerminal = new AcceptingProjectTerminal();
|
|
193
|
-
feeTerminal = new RevertingFeeTerminal();
|
|
194
|
-
feeBeneficiary = new RejectingFeeBeneficiary();
|
|
195
|
-
caller = new RejectingMintCaller();
|
|
196
|
-
acceptingCaller = new AcceptingMintCaller();
|
|
197
|
-
publisher = new CTPublisher(IJBDirectory(address(directory)), permissions, 1, address(0));
|
|
198
|
-
|
|
199
|
-
directory.setTerminals(address(projectTerminal), address(feeTerminal));
|
|
200
|
-
|
|
201
|
-
CTAllowedPost[] memory allowedPosts = new CTAllowedPost[](1);
|
|
202
|
-
allowedPosts[0] = CTAllowedPost({
|
|
203
|
-
hook: address(hook),
|
|
204
|
-
category: 1,
|
|
205
|
-
minimumPrice: 1,
|
|
206
|
-
minimumTotalSupply: 1,
|
|
207
|
-
maximumTotalSupply: type(uint32).max,
|
|
208
|
-
maximumSplitPercent: 0,
|
|
209
|
-
allowedAddresses: new address[](0)
|
|
210
|
-
});
|
|
211
|
-
publisher.configurePostingCriteriaFor(allowedPosts);
|
|
212
|
-
|
|
213
|
-
vm.deal(address(caller), 105);
|
|
214
|
-
vm.deal(address(acceptingCaller), 105);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function test_feePaymentFailure_refundsMsgSenderAndPreservesMint() public {
|
|
218
|
-
CTPost[] memory posts = new CTPost[](1);
|
|
219
|
-
posts[0] = CTPost({
|
|
220
|
-
encodedIPFSUri: keccak256("post"),
|
|
221
|
-
totalSupply: 1,
|
|
222
|
-
price: 100,
|
|
223
|
-
category: 1,
|
|
224
|
-
splitPercent: 0,
|
|
225
|
-
splits: new JBSplit[](0)
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
vm.prank(address(acceptingCaller));
|
|
229
|
-
acceptingCaller.execute{value: 105}(
|
|
230
|
-
publisher, IJB721TiersHook(address(hook)), posts, address(this), address(feeBeneficiary)
|
|
231
|
-
);
|
|
232
|
-
|
|
233
|
-
assertEq(projectTerminal.totalReceived(), 100, "main project payment should still succeed");
|
|
234
|
-
assertEq(address(feeTerminal).balance, 0, "fee terminal should receive nothing after reverting");
|
|
235
|
-
assertEq(address(feeBeneficiary).balance, 0, "fee beneficiary should receive nothing");
|
|
236
|
-
assertEq(address(acceptingCaller).balance, 5, "caller should receive the refunded fee");
|
|
237
|
-
assertEq(address(publisher).balance, 0, "publisher should not retain trapped fees");
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function test_feePaymentFailure_revertsIfMsgSenderRejectsRefund() public {
|
|
241
|
-
CTPost[] memory posts = new CTPost[](1);
|
|
242
|
-
posts[0] = CTPost({
|
|
243
|
-
encodedIPFSUri: keccak256("post"),
|
|
244
|
-
totalSupply: 1,
|
|
245
|
-
price: 100,
|
|
246
|
-
category: 1,
|
|
247
|
-
splitPercent: 0,
|
|
248
|
-
splits: new JBSplit[](0)
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
vm.prank(address(caller));
|
|
252
|
-
vm.expectRevert(abi.encodeWithSelector(CTPublisher.CTPublisher_FeePaymentFailed.selector, 5));
|
|
253
|
-
caller.execute{value: 105}(
|
|
254
|
-
publisher, IJB721TiersHook(address(hook)), posts, address(this), address(feeBeneficiary)
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
assertEq(projectTerminal.totalReceived(), 0, "main project payment should roll back with the fee failure");
|
|
258
|
-
assertEq(address(feeTerminal).balance, 0, "fee terminal should receive nothing after reverting");
|
|
259
|
-
assertEq(address(feeBeneficiary).balance, 0, "fee beneficiary should receive nothing");
|
|
260
|
-
assertEq(address(caller).balance, 105, "caller should retain funds when the mint reverts");
|
|
261
|
-
assertEq(address(publisher).balance, 0, "publisher should not retain trapped fees");
|
|
262
|
-
}
|
|
263
|
-
}
|