Skip to content

Conversation

@IronJam11
Copy link
Contributor

@IronJam11 IronJam11 commented Sep 20, 2025

  • Adding ID to tree struct
  • Planter token logical bug in the contract function
  • Adding fetchTreebyID functions for frontend use cases
  • getUserDetails and ping function
  • adding necessary reverts
  • adding scripts for deployment
  • Changed foundry test cases
  • Remove verification logic -> (isHidden paramater added to reduce gas fees)

Summary by CodeRabbit

  • New Features

    • NFTs now include metadata and numberOfTrees; QR field renamed to qrPhoto.
    • Multi-verifier flow: multiple verifiers per tree, self-verification blocked, verifications can be removed by tree owners.
    • Per-user profiles and verifier/token details; planter tokens minted/burned to reward verifications.
  • Refactor

    • Token model simplified to rely on care and legacy tokens; organisation image field renamed to organisationPhoto.
    • Verification and planter token handling moved to per-user and per-token tracking.
  • Chores

    • Added end-to-end deployment scripts with verification and deployment summaries.
  • Bug Fixes

    • New errors for invalid contract addresses, self-verification, missing verifications, and ownership-transfer failures.

@coderabbitai
Copy link

coderabbitai bot commented Sep 20, 2025

Walkthrough

Adds combined and single-target deployment scripts; removes VerifierToken; introduces per-user PlanterToken creation, per-token verifications, and expanded tree metadata/numberOfTrees support; updates Organisation, structs/errors, tests, PlanterToken, deployment scripts, and CI.

Changes

Cohort / File(s) Summary
Deployment: combined script
script/DeployAllContracts.s.sol
New DeployAllContractsAtOnce script: deploys CareToken and LegacyToken, deploys TreeNft(care, legacy), transfers token ownership to TreeNft, deploys OrganisationFactory, exposes public deployed addresses, runs verifyDeployment() and logs steps; reads PRIVATE_KEY.
Deployment: single-target script
script/DeployOrganisationFactory.s.sol
New DeployOrganisationFactory script: validates provided TREE_NFT_ADDRESS (reverts InvalidContractAddress() if empty), reads PRIVATE_KEY, broadcasts deployment of OrganisationFactory(treeNftAddress), logs results.
Deployment: TreeNft script update
script/DeployTreeNftContract.s.sol
Removed planter/verifier token deployments and refs; deploys TreeNft(careToken, legacyToken); updated ownership verification and logs.
Core contract: TreeNft
src/TreeNft.sol
Removed VerifierToken dependency; constructor now TreeNft(careToken, legacyToken); renamed counters (e.g., s_treeTokenCounter), added per-token verification mappings and per-user planter/verifier token tracking; mintNft extended (qrPhoto, metadata, numberOfTrees); verify creates/reuses per-verifier PlanterToken, mints planter tokens proportional to numberOfTrees; removeVerification implemented; added read helpers (getUserProfile, getUserVerifierTokenDetails).
Organisation changes
src/Organisation.sol
plantTreeProposal signature updated (qrPhoto, metadata, numberOfTrees); TreePlantingProposal struct updated; proposal creation and NFT mint paths now pass metadata and numberOfTrees.
Structs and errors
src/utils/structs.sol, src/utils/errors.sol
Added VerificationDetails and UserDetails; Tree, TreeNftVerification, and TreePlantingProposal expanded (id, qrPhoto, metadata, numberOfTrees, initiator); renamed photo fields (organisationPhoto, profilePhoto); added errors InvalidContractAddress(), CannotVerifyOwnTree(), VerificationNotFound(), OwnershipNotTransferred().
OrganisationFactory minor
src/OrganisationFactory.sol
getAllOrganisationDetails now returns OrganisationDetails using organisationPhoto field.
Token contracts
src/token-contracts/PlanterToken.sol, src/token-contracts/VerifierToken.sol
PlanterToken updated: adds planterAddress, constructor constructor(address _planter) and Ownable(msg.sender), plus getPlanterAddress() and burnFrom(); VerifierToken file/contract removed.
Tests: TreeNft
test/TreeNft.t.sol
Test contract renamed to TreeNftVerificationTest; updated imports and constants (METADATA, NUM_TREES, etc.); added public test accounts and VerificationRemoved event; tests updated for multi-verifier flows, removal, planter token balances, and new constructor/mint signatures.
Tests: Organisation & OrganisationFactory
test/Organisation.t.sol, test/OrganisationFactory.t.sol
Updated to new TreeNft constructor and mint/plant signatures; removed VerifierToken/PlanterToken direct usage and ownership assertions; renamed photo constants to organisationPhoto / photo fields; added METADATA/NUMBER_OF_TREES constants where needed.
CI
.github/workflows/test.yml
Set FOUNDRY_DISABLE_NIGHTLY_WARNING: true and switched Foundry install from nightly to stable.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev
  participant Script as DeployAllContractsAtOnce
  participant Care as CareToken
  participant Leg as LegacyToken
  participant Tree as TreeNft
  participant OrgF as OrganisationFactory

  Dev->>Script: run()
  Script->>Care: deploy CareToken(deployer)
  Script->>Leg: deploy LegacyToken(deployer)
  Script->>Tree: deploy TreeNft(address(Care), address(Leg))
  Script->>Care: transferOwnership(Tree)
  Script->>Leg: transferOwnership(Tree)
  Script->>OrgF: deploy OrganisationFactory(address(Tree))
  Script->>Tree: verifyDeployment()
  Script-->>Dev: log addresses & summary
