diff --git a/src/Dropper.sol b/src/Dropper.sol index efb0e95..b590ac0 100644 --- a/src/Dropper.sol +++ b/src/Dropper.sol @@ -69,6 +69,7 @@ contract Dropper { error InsufficientTokensRemaining(); error InvalidMerkleProof(); error ArityMismatch(); + error DropIdInvalid(); mapping(uint256 => DropData) public drops; mapping(uint256 => mapping(address => bool)) private _claimed; @@ -185,6 +186,7 @@ contract Dropper { * @param dropId The drop ID of the drop to refund */ function refundToRecipient(uint256 dropId) external { + if (dropId > numDrops || dropId == 0) revert DropIdInvalid(); DropData storage drop = drops[dropId]; if (drop.expirationTimestamp > block.timestamp) revert DropStillLive(); if (drop.totalTokens == drop.claimedTokens) revert AllTokensClaimed(); @@ -206,6 +208,7 @@ contract Dropper { * @param merkleProof The merkle inclusion proof */ function claim(uint256 dropId, uint256 amount, bytes32[] calldata merkleProof) public { + if (dropId > numDrops || dropId == 0) revert DropIdInvalid(); DropData storage drop = drops[dropId]; if (drop.expirationTimestamp <= block.timestamp || block.timestamp < drop.startTimestamp) revert DropNotLive(); diff --git a/test/Dropper.t.sol b/test/Dropper.t.sol index d9ae05b..d78b2c6 100644 --- a/test/Dropper.t.sol +++ b/test/Dropper.t.sol @@ -342,6 +342,19 @@ contract DropperTest is PRBTest, StdCheats { assertEq(token.balanceOf(address(this)), tokensToRefund); } + function test_refundToRecipient_reverts_dropIdInvalid() public { + (uint256 dropId,) = + testCreateDrop([address(1), address(2), address(3), address(4)], [uint40(100), 1000, 1000, 1000]); + + vm.warp(block.timestamp + 3601); + + vm.expectRevert(Dropper.DropIdInvalid.selector); + dropper.refundToRecipient(dropId + 1); + + vm.expectRevert(Dropper.DropIdInvalid.selector); + dropper.refundToRecipient(0); + } + function test_createDrop_fail_endBeforeStart() external { vm.expectRevert(Dropper.EndBeforeStart.selector); dropper.createDrop(