Skip to content

Commit 8307b30

Browse files
committed
Can mint NFT from KiddoPerks contract
1 parent 5a3382a commit 8307b30

File tree

4 files changed

+68
-14
lines changed

4 files changed

+68
-14
lines changed

packages/foundry/contracts/KiddoPerks.sol

+29-10
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ contract KiddoPerks is Ownable {
2323
error KiddoPerks__CannotCompleteRemovedTask(uint256 id);
2424
error KiddoPerks__ChildAlreadyRemoved(uint256 id);
2525
error KiddoPerks__PerkAlreadyRemoved(uint256 id);
26-
error KiddoPerks__NotEnoughTokenBalance(uint256 id, address by, uint256 tokensRequired);
26+
error KiddoPerks__NotEnoughTokenBalance(
27+
uint256 id, address by, uint256 tokensRequired
28+
);
2729
error KiddoPerks__PerkAlreadyRedeemmed(uint256 id, address by);
2830
error KiddoPerks__NoValidChild(address childAddr);
2931
error KiddoPerks__CannotMintAnyNFTYet(address who);
@@ -39,13 +41,15 @@ contract KiddoPerks is Ownable {
3941
uint256 public s_childrenNextId = 0;
4042

4143
mapping(uint256 => Perk) public s_perks;
42-
mapping(uint256 perkId => mapping(address by => bool isRedeemed)) public s_perksRedeemedBy;
44+
mapping(uint256 perkId => mapping(address by => bool isRedeemed)) public
45+
s_perksRedeemedBy;
4346
uint256 public s_perksNextId = 0;
4447

4548
mapping(uint256 => Task) public s_tasks;
4649
uint256 public s_taskNextId = 0;
4750
mapping(address => mapping(uint256 => bool)) public s_completedTasksByUser;
48-
mapping(address child => uint256 numTasksCompleted) public s_childNumTasksCompleted;
51+
mapping(address child => uint256 numTasksCompleted) public
52+
s_childNumTasksCompleted;
4953

5054
struct Task {
5155
uint256 id;
@@ -91,7 +95,10 @@ contract KiddoPerks is Ownable {
9195
/**
9296
* Tasks
9397
*/
94-
function createTask(string memory title, uint256 tokensReward) public onlyOwner {
98+
function createTask(
99+
string memory title,
100+
uint256 tokensReward
101+
) public onlyOwner {
95102
s_tasks[s_taskNextId] = Task(s_taskNextId, title, tokensReward, false);
96103
s_taskNextId++;
97104
emit TaskCreated(title);
@@ -103,7 +110,10 @@ contract KiddoPerks is Ownable {
103110
return s_tasks[id];
104111
}
105112

106-
function completeTask(uint256 taskId, address by) public onlyOwner onlyValidChild(by) {
113+
function completeTask(
114+
uint256 taskId,
115+
address by
116+
) public onlyOwner onlyValidChild(by) {
107117
if (taskId >= s_taskNextId) {
108118
revert KiddoPerks__TaskNotFound(taskId);
109119
}
@@ -134,7 +144,10 @@ contract KiddoPerks is Ownable {
134144
emit TaskRemoved(id);
135145
}
136146

137-
function isTaskCompletedBy(uint256 taskId, address by) public view returns (bool) {
147+
function isTaskCompletedBy(
148+
uint256 taskId,
149+
address by
150+
) public view returns (bool) {
138151
return s_completedTasksByUser[by][taskId];
139152
}
140153

@@ -151,7 +164,10 @@ contract KiddoPerks is Ownable {
151164
/**
152165
* Perks
153166
*/
154-
function createPerk(string memory title, uint256 tokensRequired) public onlyOwner {
167+
function createPerk(
168+
string memory title,
169+
uint256 tokensRequired
170+
) public onlyOwner {
155171
Perk memory newPerk = Perk(s_perksNextId, title, tokensRequired, false);
156172
s_perks[s_perksNextId] = newPerk;
157173
s_perksNextId++;
@@ -195,13 +211,16 @@ contract KiddoPerks is Ownable {
195211
Perk memory perk = s_perks[perkId];
196212
uint256 userTokenBalance = token.balanceOf(msg.sender);
197213
if (userTokenBalance < perk.tokensRequired) {
198-
revert KiddoPerks__NotEnoughTokenBalance(perkId, msg.sender, perk.tokensRequired);
214+
revert KiddoPerks__NotEnoughTokenBalance(
215+
perkId, msg.sender, perk.tokensRequired
216+
);
199217
}
200218
if (s_perksRedeemedBy[perkId][msg.sender]) {
201219
revert KiddoPerks__PerkAlreadyRedeemmed(perkId, msg.sender);
202220
}
203221

204-
bool sent = token.transferFrom(msg.sender, address(this), perk.tokensRequired);
222+
bool sent =
223+
token.transferFrom(msg.sender, address(this), perk.tokensRequired);
205224
if (!sent) {
206225
revert("Error on token transfer");
207226
}
@@ -258,7 +277,7 @@ contract KiddoPerks is Ownable {
258277
*/
259278
function mintNFTByTaskCompletion() public {
260279
uint256 numTaskCompletedByChild = s_childNumTasksCompleted[msg.sender];
261-
if (numTaskCompletedByChild >= MIN_TASK_COMPLETED_NFT) {
280+
if (numTaskCompletedByChild < MIN_TASK_COMPLETED_NFT) {
262281
revert KiddoPerks__CannotMintAnyNFTYet(msg.sender);
263282
}
264283
nft.mintNft(msg.sender, s_childNumTasksCompleted[msg.sender]);

packages/foundry/foundry.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
src = 'contracts'
33
out = 'out'
44
libs = ['lib']
5-
fs_permissions = [{ access = "read-write", path = "./"}]
5+
fs_permissions = [{ access = "read-write", path = "./" }]
66

77
[rpc_endpoints]
88
default_network = "http://127.0.0.1:8545"
@@ -34,7 +34,7 @@ sepolia = { key = "${ETHERSCAN_API_KEY}" }
3434

3535
[fmt]
3636
multiline_func_header = "params_first"
37-
line_length = 120
37+
line_length = 80
3838
tab_width = 2
3939
quote_style = "double"
4040
bracket_spacing = true

packages/foundry/script/DeployKiddoPerks.s.sol

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pragma solidity ^0.8.19;
33

44
import { KiddoPerks } from "../contracts/KiddoPerks.sol";
55
import { KDOToken } from "../contracts/KDOToken.sol";
6+
import { KDONft } from "../contracts/KDONft.sol";
67
import { ScaffoldETHDeploy, console } from "./DeployHelpers.s.sol";
78

89
contract DeployKiddoPerks is ScaffoldETHDeploy {
@@ -11,8 +12,9 @@ contract DeployKiddoPerks is ScaffoldETHDeploy {
1112
address PARENT = 0x27dBc64e6C38633eD526d970258372476BCE58C0;
1213

1314
KDOToken token = new KDOToken();
15+
KDONft nft = new KDONft();
1416

15-
KiddoPerks kiddoPerks = new KiddoPerks(token);
17+
KiddoPerks kiddoPerks = new KiddoPerks(token, nft);
1618
console.logString(
1719
string.concat(
1820
"KiddoPerks deployed at: ", vm.toString(address(kiddoPerks))

packages/foundry/test/KiddoPerks.t.sol

+34-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ pragma solidity ^0.8.13;
44
import { Test, console } from "forge-std/Test.sol";
55
import { KiddoPerks } from "../contracts/KiddoPerks.sol";
66
import { KDOToken } from "../contracts/KDOToken.sol";
7+
import { KDONft } from "../contracts/KDONft.sol";
78
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
89

910
contract KiddoPerksTest is Test {
1011
KiddoPerks public kiddoPerks;
1112
KDOToken public kdoToken;
13+
KDONft public kdoNft;
1214

1315
uint256 constant SMALL_REQUIRED_TOKENS_AMOUNT = 2 * 1e18;
1416

@@ -18,8 +20,9 @@ contract KiddoPerksTest is Test {
1820

1921
function setUp() public {
2022
kdoToken = new KDOToken();
23+
kdoNft = new KDONft();
2124

22-
kiddoPerks = new KiddoPerks(kdoToken);
25+
kiddoPerks = new KiddoPerks(kdoToken, kdoNft);
2326
kiddoPerks.setParent(PARENT);
2427
kdoToken.transferOwnership(address(kiddoPerks));
2528
}
@@ -516,6 +519,36 @@ contract KiddoPerksTest is Test {
516519
kiddoPerks.removeChild(childId);
517520
}
518521

522+
/**
523+
* NFTs
524+
*/
525+
function testRevertsIfTriesToMintNFTWithNoMinTasksCompletion()
526+
public
527+
withChildCreated
528+
withTaskCreated
529+
{
530+
vm.startPrank(PARENT);
531+
kiddoPerks.createTask("Clean up room", SMALL_REQUIRED_TOKENS_AMOUNT);
532+
kiddoPerks.createTask("Make bed", SMALL_REQUIRED_TOKENS_AMOUNT);
533+
kiddoPerks.createTask("Brush teeth", SMALL_REQUIRED_TOKENS_AMOUNT);
534+
kiddoPerks.createTask("Do homework", SMALL_REQUIRED_TOKENS_AMOUNT);
535+
kiddoPerks.createTask("Throw out trash", SMALL_REQUIRED_TOKENS_AMOUNT);
536+
537+
kiddoPerks.completeTask(0, CHILD_ONE);
538+
kiddoPerks.completeTask(1, CHILD_ONE);
539+
kiddoPerks.completeTask(2, CHILD_ONE);
540+
kiddoPerks.completeTask(3, CHILD_ONE);
541+
vm.stopPrank();
542+
543+
vm.prank(CHILD_ONE);
544+
vm.expectRevert(
545+
abi.encodeWithSelector(
546+
KiddoPerks.KiddoPerks__CannotMintAnyNFTYet.selector, CHILD_ONE
547+
)
548+
);
549+
kiddoPerks.mintNFTByTaskCompletion();
550+
}
551+
519552
/**
520553
* Modifiers
521554
*/

0 commit comments

Comments
 (0)