Loading
sequenceDiagram
  autonumber
  actor Minter
  actor Verifier
  participant Tree as TreeNft
  participant PT as PlanterToken (per-verifier)

  Minter->>Tree: mintNft(..., qrPhoto, metadata, ..., numberOfTrees)
  Tree-->>Minter: tokenId

  Verifier->>Tree: verify(tokenId, proofHashes, description)
  Tree->>Tree: revert if caller is owner (CannotVerifyOwnTree)
  alt has PlanterToken for verifier
    Tree-->>PT: use existing planter token
  else
    Tree->>PT: deploy new PlanterToken(verifier)
  end
  Tree->>PT: mint planter tokens (based on numberOfTrees)
  Tree-->>Verifier: record verification

  Minter->>Tree: removeVerification(tokenId, verifier)
  Tree->>Tree: find verification or revert (VerificationNotFound)
  Tree->>PT: burn tokens if applicable
  Tree-->>Minter: emit VerificationRemoved
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • ceilican

Poem

I hopped through code, ears tall and keen,
Pruned verifier vines and made fields more green.
Metadata seeds and tokens anew,
One script plants all — a morning dew.
Rabbits cheer when tests pass through! 🐇🌱

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title “Minor bug fixes” is too generic and does not convey the substantial structural and feature changes in this pull request, such as adding tree IDs, new fetch and user detail functions, deployment scripts, removal of verification logic, and extensive test updates. It fails to highlight the primary additions and modifications implemented. Please update the title to succinctly describe the major changes, for example: “Add tree ID support, new fetchTreeByID/userDetail functions, and update verification logic,” so that it accurately reflects the PR’s scope.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
src/Organisation.sol (4)

172-174: Critical: unreachable revert makes getVerificationRequest accept invalid IDs.
Condition verificationID >= s_verificationCounter && verificationID < 0 is never true (uint can’t be < 0). Use a single upper-bound check.

Apply:

-        if (verificationID >= s_verificationCounter && verificationID < 0) revert InvalidVerificationId();
+        if (verificationID >= s_verificationCounter) revert InvalidVerificationId();

265-266: Latitude/longitude bounds are incorrect.
Latitude should be ≤ 90° and longitude ≤ 180° (scaled). Current checks allow up to 180°/360°.

Suggested fix:

-        if (_latitude > 180 * 1e6) revert InvalidCoordinates();
-        if (_longitude > 360 * 1e6) revert InvalidCoordinates();
+        if (_latitude > 90 * 1e6) revert InvalidCoordinates();
+        if (_longitude > 180 * 1e6) revert InvalidCoordinates();

Consider mirroring the same fix in TreeNft.mintNft for consistency.


246-252: Rejection threshold likely too low.
no threshold uses (owners.length - requiredVotes), which for 3 owners equals 1 — a single No can reject. Usually both approval and rejection should use requiredVotes.

Apply:

-        } else if (s_verificationNoVoters[verificationID].length >= (owners.length - requiredVotes)) {
+        } else if (s_verificationNoVoters[verificationID].length >= requiredVotes) {
             request.status = 2;
         }

398-407: Fix test mintNft argument order (geoHash / metadata swapped)

  • src/Organisation.sol: approve path forwards proposal.metadata to mintNft — calls at ~285–293 and ~398–407.
  • src/TreeNft.sol: mintNft signature expects metadata before geoHash (function at line ~69).
  • test/TreeNft.t.sol: line 405 calls mintNft(..., GEO_HASH, METADATA, ...) — change to (..., METADATA, GEO_HASH, ...) to match signature.
🧹 Nitpick comments (9)
src/utils/errors.sol (1)

4-4: Typo in docstring.

“Organisaiton” → “Organisation”.

Apply:

-/// Organisaiton Factory and Organisation
+/// Organisation Factory and Organisation
src/utils/structs.sol (1)

46-57: UserDetails duplicates User fields; consider composition to avoid drift.

Keep User as the stored struct and derive UserDetails on read paths, or embed User inside UserDetails to prevent divergence. If stored on-chain, consider narrower types for token counters to pack better.

script/DeployOrganisationFactory.s.sol (1)

31-36: Optional post-deploy verification.

Consider asserting the factory is wired to the provided TreeNFT to catch misconfiguration early.

Example:

         console.log("\n========== DEPLOYMENT SUMMARY ==========");
         console.log("OrganisationFactory Address: ", orgFactoryAddress);
         console.log("Linked TreeNFT Address:      ", treeNftAddress);
         console.log("Deployment completed successfully.");
         console.log("========================================\n");
+
+        // Quick sanity check (non-reverting, logs only)
+        // OrganisationFactory org = OrganisationFactory(orgFactoryAddress);
+        // console.log("Factory points to TreeNFT:  ", address(org.treeNftContract()));
test/Organisation.t.sol (1)

244-245: plantTreeProposal arg order looks correct; add a metadata assertion.
Consider asserting proposal.metadata to catch regressions.

Apply this diff to extend the test:

         TreePlantingProposal memory proposal = Organisation(orgAddress).getTreePlantingProposal(0);
         vm.stopPrank();

         assertEq(proposal.id, 0);
         assertEq(proposal.status, 1);
         assertEq(proposal.latitude, LATITUDE);
         assertEq(proposal.longitude, LONGITUDE);
         assertEq(proposal.species, SPECIES);
         assertEq(proposal.imageUri, IMAGE_URI);
         assertEq(proposal.qrIpfsHash, QR_IPFS_HASH);
+        assertEq(proposal.metadata, METADATA);
         assertEq(proposal.geoHash, GEOHASH);
script/DeployAllContracts.s.sol (2)

52-61: Ownership transfers logged; verify all four owners in verifyDeployment.
You only assert CareToken’s owner. Add checks for the other tokens.

Apply:

     CareToken careToken = CareToken(careTokenAddress);
     require(careToken.owner() == treeNftAddress, "CareToken ownership not transferred");
+    PlanterToken planterToken = PlanterToken(planterTokenAddress);
+    require(planterToken.owner() == treeNftAddress, "PlanterToken ownership not transferred");
+    VerifierToken verifierToken = VerifierToken(verifierTokenAddress);
+    require(verifierToken.owner() == treeNftAddress, "VerifierToken ownership not transferred");
+    LegacyToken legacy = LegacyToken(legacyTokenAddress);
+    require(legacy.owner() == treeNftAddress, "LegacyToken ownership not transferred");

