Skip to content

Commit 7de5cf2

Browse files
committed
Ensure that a valid child can reedem perk and do tasks
1 parent 7717fef commit 7de5cf2

File tree

2 files changed

+71
-7
lines changed

2 files changed

+71
-7
lines changed

packages/foundry/contracts/KiddoPerks.sol

+15-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ contract KiddoPerks is Ownable {
2626
uint256 id, address by, uint256 tokensRequired
2727
);
2828
error KiddoPerks__PerkAlreadyRedemmed(uint256 id, address by);
29+
error KiddoPerks__NoValidChild(address childAddr);
2930

3031
KDOToken token;
3132
address public parent;
3233

3334
mapping(uint256 => Child) public s_children;
35+
mapping(address child => bool isActive) s_validChildAddresses;
3436
uint256 public s_childrenNextId = 0;
3537

3638
mapping(uint256 => Perk) public s_perks;
@@ -136,7 +138,7 @@ contract KiddoPerks is Ownable {
136138
function isTaskCompletedBy(
137139
uint256 taskId,
138140
address by
139-
) public view returns (bool) {
141+
) public view onlyValidChild(by) returns (bool) {
140142
return s_completedTasksByUser[by][taskId];
141143
}
142144

@@ -196,7 +198,7 @@ contract KiddoPerks is Ownable {
196198

197199
function redeemPerk(
198200
uint256 perkId
199-
) public {
201+
) public onlyValidChild(msg.sender) {
200202
Perk memory perk = s_perks[perkId];
201203
uint256 userTokenBalance = token.balanceOf(msg.sender);
202204
if (userTokenBalance < perk.tokensRequired) {
@@ -223,6 +225,7 @@ contract KiddoPerks is Ownable {
223225
function addChild(string memory name, address childAddr) public onlyOwner {
224226
Child memory newChild = Child(s_childrenNextId, name, childAddr, false);
225227
s_children[s_childrenNextId] = newChild;
228+
s_validChildAddresses[childAddr] = true;
226229
s_childrenNextId++;
227230

228231
emit ChildAdded(name, childAddr);
@@ -245,6 +248,7 @@ contract KiddoPerks is Ownable {
245248
}
246249

247250
s_children[id].removed = true;
251+
s_validChildAddresses[s_children[id].childAddr] = false;
248252

249253
emit ChildRemoved(id);
250254
}
@@ -258,4 +262,13 @@ contract KiddoPerks is Ownable {
258262

259263
return allChildren;
260264
}
265+
266+
modifier onlyValidChild(
267+
address childAddress
268+
) {
269+
if (s_validChildAddresses[childAddress] == false) {
270+
revert KiddoPerks__NoValidChild(childAddress);
271+
}
272+
_;
273+
}
261274
}

packages/foundry/test/KiddoPerks.t.sol

+56-5
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@ contract KiddoPerksTest is Test {
8585
event TaskCompleted(address indexed by, string title, uint256 taskId);
8686
event TokenMinted(address by, uint256 tokenReward);
8787

88-
function testParentCanMarkTaskAsCompleted() public withTaskCreated {
88+
function testParentCanMarkTaskAsCompleted()
89+
public
90+
withTaskCreated
91+
withChildCreated
92+
{
8993
vm.prank(PARENT);
9094
vm.expectEmit(true, true, false, true);
9195
emit TaskCompleted(CHILD_ONE, "Clean up room", 0);
@@ -255,7 +259,7 @@ contract KiddoPerksTest is Test {
255259

256260
event PerkRedeemed(uint256 perkId, address by);
257261

258-
function testChildCanRedeemPerk() public withPerkCreated {
262+
function testChildCanRedeemPerk() public withPerkCreated withChildCreated {
259263
uint256 perkId = 0;
260264
uint256 initialChildBalance = 5 * 10 ** 18;
261265
uint256 perkTokensRequired = 2 * 10 ** 18;
@@ -274,7 +278,11 @@ contract KiddoPerksTest is Test {
274278
assertEq(initialChildBalance, perkTokensRequired + userFinalBalance);
275279
}
276280

277-
function testChildCannotReddemMoreThanOnceAPerk() public withPerkCreated {
281+
function testChildCannotReddemMoreThanOnceAPerk()
282+
public
283+
withPerkCreated
284+
withChildCreated
285+
{
278286
uint256 perkId = 0;
279287
uint256 initialChildBalance = 5 * 10 ** 18;
280288
uint256 perkTokensRequired = 2 * 10 ** 18;
@@ -301,26 +309,69 @@ contract KiddoPerksTest is Test {
301309
function testRevertsOnRedeemWhenChildHasNotEnoughTokenBalance()
302310
public
303311
withPerkCreated
312+
withChildCreated
304313
{
305314
uint256 perkId = 0;
315+
uint256 tokensToMint = 1 * 10 ** 18;
316+
uint256 perkTokensRequired = 2 * 10 ** 18;
306317
vm.prank(address(kiddoPerks));
307-
kdoToken.mint(CHILD_ONE, 1 * 10 ** 18);
318+
kdoToken.mint(CHILD_ONE, tokensToMint);
308319

309320
vm.prank(CHILD_ONE);
310321
vm.expectRevert(
311322
abi.encodeWithSelector(
312323
KiddoPerks.KiddoPerks__NotEnoughTokenBalance.selector,
313324
perkId,
314325
CHILD_ONE,
315-
2 * 10 ** 18
326+
perkTokensRequired
327+
)
328+
);
329+
kiddoPerks.redeemPerk(perkId);
330+
}
331+
332+
function testRevertIfNoValidChildTriesToRedeemPerk() public withPerkCreated {
333+
uint256 perkId = 0;
334+
uint256 tokensToMint = 1 * 10 ** 18;
335+
336+
vm.prank(address(kiddoPerks));
337+
kdoToken.mint(CHILD_TWO, tokensToMint);
338+
339+
vm.prank(CHILD_TWO);
340+
vm.expectRevert(
341+
abi.encodeWithSelector(
342+
KiddoPerks.KiddoPerks__NoValidChild.selector, CHILD_TWO
316343
)
317344
);
318345
kiddoPerks.redeemPerk(perkId);
319346
}
320347

348+
function testRevertIfRemovedChildTriesToRedeemPerk()
349+
public
350+
withPerkCreated
351+
withChildCreated
352+
{
353+
uint256 perkId = 0;
354+
uint256 childId = 0;
355+
uint256 tokensToMint = 1 * 10 ** 18;
356+
357+
vm.prank(address(kiddoPerks));
358+
kdoToken.mint(CHILD_ONE, tokensToMint);
359+
360+
vm.prank(PARENT);
361+
kiddoPerks.removeChild(childId);
362+
363+
vm.prank(CHILD_ONE);
364+
vm.expectRevert(
365+
abi.encodeWithSelector(
366+
KiddoPerks.KiddoPerks__NoValidChild.selector, CHILD_ONE
367+
)
368+
);
369+
kiddoPerks.redeemPerk(perkId);
370+
}
321371
/////////////////////
322372
//// Child test
323373
/////////////////////
374+
324375
function testRevertsIfNoParentTriesToAddChild() public withTaskCreated {
325376
string memory childName = "Willy";
326377
vm.prank(CHILD_ONE);

0 commit comments

Comments
 (0)