Skip to content

Commit 3b4c7f3

Browse files
authored
Merge pull request #47 from realproject7/task/42-input-validations
[#42] Add input validations: title, hash, zero-address, array cap
2 parents 9435f22 + c68fa99 commit 3b4c7f3

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

script/E2ETest.s.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,11 +407,11 @@ contract E2ETest is Script {
407407
console.log("[F2] CID exact max (100 chars) PASS storylineId=%d", idF2);
408408
scenariosPassed++;
409409

410-
// F4: chainPlot with empty title (title not validated in chainPlot) — use F1's storyline
411-
FACTORY.chainPlot(idF1, "", CID_46, HASH_B);
410+
// F4: chainPlot to F1 storyline (verifies cross-storyline chaining)
411+
FACTORY.chainPlot(idF1, "F1 Chapter 2", CID_46, HASH_B);
412412
(,, uint24 pc,,) = FACTORY.storylines(idF1);
413413
require(pc == 2, "F4: plotCount should be 2");
414-
console.log("[F4] chainPlot with empty title PASS plotCount=%d", pc);
414+
console.log("[F4] chainPlot to F1 storyline PASS plotCount=%d", pc);
415415
scenariosPassed++;
416416

417417
// F5: Buy then sell same amount - refund < cost due to royalties

src/StoryFactory.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ contract StoryFactory {
7878
uint128[] memory _stepRanges,
7979
uint128[] memory _stepPrices
8080
) {
81+
require(_bond != address(0), "Zero bond address");
82+
require(_plotToken != address(0), "Zero token address");
8183
require(_stepRanges.length == _stepPrices.length, "Step arrays length mismatch");
8284
require(_stepRanges.length > 0, "Empty step arrays");
85+
require(_stepRanges.length <= 1000, "Too many steps");
8386

8487
BOND = IMCV2_Bond(_bond);
8588
PLOT_TOKEN = IERC20(_plotToken);
@@ -105,6 +108,7 @@ contract StoryFactory {
105108
{
106109
require(bytes(title).length > 0, "Empty title");
107110
require(bytes(openingCID).length >= 46 && bytes(openingCID).length <= 100, "Invalid CID");
111+
require(openingHash != bytes32(0), "Empty hash");
108112

109113
storylineId = ++storylineCount;
110114

@@ -155,7 +159,9 @@ contract StoryFactory {
155159
{
156160
Storyline storage s = storylines[storylineId];
157161
require(msg.sender == s.writer, "Not writer");
162+
require(bytes(title).length > 0, "Empty title");
158163
require(bytes(contentCID).length >= 46 && bytes(contentCID).length <= 100, "Invalid CID");
164+
require(contentHash != bytes32(0), "Empty hash");
159165
if (s.hasDeadline) {
160166
require(block.timestamp <= uint256(s.lastPlotTime) + 168 hours, "Deadline passed");
161167
}

test/StoryFactory.t.sol

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,4 +372,64 @@ contract StoryFactoryTest is Test {
372372
assertEq(factory.MINT_ROYALTY(), 100); // 1%
373373
assertEq(factory.BURN_ROYALTY(), 100); // 1%
374374
}
375+
376+
// ===================================================================
377+
// Input validations (#42)
378+
// ===================================================================
379+
380+
function test_chainPlot_revert_emptyTitle() public {
381+
vm.prank(writer);
382+
uint256 id = factory.createStoryline("Story", VALID_CID, FAKE_HASH, false);
383+
384+
vm.prank(writer);
385+
vm.expectRevert("Empty title");
386+
factory.chainPlot(id, "", VALID_CID, FAKE_HASH);
387+
}
388+
389+
function test_createStoryline_revert_emptyHash() public {
390+
vm.prank(writer);
391+
vm.expectRevert("Empty hash");
392+
factory.createStoryline("Title", VALID_CID, bytes32(0), false);
393+
}
394+
395+
function test_chainPlot_revert_emptyHash() public {
396+
vm.prank(writer);
397+
uint256 id = factory.createStoryline("Story", VALID_CID, FAKE_HASH, false);
398+
399+
vm.prank(writer);
400+
vm.expectRevert("Empty hash");
401+
factory.chainPlot(id, "Chapter 2", VALID_CID, bytes32(0));
402+
}
403+
404+
function test_constructor_revert_zeroBond() public {
405+
uint128[] memory ranges = new uint128[](1);
406+
ranges[0] = 1e18;
407+
uint128[] memory prices = new uint128[](1);
408+
prices[0] = 1e15;
409+
410+
vm.expectRevert("Zero bond address");
411+
new StoryFactory(address(0), address(plot), 1e18, ranges, prices);
412+
}
413+
414+
function test_constructor_revert_zeroToken() public {
415+
uint128[] memory ranges = new uint128[](1);
416+
ranges[0] = 1e18;
417+
uint128[] memory prices = new uint128[](1);
418+
prices[0] = 1e15;
419+
420+
vm.expectRevert("Zero token address");
421+
new StoryFactory(address(bond), address(0), 1e18, ranges, prices);
422+
}
423+
424+
function test_constructor_revert_tooManySteps() public {
425+
uint128[] memory ranges = new uint128[](1001);
426+
uint128[] memory prices = new uint128[](1001);
427+
for (uint256 i = 0; i < 1001; i++) {
428+
ranges[i] = uint128(i + 1);
429+
prices[i] = uint128(i + 1);
430+
}
431+
432+
vm.expectRevert("Too many steps");
433+
new StoryFactory(address(bond), address(plot), 1e18, ranges, prices);
434+
}
375435
}

0 commit comments

Comments
 (0)