62-66: Persist OrganisationFactory address if needed.
Optional: expose orgFactoryAddress as a public state var for tooling.

-    function run() external {
+    address public orgFactoryAddress;
+    function run() external {
 ...
-        address orgFactoryAddress = address(orgFactory);
+        orgFactoryAddress = address(orgFactory);
src/TreeNft.sol (3)

406-408: Redundant check in _exists.
tokenId >= 0 is always true for uint; simplify.

-    function _exists(uint256 tokenId) internal view returns (bool) {
-        return tokenId < s_tokenCounter && tokenId >= 0;
-    }
+    function _exists(uint256 tokenId) internal view returns (bool) {
+        return tokenId < s_tokenCounter;
+    }

310-347: Naming nit: visiblecount vs visibleCount.
Return variable visiblecount is lowercased; local uses visibleCount. Align names for clarity.

-        returns (TreeNftVerification[] memory verifications, uint256 totalCount, uint256 visiblecount)
+        returns (TreeNftVerification[] memory verifications, uint256 totalCount, uint256 visibleCount)

109-134: Optional: include metadata in tokenURI.
Improves discoverability on-chain wallets/UIs.

Example addition inside attributes array:

  • Add {"trait_type":"Metadata","value": tree.metadata} or embed as an external_url field if it’s an IPFS URI.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 014060c and 517f4e4.

⛔ Files ignored due to path filters (1)
  • .DS_Store is excluded by !**/.DS_Store
📒 Files selected for processing (9)
  • script/DeployAllContracts.s.sol (1 hunks)
  • script/DeployOrganisationFactory.s.sol (1 hunks)
  • script/DeployTreeNftContract.s.sol (1 hunks)
  • src/Organisation.sol (4 hunks)
  • src/TreeNft.sol (5 hunks)
  • src/utils/errors.sol (2 hunks)
  • src/utils/structs.sol (2 hunks)
  • test/Organisation.t.sol (6 hunks)
  • test/TreeNft.t.sol (22 hunks)
🔇 Additional comments (21)
src/utils/errors.sol (2)

30-30: Good addition: deploy-time contract address guard.

InvalidContractAddress() is a sensible, reusable error for script/runtime validation.


51-54: Import custom errors in deployment scripts

Deployment scripts reference custom errors from src/utils/errors.sol — ensure those scripts import them to avoid compile failures.

  • script/DeployTreeNftContract.s.sol — lines 79, 82, 85, 88: revert OwnershipNotTransferred();
  • script/DeployOrganisationFactory.s.sol — line 14: revert InvalidContractAddress();

Add an import, for example:
import { OwnershipNotTransferred, InvalidContractAddress } from "../src/utils/errors.sol";

src/utils/structs.sol (3)

68-68: Metadata field on Tree: LGTM.

Adds flexibility for per‑token metadata storage and matches test updates.


85-85: TreePlantingProposal.metadata: LGTM.

Consistent with Tree metadata propagation.


60-60: Tree.id semantics — confirmed aligned with tokenId. s_tokenIDtoTree[tokenId] is initialized with Tree(tokenId, ...) during mint (no other .id writes/usages found); getTreeDetailsbyID returns s_tokenIDtoTree[tokenId]. (src/utils/structs.sol:59-61; src/TreeNft.sol:88-90,206-211)

test/TreeNft.t.sol (2)

311-316: Event expectation + visibility filtering behavior: LGTM.

Emitting VerificationRemoved and asserting the filtered list length is 0 matches the new isHidden approach.


69-70: Fix swapped args in mintNft call (test/TreeNft.t.sol:405)

mintNft expects (…, qrIpfsHash, metadata, geoHash, …); the call at line 405 passes GEO_HASH then METADATA, swapping those fields and corrupting stored data.

-        treeNft.mintNft(LATITUDE, LONGITUDE, SPECIES, IMAGE_URI, QR_IPFS_HASH, GEO_HASH, METADATA, initialPhotos);
+        treeNft.mintNft(LATITUDE, LONGITUDE, SPECIES, IMAGE_URI, QR_IPFS_HASH, METADATA, GEO_HASH, initialPhotos);

Add assertEq(tree.metadata, METADATA) in a couple of tests and recheck the gas threshold in testGasOptimization after this fix.

Likely an incorrect or invalid review comment.

test/Organisation.t.sol (5)

44-44: Good: central METADATA test constant.
Keeps tests DRY and aligned with new signatures.


162-163: mintNft arg order updated correctly.
Order matches TreeNft.mintNft(..., qrIpfsHash, metadata, geoHash, photos).


194-196: mintNft updated here as well.
Consistent with the new metadata slot.


274-276: mintNft arg order updated consistently.
No issues.


297-299: plantTreeProposal update consistent with metadata addition.
Looks good.

src/Organisation.sol (3)

261-264: API: metadata parameter correctly introduced.
Signature change is coherent with tests and TreeNft.


279-280: Proposal now stores metadata.
Matches structs and tests.


285-295: Auto-approve: mint path forwards metadata — organisation calls updated; tests need one fix.
src/Organisation.sol call sites (lines 285, 398) now pass metadata in the correct position matching src/TreeNft.sol:mintNft. One test still passes geoHash and metadata swapped: test/TreeNft.t.sol:405 — swap those args and re-run tests.

script/DeployAllContracts.s.sol (1)

12-18: State captures for deployed addresses are helpful.
Good for post-run inspection.

src/TreeNft.sol (5)

75-78: API: metadata added to mintNft.
Matches tests and Organisation flow.


89-104: Tree now stores id and metadata.
Initialization order is correct; id == tokenId maintained.


374-390: User profile aggregation looks correct.
Balances and counters are assembled as expected; revert on unregistered is fine.


410-412: ping utility is fine.
Simple liveness check.


1-414: No duplicate getUserProfile declaration found — single definition
Single declaration at src/TreeNft.sol:374 (function getUserProfile). No other declarations found repo-wide.

Comment on lines +14 to +15
if (treeNftAddress.code.length <= 0) revert InvalidContractAddress();

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing import for InvalidContractAddress(); script won’t compile.

Add the errors import.

Apply:

 import "../src/OrganisationFactory.sol";
+import "../src/utils/errors.sol";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (treeNftAddress.code.length <= 0) revert InvalidContractAddress();
import "../src/OrganisationFactory.sol";
import "../src/utils/errors.sol";
🤖 Prompt for AI Agents
In script/DeployOrganisationFactory.s.sol around lines 14-15, the revert
InvalidContractAddress() is used but the error type is not imported so the
script will not compile; add an import for the InvalidContractAddress error from
your project's errors file (e.g., errors.sol) at the top of the solidity script,
ensuring the import path is correct for the repository structure, then recompile
to confirm the symbol is resolved.

Comment on lines 79 to 89
if (careToken.owner() != treeNftAddress) revert OwnershipNotTransferred();

PlanterToken planterToken = PlanterToken(planterTokenAddress);
if (planterToken.owner() != treeNftAddress) revert OwnershipNotTransferred();

VerifierToken verifierToken = VerifierToken(verifierTokenAddress);
if (verifierToken.owner() != treeNftAddress) revert OwnershipNotTransferred();

LegacyToken legacyToken = LegacyToken(legacyTokenAddress);
if (legacyToken.owner() != treeNftAddress) revert OwnershipNotTransferred();

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing import for custom error causes compilation failure.

OwnershipNotTransferred() is undeclared in this source unit.

Apply:

 import "../src/token-contracts/LegacyToken.sol";
+import "../src/utils/errors.sol";

Optional: stop broadcasting before view-only verification to avoid accidental txs during checks.

-        console.log("========================\n");
-        verifyDeployment();
+        console.log("========================\n");
+        vm.stopBroadcast();
+        verifyDeployment();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (careToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
PlanterToken planterToken = PlanterToken(planterTokenAddress);
if (planterToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
VerifierToken verifierToken = VerifierToken(verifierTokenAddress);
if (verifierToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
LegacyToken legacyToken = LegacyToken(legacyTokenAddress);
if (legacyToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
// --- add to imports (near other imports) ---
import "../src/token-contracts/LegacyToken.sol";
import "../src/utils/errors.sol";
// --- existing ownership checks (unchanged) ---
if (careToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
PlanterToken planterToken = PlanterToken(planterTokenAddress);
if (planterToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
VerifierToken verifierToken = VerifierToken(verifierTokenAddress);
if (verifierToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
LegacyToken legacyToken = LegacyToken(legacyTokenAddress);
if (legacyToken.owner() != treeNftAddress) revert OwnershipNotTransferred();
// --- replace before verification ---
console.log("========================\n");
vm.stopBroadcast();
verifyDeployment();
🤖 Prompt for AI Agents
In script/DeployTreeNftContract.s.sol around lines 79-89, the custom error
OwnershipNotTransferred() is not declared or imported causing compilation
failures; fix by either importing the contract/file that declares this error at
the top of the Solidity file or add a local declaration `error
OwnershipNotTransferred();` in this source unit, then keep the ownership checks
as-is; optionally, to avoid accidental transactions during view-only
verification, call vm.stopBroadcast() (or the appropriate stopBroadcast function
from the foundry runtime) before performing those read-only owner checks.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/TreeNft.sol (2)

233-235: Mint full ERC20 units when rewarding planters.

planterToken.mint(..., tree.numberOfTrees) still mints raw integers, i.e., base units (1 = 1e‑18 tokens with 18 decimals). Planters effectively receive zero whole tokens. Multiply by 10 ** uint256(planterToken.decimals()) (or 1e18) before minting so rewards match the intended tree count.


239-255: Make removal actually revoke verification state.

Hiding the record leaves s_tokenIDtoUserVerification[_tokenId][verifier] true and s_verifierToTokenIDs untouched, so isVerified gates never unlock and revoked verifications still surface in listings. Clear the boolean flag (and prune token ID lists or filter them on read) when marking hidden so removal has effect.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 517f4e4 and 2be0cb3.

📒 Files selected for processing (4)
  • src/TreeNft.sol (5 hunks)
  • src/token-contracts/PlanterToken.sol (1 hunks)
  • src/utils/errors.sol (2 hunks)
  • src/utils/structs.sol (3 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
src/utils/structs.sol

[error] 21-25: Code formatting differences detected by forge fmt --check in struct definitions (verifierPlanterTokenAddress field). Ensure alignment and spacing as per project style.

src/TreeNft.sol

[error] 46-50: Constructor formatting and inheritance formatting differences detected by forge fmt --check in TreeNft.sol. Apply consistent formatting.

src/token-contracts/PlanterToken.sol

[error] 6-12: Code formatting differences detected by forge fmt --check in PlanterToken.sol. Ensure consistent spacing and indentation.

src/TreeNft.sol Outdated
Comment on lines 398 to 414
function getUserVerifierTokenDetails(address userAddress) public view returns (VerificationDetails[] memory verifierTokenDetails) {
// This function returns the verifier token address of the user

TreeNftVerification[] memory userVerifications = s_userToVerifications[userAddress];
for(uint i = 0; i < userVerifications.length; i++) {
PlanterToken planterToken = PlanterToken(userVerifications[i].verifierPlanterTokenAddress);
verifierTokenDetails[i] = VerificationDetails({
verifier: userVerifications[i].verifier,
timestamp: userVerifications[i].timestamp,
proofHashes: userVerifications[i].proofHashes,
description: userVerifications[i].description,
isHidden: userVerifications[i].isHidden,
numberOfTrees: planterToken.balanceOf(userAddress),
verifierPlanterTokenAddress: userVerifications[i].verifierPlanterTokenAddress
});
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix array initialisation and token accounting.

verifierTokenDetails[i] = … writes into an uninitialised memory array, causing every call to revert. Instantiate it first:

verifierTokenDetails = new VerificationDetails[](userVerifications.length);

Additionally, you query planterToken.balanceOf(userAddress) even though verify() mints to the tree owner (ownerOf(_tokenId)), so the returned balances are always zero for the verifier. Please fetch balances for the actual recipient (or adjust minting) to report meaningful numbers.

🤖 Prompt for AI Agents
In src/TreeNft.sol around lines 398 to 414, the function writes into an
uninitialised memory array and reports wrong token balances; initialize
verifierTokenDetails with new VerificationDetails[](userVerifications.length)
before the loop, and for numberOfTrees query the planter token balance of the
actual mint recipient (not the verifier): fetch the recipient (e.g.,
ownerOf(userVerifications[i].tokenId) if tokenId is stored on the verification,
or use whatever recipient address the verify() call mints to) and call
planterToken.balanceOf(recipient); alternatively modify the verification data to
store the recipient at verification time and use that stored address for the
balance lookup.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
script/DeployTreeNftContract.s.sol (1)

4-64: Fix missing import for OwnershipNotTransferred.

OwnershipNotTransferred() is referenced but never declared in this compilation unit, so the script fails to compile. Import the custom error definition from src/utils/errors.sol (or declare it locally) before using it.

 import "../src/token-contracts/LegacyToken.sol";
+import "../src/utils/errors.sol";
♻️ Duplicate comments (3)
src/TreeNft.sol (3)

207-239: Verify function implements comprehensive validation and token minting.

The updated verify() function includes:

  • Self-verification prevention (line 213)
  • Dynamic PlanterToken creation for new verifiers (lines 218-221)
  • Token minting to tree owner based on numberOfTrees (line 235)
  • Proper state updates across multiple mappings

However, there's a critical issue with the token amount being minted.

Token minting uses raw numberOfTrees without accounting for ERC20 decimals.

Line 235 mints tree.numberOfTrees directly, which represents the number of base units (1e-18 tokens per unit if using 18 decimals). If the intent is to mint whole tokens, this should be multiplied by 10**planterToken.decimals().

Apply this diff if the intent is to mint whole tokens:

-            planterToken.mint(ownerOf(_tokenId), tree.numberOfTrees);
+            planterToken.mint(ownerOf(_tokenId), tree.numberOfTrees * 10**planterToken.decimals());

Based on learnings from past review comments.


445-465: Critical: Uninitialized array causes revert.

The function writes to verifierTokenDetails[i] without first initializing the array, which will cause every call to revert.

Initialize the array before the loop:

     function getUserVerifierTokenDetails(address userAddress)
         public
         view
         returns (VerificationDetails[] memory verifierTokenDetails)
     {
         // This function returns the verifier token address of the user
 
         TreeNftVerification[] memory userVerifications = s_userToVerifications[userAddress];
+        verifierTokenDetails = new VerificationDetails[](userVerifications.length);
         for (uint256 i = 0; i < userVerifications.length; i++) {

Additionally, Line 461 queries planterToken.balanceOf(userAddress) but the tokens were minted to the tree owner (line 235 in verify()), not the verifier. This will return zero for most queries.

To fix the balance lookup, fetch the tree owner's balance:

-                numberOfTrees: planterToken.balanceOf(userAddress),
+                numberOfTrees: planterToken.balanceOf(ownerOf(userVerifications[i].tokenId)),

Based on learnings from past review comments.


487-489: Remove test artifact function.

The ping() function appears to be a test artifact and should be removed from production code as it serves no functional purpose.

Based on learnings from past review comment by Zahnentferner.

Remove the function:

-    function ping() public pure returns (string memory) {
-        return "pong";
-    }
🧹 Nitpick comments (2)
script/DeployAllContracts.s.sol (1)

75-79: Use the correct contract type for legacyToken.

legacyToken is instantiated as CareToken, which is misleading and fragile; if the interfaces ever diverge this breaks verification. Instantiate it as LegacyToken instead.

-        CareToken legacyToken = CareToken(legacyTokenAddress);
+        LegacyToken legacyToken = LegacyToken(legacyTokenAddress);
src/TreeNft.sol (1)

483-485: Redundant check in _exists function.

Line 484 includes tokenId >= 0 which is always true for uint256 types since they cannot be negative.

Simplify to:

     function _exists(uint256 tokenId) internal view returns (bool) {
-        return tokenId < s_treeTokenCounter && tokenId >= 0;
+        return tokenId < s_treeTokenCounter;
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2be0cb3 and d096df0.

📒 Files selected for processing (11)
  • script/DeployAllContracts.s.sol (1 hunks)
  • script/DeployTreeNftContract.s.sol (2 hunks)
  • src/Organisation.sol (4 hunks)
  • src/TreeNft.sol (9 hunks)
  • src/token-contracts/PlanterToken.sol (1 hunks)
  • src/token-contracts/VerifierToken.sol (0 hunks)
  • src/utils/errors.sol (2 hunks)
  • src/utils/structs.sol (3 hunks)
  • test/Organisation.t.sol (6 hunks)
  • test/OrganisationFactory.t.sol (1 hunks)
  • test/TreeNft.t.sol (1 hunks)
💤 Files with no reviewable changes (1)
  • src/token-contracts/VerifierToken.sol
🧰 Additional context used
🪛 GitHub Actions: CI
test/Organisation.t.sol

[error] 237-243: forge fmt --check reported formatting changes. The diff shows formatting adjustments to the plantTreeProposal call. Run 'forge fmt' to auto-format or fix manually.


[error] 295-299: forge fmt --check reported formatting changes. The diff shows formatting adjustments to the plantTreeProposal call. Run 'forge fmt' to auto-format or fix manually.

🔇 Additional comments (10)
test/TreeNft.t.sol (6)

4-4: Import path updated for Foundry standard.

The import path has been updated to ../lib/forge-std/src/Test.sol, which is the correct path for Foundry's standard library when installed as a git submodule in the lib directory.


12-42: Test contract properly structured for verification flow testing.

The contract has been renamed to TreeNftVerificationTest and includes appropriate test fixtures with public addresses for planter and verifiers, the VerificationRemoved event declaration for testing, and well-organized test constants. This provides a solid foundation for comprehensive verification testing.


44-90: Core verification flow tests are well-implemented.

The tests properly validate:

  • Basic verification with token minting (lines 44-60)
  • Self-verification prevention (lines 62-73)
  • Double verification prevention (lines 75-89)

All tests correctly use vm.prank, expect appropriate reverts, and verify state changes.


91-174: Multi-verifier and removal tests provide comprehensive coverage.

The test suite thoroughly validates:

  • Multiple verifiers can verify the same tree (lines 91-115)
  • Verification removal cleans up state correctly (lines 117-140)
  • Removal properly updates verification counts and arrays (lines 142-174)

These tests ensure the verification system maintains consistency across complex scenarios.


176-290: Edge case and security tests are thorough.

The test coverage includes:

  • Token burning on verification removal (lines 176-195)
  • Array cleanup when removing verifications (lines 197-222)
  • Handling non-existent verification removal (lines 224-233)
  • Event emission verification (lines 235-249)
  • Insufficient token balance scenarios (lines 251-274)
  • Ownership requirements for removal (lines 276-290)

This comprehensive edge case testing ensures robust functionality.


292-486: Query and state management tests validate data integrity.

The remaining tests properly validate:

  • Verifier retrieval functions (lines 292-337)
  • Revocation counter increments (lines 339-358)
  • Invalid tree ID handling (lines 360-366)
  • PlanterToken lifecycle (lines 368-384)
  • Complex multi-tree scenarios (lines 386-486)

These tests ensure data structures remain consistent through various operations.

src/TreeNft.sol (4)

45-57: Constructor signature updated to accept only core tokens.

The constructor now takes only _careTokenContract and _legacyTokenContract addresses, removing dependencies on VerifierToken and PlanterToken. PlanterTokens are now created dynamically per verifier during the first verification.


61-101: mintNft extended with metadata and numberOfTrees parameters.

The function now accepts metadata and numberOfTrees parameters, which are stored in the Tree struct. The numberOfTrees field is later used to determine how many planter tokens to mint during verification.

Ensure that numberOfTrees is properly validated in upstream code or UI to prevent minting excessive tokens. Consider adding a reasonable upper bound check to prevent abuse.


427-443: getUserProfile function properly retrieves user details.

The function validates user existence and returns comprehensive user details including token balances. The implementation correctly maps stored User data to the UserDetails return struct.


241-297: removeVerification now correctly clears the verification flag
The mapping s_tokenIDtoUserVerification[tokenId][verifier] is set to false at line 251, so isVerified(tokenId, verifier) will return false after removal.

@IronJam11 IronJam11 force-pushed the minorBugFixes branch 3 times, most recently from 0425b0b to 9c45baf Compare October 11, 2025 14:13
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/TreeNft.sol (1)

207-239: Ensure consistent decimal precision in burn operation. In src/TreeNft.sol line 281, burnFrom is called with tree.numberOfTrees (missing * 1e18), causing a units mismatch. Update to planterToken.burnFrom(treeOwner, tree.numberOfTrees * 1e18).

♻️ Duplicate comments (1)
src/TreeNft.sol (1)

445-465: Critical: Fix uninitialized array in getUserVerifierTokenDetails.

The function writes to verifierTokenDetails[i] without initializing the array, which will cause every call to revert. This matches the issue flagged in past review comments.

Apply this diff to initialize the array:

     function getUserVerifierTokenDetails(address userAddress)
         public
         view
         returns (VerificationDetails[] memory verifierTokenDetails)
     {
         // This function returns the verifier token address of the user
 
         TreeNftVerification[] memory userVerifications = s_userToVerifications[userAddress];
+        verifierTokenDetails = new VerificationDetails[](userVerifications.length);
         for (uint256 i = 0; i < userVerifications.length; i++) {
             PlanterToken planterToken = PlanterToken(userVerifications[i].verifierPlanterTokenAddress);
             verifierTokenDetails[i] = VerificationDetails({
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7080fab and 9c45baf.

📒 Files selected for processing (7)
  • .github/workflows/test.yml (2 hunks)
  • src/Organisation.sol (4 hunks)
  • src/OrganisationFactory.sol (2 hunks)
  • src/TreeNft.sol (8 hunks)
  • src/utils/structs.sol (4 hunks)
  • test/Organisation.t.sol (8 hunks)
  • test/OrganisationFactory.t.sol (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-26T10:22:04.651Z
Learnt from: ceilican
PR: StabilityNexus/Treee-Solidity#4
File: src/Organisation.sol:4-4
Timestamp: 2025-05-26T10:22:04.651Z
Learning: The Organisation contract in src/Organisation.sol uses a multi-owner design pattern with `address[] public owners` and custom ownership checking, which is incompatible with OpenZeppelin's single-owner Ownable contract. The multi-owner system is required for voting mechanisms on verification requests.

Applied to files:

  • src/utils/structs.sol
🔇 Additional comments (17)
.github/workflows/test.yml (1)

10-10: Stable toolchain switch looks good.

Disabling the nightly warning and pinning to the stable toolchain keeps CI noise-free while tracking the latest stable forge release. 👍

Also applies to: 27-27

src/OrganisationFactory.sol (1)

113-113: LGTM! Field rename is consistent.

The rename from photoIpfsHash to organisationPhoto aligns with the updated OrganisationDetails struct definition and maintains consistency across success and error paths.

Also applies to: 126-126

test/Organisation.t.sol (2)

155-157: LGTM! mintNft calls updated with new parameters.

The test calls to mintNft now correctly include QR_HASH, METADATA, and NUMBER_OF_TREES parameters, aligning with the extended function signature.

Also applies to: 189-191, 271-273


240-242: LGTM! plantTreeProposal calls updated with new parameters.

The test calls to plantTreeProposal now correctly include METADATA and NUMBER_OF_TREES parameters, matching the extended function signature.

Also applies to: 295-297

src/utils/structs.sol (4)

8-8: LGTM! Field renames improve clarity.

The renaming of photo-related fields (photoIpfsHashorganisationPhoto, profilePhotoIpfsprofilePhoto, qrIpfsHashqrPhoto) makes the codebase more flexible and not tied to IPFS storage, allowing for different storage solutions.

Also applies to: 50-50, 76-76, 92-92


27-35: LGTM! New VerificationDetails struct supports enhanced verification flow.

The new VerificationDetails struct appropriately captures verification metadata including the verifier's planter token address and number of trees, supporting the per-user token management feature.


57-66: LGTM! UserDetails struct provides comprehensive user information.

The new UserDetails struct consolidates user profile data with token balances, providing a complete view of user information in a single query.


69-69: LGTM! Tree struct enhancements support expanded metadata.

The additions of id, metadata, and numberOfTrees fields to the Tree struct enable richer tree data tracking and align with the enhanced minting flow.

Also applies to: 77-77, 83-83

src/Organisation.sol (3)

260-264: LGTM! Function signature extended to support enhanced tree metadata.

The plantTreeProposal function now correctly accepts _qrPhoto, _metadata, and numberOfTrees parameters, aligning with the enhanced tree data model.


276-281: LGTM! Proposal initialization updated with new fields.

The TreePlantingProposal struct is properly initialized with the new qrPhoto, metadata, and numberOfTrees fields.


287-297: LGTM! mintNft calls consistently updated.

Both calls to mintNft (on proposal creation with ≤2 owners and on voting approval) correctly pass all new parameters including qrPhoto, metadata, and numberOfTrees.

Also applies to: 401-411

src/TreeNft.sol (6)

45-57: LGTM! Constructor simplified to remove token contract dependencies.

The TreeNft constructor now only accepts careToken and legacyToken addresses, removing the dependency on pre-deployed PlanterToken and VerifierToken contracts. This aligns with the new per-user planter token creation pattern.


61-101: LGTM! mintNft function extended with enhanced metadata.

The function signature and Tree struct initialization correctly incorporate the new qrPhoto, metadata, and numberOfTrees parameters. The tree ID is properly set from s_treeTokenCounter before incrementing.


213-213: LGTM! Self-verification check prevents gaming the system.

The addition of if (msg.sender == treeOwner) revert CannotVerifyOwnTree(); prevents tree owners from verifying their own trees, which is essential to maintain verification integrity.


218-223: LGTM! Per-user planter token pattern improves scalability.

Creating a unique PlanterToken contract per verifier (lines 218-223) allows independent token management and prevents conflicts. The pattern of checking if a user's planter token exists before creating a new one is correct.


427-443: LGTM! getUserProfile provides comprehensive user information.

The function correctly retrieves user details from storage and enriches them with token balances from the CareToken and LegacyToken contracts.


410-410: LGTM! Legacy token minting uses correct decimal precision.

Line 410 correctly mints legacy tokens with 1 * 1e18 to account for 18 decimals.

Comment on lines +52 to 56
treeNft = new TreeNft(address(careToken), address(legacyToken));

careToken.transferOwnership(address(treeNft));
planterToken.transferOwnership(address(treeNft));
verifierToken.transferOwnership(address(treeNft));
legacyToken.transferOwnership(address(treeNft));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove obsolete PlanterToken ownership transfer.

The TreeNft constructor no longer accepts planterToken as a parameter (line 52), but line 55 still attempts to transfer its ownership to TreeNft. This call will succeed but serves no purpose since TreeNft doesn't manage this token anymore.

Apply this diff to remove the obsolete ownership transfer:

         careToken = new CareToken(owner);
         planterToken = new PlanterToken(owner);
         legacyToken = new LegacyToken(owner);
 
         treeNft = new TreeNft(address(careToken), address(legacyToken));
 
         careToken.transferOwnership(address(treeNft));
-        planterToken.transferOwnership(address(treeNft));
         legacyToken.transferOwnership(address(treeNft));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
treeNft = new TreeNft(address(careToken), address(legacyToken));
careToken.transferOwnership(address(treeNft));
planterToken.transferOwnership(address(treeNft));
verifierToken.transferOwnership(address(treeNft));
legacyToken.transferOwnership(address(treeNft));
careToken = new CareToken(owner);
planterToken = new PlanterToken(owner);
legacyToken = new LegacyToken(owner);
treeNft = new TreeNft(address(careToken), address(legacyToken));
careToken.transferOwnership(address(treeNft));
legacyToken.transferOwnership(address(treeNft));
🤖 Prompt for AI Agents
In test/Organisation.t.sol around lines 52 to 56, the test still transfers
ownership of planterToken to TreeNft even though the TreeNft constructor no
longer accepts or manages planterToken; remove the obsolete
planterToken.transferOwnership(address(treeNft)); call so only relevant tokens
(careToken and legacyToken) have their ownership transferred to the TreeNft
instance.

legacyToken = new LegacyToken(owner);

treeNft = new TreeNft(address(careToken), address(planterToken), address(verifierToken), address(legacyToken));
treeNft = new TreeNft(address(careToken), address(legacyToken));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify TreeNft contract interaction with CareToken and LegacyToken.

The TreeNft constructor now only accepts careToken and legacyToken addresses. Ensure that all TreeNft functionality that previously relied on PlanterToken or VerifierToken has been properly refactored.

Run the following script to verify TreeNft no longer references the removed token contracts:


🏁 Script executed:

#!/bin/bash
# Description: Verify that TreeNft.sol does not reference VerifierToken

# Check for any remaining VerifierToken references
rg -n "VerifierToken" --type sol --glob '!*test*'

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Description: Verify that no Solidity contracts reference VerifierToken or PlanterToken
rg -nP "(VerifierToken|PlanterToken)" -g '*.sol' --glob '!*test*'

Length of output: 1983


Refactor TreeNft.sol to remove PlanterToken/VerifierToken references.
TreeNft.sol still imports PlanterToken (line 17) and retains mappings and logic for planter/verifier tokens (lines 34–35, 218–223, 236, 276–282, 445–462). Eliminate or update these remnants to match the new constructor signature.

🤖 Prompt for AI Agents
In test/OrganisationFactory.t.sol around line 42, TreeNft is being instantiated
using the old constructor that expects PlanterToken/VerifierToken; refactor
TreeNft.sol to remove the PlanterToken import and all planter/verifier-related
state and logic (mappings at lines ~34–35, functions and logic at ~218–223, 236,
276–282, 445–462) so the contract matches the new constructor signature, then
update the test to instantiate TreeNft with the new constructor parameters
(remove passing PlanterToken/VerifierToken addresses and any tests that rely on
the removed mappings or functions). Ensure all imports, state variables,
modifiers, and tests referencing PlanterToken/VerifierToken are deleted or
adapted to the new design.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/utils/structs.sol (1)

27-35: Consider documenting the distinction between VerificationDetails and TreeNftVerification.

Both structs share similar fields but serve different purposes:

  • VerificationDetails includes numberOfTrees (aggregate verification data)
  • TreeNftVerification includes treeNftId (per-NFT verification data)

To reduce confusion, consider adding inline comments explaining when each struct should be used.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e7d659 and 2be49a8.

📒 Files selected for processing (2)
  • src/Organisation.sol (4 hunks)
  • src/utils/structs.sol (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-26T10:22:04.651Z
Learnt from: ceilican
PR: StabilityNexus/Treee-Solidity#4
File: src/Organisation.sol:4-4
Timestamp: 2025-05-26T10:22:04.651Z
Learning: The Organisation contract in src/Organisation.sol uses a multi-owner design pattern with `address[] public owners` and custom ownership checking, which is incompatible with OpenZeppelin's single-owner Ownable contract. The multi-owner system is required for voting mechanisms on verification requests.

Applied to files:

  • src/utils/structs.sol
🔇 Additional comments (10)
src/utils/structs.sol (7)

8-8: LGTM: Consistent naming improvement.

The field rename from photoIpfsHash to organisationPhoto improves consistency with other photo field names in the codebase.


24-24: LGTM: Tracking verifier planter token address.

The addition of verifierPlanterTokenAddress enables linking verifications to specific planter tokens, which aligns with the per-user PlanterToken architecture mentioned in the PR objectives.


50-50: LGTM: Consistent naming improvement.

The field rename from profilePhotoIpfs to profilePhoto aligns with the naming convention used in organisationPhoto.


57-66: LGTM: Extended user profile for frontend.

The new UserDetails struct appropriately extends User with token balance fields (legacyTokens and careTokens) for frontend display purposes, as mentioned in the PR objectives.


76-77: LGTM: Enhanced tree metadata and batch support.

The additions of qrPhoto (renamed from qrIpfsHash), metadata, and numberOfTrees fields enable:

  1. Consistent photo field naming
  2. Rich metadata storage for NFTs
  3. Support for batch tree planting scenarios

These changes align well with the PR objectives to support frontend use cases and reduce gas fees.

Also applies to: 83-83


92-92: LGTM: Proposal struct enhanced with metadata and initiator tracking.

The changes properly extend TreePlantingProposal with:

  1. qrPhoto (renamed from qrIpfsHash) for consistency
  2. metadata for rich proposal context
  3. numberOfTrees for batch proposals
  4. initiator for tracking proposal origin

All fields are correctly initialized in Organisation.sol (lines 270-283).

Also applies to: 95-95, 97-98


69-69: Tree.id is initialized correctly
mintNft passes tokenId as the first argument to Tree, so the id field is properly set.

src/Organisation.sol (3)

260-264: LGTM: Function signature properly updated.

The plantTreeProposal signature correctly incorporates:

  1. _qrPhoto (replacing _qrIpfshash) for consistent naming
  2. _metadata for rich proposal context
  3. numberOfTrees for batch planting support

All parameters have proper memory qualifiers.


270-283: LGTM: All new struct fields properly initialized.

The TreePlantingProposal construction correctly initializes:

  1. qrPhoto with _qrPhoto parameter
  2. metadata with _metadata parameter
  3. status with 0 (pending state)
  4. numberOfTrees with function parameter
  5. initiator with msg.sender for proper tracking

288-298: TreeNft.mintNft signature matches updated parameters; no changes required.

if (planterToken.balanceOf(treeOwner) >= tokensToReturn) {
planterToken.burnFrom(treeOwner, tokensToReturn);
address[] storage verifierTokenAddrs = s_userToVerifierTokenAddresses[treeOwner];
for (uint256 j = 0; j < verifierTokenAddrs.length; j++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this for loop become too expensive?


TreeNftVerification[] memory userVerifications = s_userToVerifications[userAddress];
for(uint i = 0; i < userVerifications.length; i++) {
for (uint256 i = 0; i < userVerifications.length; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this for loop become too expensive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, i will write a paginated view function.

uint256 private s_deathCounter;
uint256 private s_treeNftVerification;
uint256 private s_userCounter;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are some of the imports above still used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes sir - for mappings majorly

string description;
bool isHidden;
uint256 treeNftId;
address verifierPlanterTokenAddress;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this address?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the unique planter token contract address of very every planter

address[] ancestors;
uint256 lastCareTimestamp;
uint256 careCount;
uint256 numberOfTrees;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memtioned on discord

@Zahnentferner Zahnentferner merged commit 41e9f4d into StabilityNexus:main Oct 16, 2025
2 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants