Mini-DIT: Experimental Decentralized Identity Token Prototype with Foundry Tests#6
Mini-DIT: Experimental Decentralized Identity Token Prototype with Foundry Tests#6VivekLatpate wants to merge 12 commits intoStabilityNexus:mainfrom
Conversation
Updated README to reflect the Mini-DIT prototype details and goals.
Mini dit prototype
Mini dit prototype
Add minimal GitHub Actions permissions and fix CI
📝 WalkthroughWalkthroughThis PR establishes a Foundry-based smart contract project featuring a Decentralized Identity Tokens (MiniDIT) system. Changes include CI/CD workflow configuration, foundry setup, two smart contracts (Counter as a basic example and MiniDIT as an ERC721-based identity system with endorsement mechanics), corresponding test suites, updated documentation, and git submodule dependencies. Changes
Sequence Diagram(s)sequenceDiagram
actor Alice as Alice (Caller 1)
participant MiniDIT
actor Bob as Bob (Caller 2)
Alice->>MiniDIT: mintIdentity("alice.json")
MiniDIT->>MiniDIT: nextTokenId = 1, identities[1] = Identity(...)
MiniDIT->>Alice: ERC721 mint token `#1`
Bob->>MiniDIT: mintIdentity("bob.json")
MiniDIT->>MiniDIT: nextTokenId = 2, identities[2] = Identity(...)
MiniDIT->>Bob: ERC721 mint token `#2`
Alice->>MiniDIT: endorse(tokenId=1, toTokenId=2, tag="trusted")
MiniDIT->>MiniDIT: Validate: token 2 exists, token 1 not compromised
MiniDIT->>MiniDIT: endorsements[2].push(Endorsement(1, "trusted", false))
MiniDIT->>Alice: emit Endorsed event
Alice->>MiniDIT: revokeEndorsement(toTokenId=2, index=0)
MiniDIT->>MiniDIT: endorsements[2][0].revoked = true
MiniDIT->>Alice: emit EndorsementRevoked event
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@README.md`:
- Around line 72-114: README.md has an unclosed code block and leftover git
instructions causing formatting to break; fix by closing the opening
triple-backtick after the initial git checkout (re-insert ```bash around the
"Install dependencies:" section and add matching ``` before "forge install" and
around the "forge test" example), remove the accidental commit/push lines at the
bottom, add proper Markdown headings (e.g., "## 🧪 Run Tests", "## 🔍 Smart
Contract Overview", "## 🧠 Research Context"), and replace the bulleted function
list with a table documenting mintIdentity(string metadataURI),
endorse(fromTokenId, toTokenId, tag), revokeEndorsement(toTokenId, index), and
markCompromised(tokenId) so the README renders correctly.
In `@src/MiniDIT.sol`:
- Around line 46-63: The endorse function currently allows self-endorsement; add
a check in endorse to require(fromTokenId != toTokenId, "Cannot self-endorse")
(or similar) immediately after the ownerOf(fromTokenId) check so that an
identity cannot endorse itself; this touches the endorse function and prevents
pushing Endorsement(fromTokenId, tag, false) into endorsements[toTokenId] when
fromTokenId equals toTokenId.
🧹 Nitpick comments (6)
.github/workflows/test.yml (2)
26-29: UsingnightlyFoundry version may cause flaky CI.Nightly builds can introduce breaking changes or regressions that fail your CI unexpectedly. Consider pinning to a stable release for reproducibility:
♻️ Suggested change
- name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable
3-6: Consider restricting trigger branches to avoid unnecessary CI runs.Without branch filters, CI runs on every push to every branch. For typical workflows:
♻️ Optional: Add branch filters
on: push: + branches: + - main pull_request: workflow_dispatch:src/MiniDIT.sol (2)
31-37: Consider reordering for clearer checks-effects-interactions pattern.
_safeMintcan trigger a callback to the recipient if it's a contract. While the current code is safe (tokenId is captured before the call), settingidentities[tokenId]before_safeMintwould follow the CEI pattern more explicitly.♻️ Optional reorder
function mintIdentity(string calldata metadataURI) external { uint256 tokenId = nextTokenId++; + identities[tokenId] = Identity(metadataURI, false); _safeMint(msg.sender, tokenId); - identities[tokenId] = Identity(metadataURI, false); emit IdentityMinted(msg.sender, tokenId); }
65-71: Consider adding idempotency check for revocation.The function allows revoking an already-revoked endorsement, which emits a misleading
EndorsementRevokedevent. Adding a check prevents redundant event emissions.♻️ Optional improvement
function revokeEndorsement(uint256 toTokenId, uint256 index) external { Endorsement storage e = endorsements[toTokenId][index]; require(ownerOf(e.fromTokenId) == msg.sender, "Not endorser"); + require(!e.revoked, "Already revoked"); e.revoked = true; emit EndorsementRevoked(e.fromTokenId, toTokenId); }test/MiniDIT.t.sol (2)
24-37: Assert thetagfield for complete coverage.The test skips asserting the
tagvalue. Consider adding an assertion to verify the endorsement tag is stored correctly.✅ Proposed improvement
- (uint256 fromToken,, bool revoked) = dit.endorsements(1,0); + (uint256 fromToken, string memory tag, bool revoked) = dit.endorsements(1,0); assertEq(fromToken, 0); + assertEq(tag, "worked-with"); assertFalse(revoked);
56-65: Add test for compromised identity endorsement rejection.The contract blocks compromised identities from issuing endorsements (a key security feature), but there's no test verifying this behavior.
✅ Proposed test addition
function testCompromisedCannotEndorse() public { vm.prank(alice); dit.mintIdentity("ipfs://alice"); vm.prank(bob); dit.mintIdentity("ipfs://bob"); vm.prank(alice); dit.markCompromised(0); vm.prank(alice); vm.expectRevert("From identity compromised"); dit.endorse(0, 1, "worked-with"); }
| ```bash | ||
| npm run dev | ||
| # or | ||
| yarn dev | ||
| # or | ||
| pnpm dev | ||
| ``` | ||
| git clone https://github.com/<your-username>/IdentityTokens-EVM-Contracts.git | ||
| cd IdentityTokens-EVM-Contracts | ||
| git checkout mini-dit-prototype | ||
| Install dependencies: | ||
|
|
||
| #### 4. Open your Browser | ||
| forge install | ||
| 🧪 Run Tests | ||
| forge test | ||
| Expected output: | ||
|
|
||
| Navigate to [http://localhost:3000](http://localhost:3000) to see the application. | ||
| All MiniDIT tests passing | ||
| 🔍 Smart Contract Overview | ||
| Mint Identity NFT | ||
| mintIdentity(string metadataURI) | ||
| Endorse Another Identity | ||
| endorse(fromTokenId, toTokenId, tag) | ||
| Revoke Endorsement | ||
| revokeEndorsement(toTokenId, index) | ||
| Mark Identity as Compromised | ||
| markCompromised(tokenId) | ||
| 🧠 Research Context | ||
| This prototype is based on ongoing discussions around: | ||
|
|
||
| --- | ||
| DIT (Decentralized Identity Tokens) | ||
|
|
||
| ## Contributing | ||
| TNT (Trust Network Tokens) | ||
|
|
||
| We welcome contributions of all kinds! To contribute: | ||
| VouchMe-style identity endorsement flows | ||
|
|
||
| 1. Fork the repository and create your feature branch (`git checkout -b feature/AmazingFeature`). | ||
| 2. Commit your changes (`git commit -m 'Add some AmazingFeature'`). | ||
| 3. Run the development workflow commands to ensure code quality: | ||
| - `npm run format:write` | ||
| - `npm run lint:fix` | ||
| - `npm run typecheck` | ||
| 4. Push your branch (`git push origin feature/AmazingFeature`). | ||
| 5. Open a Pull Request for review. | ||
| Under the Stability Nexus / The Stable Order research direction. | ||
|
|
||
| If you encounter bugs, need help, or have feature requests: | ||
|
|
||
| - Please open an issue in this repository providing detailed information. | ||
| - Describe the problem clearly and include any relevant logs or screenshots. | ||
| --- | ||
|
|
||
| # ✅ After pasting | ||
|
|
||
| We appreciate your feedback and contributions! | ||
| Run: | ||
|
|
||
| © 2025 The Stable Order. | ||
| ```bash | ||
| git add README.md | ||
| git commit -m "Fix README markdown formatting and links" | ||
| git push origin mini-dit-prototype |
There was a problem hiding this comment.
Fix broken markdown formatting and remove leftover instructions.
The markdown structure breaks starting at line 72. The code block is not properly closed, causing subsequent sections (Installation, Run Tests, Smart Contract Overview, Research Context) to render incorrectly. Additionally, lines 107-114 contain git commit instructions that appear to be accidentally included.
📝 Proposed fix
```bash
git clone https://github.com/<your-username>/IdentityTokens-EVM-Contracts.git
cd IdentityTokens-EVM-Contracts
git checkout mini-dit-prototype
-Install dependencies:
+```
+
+Install dependencies:
+```bash
forge install
-🧪 Run Tests
+```
+
+---
+
+## 🧪 Run Tests
+
+```bash
forge test
-Expected output:
+```
-All MiniDIT tests passing
-🔍 Smart Contract Overview
-Mint Identity NFT
-mintIdentity(string metadataURI)
-Endorse Another Identity
-endorse(fromTokenId, toTokenId, tag)
-Revoke Endorsement
-revokeEndorsement(toTokenId, index)
-Mark Identity as Compromised
-markCompromised(tokenId)
-🧠 Research Context
-This prototype is based on ongoing discussions around:
+Expected output: All MiniDIT tests passing.
-DIT (Decentralized Identity Tokens)
+---
-TNT (Trust Network Tokens)
+## 🔍 Smart Contract Overview
-VouchMe-style identity endorsement flows
+| Function | Description |
+|----------|-------------|
+| `mintIdentity(string metadataURI)` | Mint Identity NFT |
+| `endorse(fromTokenId, toTokenId, tag)` | Endorse Another Identity |
+| `revokeEndorsement(toTokenId, index)` | Revoke Endorsement |
+| `markCompromised(tokenId)` | Mark Identity as Compromised |
-Under the Stability Nexus / The Stable Order research direction.
+---
+## 🧠 Research Context
----
-
-# ✅ After pasting
-
-Run:
+This prototype is based on ongoing discussions around:
-```bash
-git add README.md
-git commit -m "Fix README markdown formatting and links"
-git push origin mini-dit-prototype
+- DIT (Decentralized Identity Tokens)
+- TNT (Trust Network Tokens)
+- VouchMe-style identity endorsement flows
+
+Under the Stability Nexus / The Stable Order research direction.🤖 Prompt for AI Agents
In `@README.md` around lines 72 - 114, README.md has an unclosed code block and
leftover git instructions causing formatting to break; fix by closing the
opening triple-backtick after the initial git checkout (re-insert ```bash around
the "Install dependencies:" section and add matching ``` before "forge install"
and around the "forge test" example), remove the accidental commit/push lines at
the bottom, add proper Markdown headings (e.g., "## 🧪 Run Tests", "## 🔍 Smart
Contract Overview", "## 🧠 Research Context"), and replace the bulleted function
list with a table documenting mintIdentity(string metadataURI),
endorse(fromTokenId, toTokenId, tag), revokeEndorsement(toTokenId, index), and
markCompromised(tokenId) so the README renders correctly.
| function endorse( | ||
| uint256 fromTokenId, | ||
| uint256 toTokenId, | ||
| string calldata tag | ||
| ) external { | ||
| require(ownerOf(fromTokenId) == msg.sender, "Not owner of fromToken"); | ||
|
|
||
| // Will revert if toTokenId does not exist | ||
| ownerOf(toTokenId); | ||
|
|
||
| require(!identities[fromTokenId].compromised, "From identity compromised"); | ||
|
|
||
| endorsements[toTokenId].push( | ||
| Endorsement(fromTokenId, tag, false) | ||
| ); | ||
|
|
||
| emit Endorsed(fromTokenId, toTokenId, tag); | ||
| } |
There was a problem hiding this comment.
Missing self-endorsement prevention.
The function allows an identity to endorse itself (fromTokenId == toTokenId), which may not be semantically meaningful and could be exploited to artificially inflate endorsement counts.
🐛 Proposed fix
function endorse(
uint256 fromTokenId,
uint256 toTokenId,
string calldata tag
) external {
require(ownerOf(fromTokenId) == msg.sender, "Not owner of fromToken");
+ require(fromTokenId != toTokenId, "Cannot self-endorse");
// Will revert if toTokenId does not exist
ownerOf(toTokenId);📝 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.
| function endorse( | |
| uint256 fromTokenId, | |
| uint256 toTokenId, | |
| string calldata tag | |
| ) external { | |
| require(ownerOf(fromTokenId) == msg.sender, "Not owner of fromToken"); | |
| // Will revert if toTokenId does not exist | |
| ownerOf(toTokenId); | |
| require(!identities[fromTokenId].compromised, "From identity compromised"); | |
| endorsements[toTokenId].push( | |
| Endorsement(fromTokenId, tag, false) | |
| ); | |
| emit Endorsed(fromTokenId, toTokenId, tag); | |
| } | |
| function endorse( | |
| uint256 fromTokenId, | |
| uint256 toTokenId, | |
| string calldata tag | |
| ) external { | |
| require(ownerOf(fromTokenId) == msg.sender, "Not owner of fromToken"); | |
| require(fromTokenId != toTokenId, "Cannot self-endorse"); | |
| // Will revert if toTokenId does not exist | |
| ownerOf(toTokenId); | |
| require(!identities[fromTokenId].compromised, "From identity compromised"); | |
| endorsements[toTokenId].push( | |
| Endorsement(fromTokenId, tag, false) | |
| ); | |
| emit Endorsed(fromTokenId, toTokenId, tag); | |
| } |
🤖 Prompt for AI Agents
In `@src/MiniDIT.sol` around lines 46 - 63, The endorse function currently allows
self-endorsement; add a check in endorse to require(fromTokenId != toTokenId,
"Cannot self-endorse") (or similar) immediately after the ownerOf(fromTokenId)
check so that an identity cannot endorse itself; this touches the endorse
function and prevents pushing Endorsement(fromTokenId, tag, false) into
endorsements[toTokenId] when fromTokenId equals toTokenId.
Overview
This Pull Request introduces Mini-DIT, a lightweight experimental prototype exploring early design and security trade-offs for Decentralized Identity Tokens (DIT) as part of the DIT 2026 research direction under Stability Nexus discussions.
This implementation is a learning-by-building prototype, intended to validate protocol assumptions and identity-endorsement flows before formal specification work.
It is not production-ready and is submitted for review and feedback only.
Key Features Implemented
Identity Token Core
Trust & Endorsements
worked-with,verified)Security & Revocation
Testing Framework
Tooling & Repository Improvements
src/,test/,foundry.toml).gitignorefor build artifactsOut of Scope (By Design)
These are intentionally excluded to keep this prototype focused on core identity and endorsement mechanics.
How to Run