-
-
Notifications
You must be signed in to change notification settings - Fork 16
Implement a maximum minting cap or require multi-signature approval for bulk mints. #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,10 @@ export default function TokenActionsPage() { | |
| }); | ||
| const [isLoadingPermissions, setIsLoadingPermissions] = useState(true); | ||
|
|
||
| // mint cap state | ||
| const [mintCap, setMintCap] = useState<bigint>(0n); | ||
| const [totalMinted, setTotalMinted] = useState<bigint>(0n); | ||
|
|
||
| // Form states for each action | ||
| const [issueRecipient, setIssueRecipient] = useState(""); | ||
| const [revokeTokenId, setRevokeTokenId] = useState(""); | ||
|
|
@@ -112,6 +116,25 @@ export default function TokenActionsPage() { | |
| setPermissions(perms); | ||
| setUserRoles(roles); | ||
| setIsTokenRevokable(tokenInfo.revokable); | ||
|
|
||
| // read mint cap and total minted from contract | ||
| const publicClient = getPublicClient(config as any, { chainId }); | ||
| if (publicClient) { | ||
| const [cap, minted] = await Promise.all([ | ||
| publicClient.readContract({ | ||
| address: contractAddress, | ||
| abi: TNTAbi, | ||
| functionName: "maxMintCap", | ||
| }) as Promise<bigint>, | ||
| publicClient.readContract({ | ||
| address: contractAddress, | ||
| abi: TNTAbi, | ||
| functionName: "getAllParticipantsCount", | ||
| }) as Promise<bigint>, | ||
| ]); | ||
| setMintCap(cap); | ||
| setTotalMinted(minted); | ||
| } | ||
|
Comment on lines
+119
to
+137
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if TNT.sol has totalSupply or a token counter that tracks actual minted count
echo "=== Looking for totalSupply or token counter ==="
rg -n "totalSupply|tokenId|_nextTokenId|_tokenIdCounter" -g "TNT.sol"
echo ""
echo "=== Check issueToken function to see how tokens are counted ==="
rg -n "function issueToken" -g "TNT.sol" -A 20Repository: StabilityNexus/TNT Length of output: 3793 🏁 Script executed: #!/bin/bash
# Check for getter functions that expose token count or supply
echo "=== Looking for public getter functions in TNT.sol ==="
rg -n "function.*\(.*\).*public.*view.*returns" contracts/src/TNT.sol | head -30
echo ""
echo "=== Check the full file to see all public read methods ==="
rg -n "public.*view" contracts/src/TNT.solRepository: StabilityNexus/TNT Length of output: 1616 🏁 Script executed: #!/bin/bash
# Check if maxMintCap exists in TNT.sol
echo "=== Searching for maxMintCap in TNT.sol ==="
rg -n "maxMintCap" contracts/src/TNT.sol
echo ""
echo "=== Looking for max supply related variables ==="
rg -n "maxSupply|max_.*supply|supply" contracts/src/TNT.sol | head -20Repository: StabilityNexus/TNT Length of output: 398 Critical: The code attempts to call Additionally, 🤖 Prompt for AI Agents |
||
| } catch (error) { | ||
| console.error("Error loading permissions:", error); | ||
| } finally { | ||
|
|
@@ -257,6 +280,10 @@ export default function TokenActionsPage() { | |
| toast.error("You don't have permission to issue tokens"); | ||
| return; | ||
| } | ||
| if (mintCap > 0n && totalMinted >= mintCap) { | ||
| toast.error("Mint cap has been reached. No more tokens can be issued."); | ||
| return; | ||
| } | ||
| try { | ||
| setIsIssuing(true); | ||
| const tx = await writeContract(config as any, { | ||
|
|
@@ -269,6 +296,7 @@ export default function TokenActionsPage() { | |
| toast.success("Token issued successfully!"); | ||
| console.log("Issue token tx:", tx); | ||
| setIssueRecipient(""); | ||
| setTotalMinted((prev) => prev + 1n); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optimistic update may desync from actual on-chain state. The optimistic increment Consider re-fetching Suggested fix toast.success("Token issued successfully!");
console.log("Issue token tx:", tx);
setIssueRecipient("");
- setTotalMinted((prev) => prev + 1n);
+ // Re-fetch actual count from contract
+ const publicClient = getPublicClient(config as any, { chainId });
+ if (publicClient) {
+ const minted = await publicClient.readContract({
+ address: contractAddress,
+ abi: TNTAbi,
+ functionName: "getAllParticipantsCount",
+ }) as bigint;
+ setTotalMinted(minted);
+ }🤖 Prompt for AI Agents |
||
| } catch (error) { | ||
| console.error("Error issuing token:", error); | ||
| toast.error("Failed to issue token"); | ||
|
|
@@ -568,23 +596,34 @@ export default function TokenActionsPage() { | |
| <label className="block text-sm font-medium text-slate-300 mb-1.5"> | ||
| Recipient Address | ||
| </label> | ||
| {/* mint cap progress */} | ||
| {mintCap > 0n && ( | ||
| <div className="text-xs text-slate-400 mb-2"> | ||
| Minted: {totalMinted.toString()} / {mintCap.toString()} | ||
| {mintCap > 0n && totalMinted >= mintCap && ( | ||
| <span className="ml-2 text-red-400 font-semibold">Cap Reached!</span> | ||
| )} | ||
| </div> | ||
| )} | ||
| <input | ||
| type="text" | ||
| value={issueRecipient} | ||
| onChange={(e) => setIssueRecipient(e.target.value)} | ||
| placeholder="Enter recipient address" | ||
| className="w-full bg-slate-800/80 border-0 text-white placeholder:text-slate-500 rounded-xl py-2.5 px-4 focus:ring-2 focus:ring-emerald-500/30 transition-all duration-200" | ||
| required | ||
| disabled={!permissions.canIssue} | ||
| disabled={!permissions.canIssue || (mintCap > 0n && totalMinted >= mintCap)} | ||
| /> | ||
| </div> | ||
| <button | ||
| type="submit" | ||
| disabled={isIssuing || !permissions.canIssue} | ||
| disabled={isIssuing || !permissions.canIssue || (mintCap > 0n && totalMinted >= mintCap)} | ||
| className="w-full py-2.5 px-4 bg-gradient-to-r from-emerald-600 to-emerald-500 hover:from-emerald-700 hover:to-emerald-600 rounded-xl text-white font-medium transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed" | ||
| > | ||
| {isIssuing | ||
| ? "Issuing..." | ||
| : mintCap > 0n && totalMinted >= mintCap | ||
| ? "Mint Cap Reached" | ||
| : !permissions.canIssue | ||
| ? "No Permission" | ||
| : "Issue Token"} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,11 @@ const TNT = { | |
| "name": "_imageURL", | ||
| "type": "string", | ||
| "internalType": "string" | ||
| }, | ||
| { | ||
| "name": "_maxMintCap", | ||
| "type": "uint256", | ||
| "internalType": "uint256" | ||
| } | ||
|
Comment on lines
+35
to
40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify TNT.sol constructor parameters and maxMintCap/maxSupply naming
echo "=== TNT.sol constructor ==="
rg -n "constructor\(" -g "TNT.sol" -A 15
echo ""
echo "=== Check for maxMintCap or maxSupply variable ==="
rg -n "maxMintCap|maxSupply" -g "TNT.sol"
echo ""
echo "=== Check for MintCapReached or MaxSupplyReached error ==="
rg -n "MintCapReached|MaxSupplyReached" -g "TNT.sol"Repository: StabilityNexus/TNT Length of output: 1554 ABI contains multiple mismatches with actual TNT contract implementation. The TNT.ts ABI file has three interconnected inconsistencies with the actual contract:
These inconsistencies will cause issues with contract verification tools, block explorers, and any frontend code attempting to read the 🤖 Prompt for AI Agents |
||
| ], | ||
| "stateMutability": "nonpayable" | ||
|
|
@@ -417,6 +422,19 @@ const TNT = { | |
| "outputs": [], | ||
| "stateMutability": "nonpayable" | ||
| }, | ||
| { | ||
| "type": "function", | ||
| "name": "maxMintCap", | ||
| "inputs": [], | ||
| "outputs": [ | ||
| { | ||
| "name": "", | ||
| "type": "uint256", | ||
| "internalType": "uint256" | ||
| } | ||
| ], | ||
| "stateMutability": "view" | ||
| }, | ||
|
Comment on lines
+425
to
+437
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check exact function/variable and error names in TNT.sol
echo "=== Public variables and functions containing 'mint' or 'supply' ==="
rg -n "public.*max|function.*max" -g "TNT.sol" -i
echo ""
echo "=== Error definitions ==="
rg -n "^error " -g "TNT.sol"Repository: StabilityNexus/TNT Length of output: 323 🏁 Script executed: #!/bin/bash
# Search for error definitions with broader patterns
echo "=== Search for error/Error patterns in TNT.sol ==="
rg -n "error|Error|revert|Revert" -g "TNT.sol" -i | head -30
echo ""
echo "=== Check ABI file lines 946-950 ==="
sed -n '946,950p' web/src/utils/contractsABI/TNT.tsRepository: StabilityNexus/TNT Length of output: 1267 ABI naming mismatches will cause contract interaction failures. The ABI declares Applies to lines 425-437 and 946-950. 🤖 Prompt for AI Agents |
||
| { | ||
| "type": "function", | ||
| "name": "metadata", | ||
|
|
@@ -925,6 +943,11 @@ const TNT = { | |
| "name": "InvalidRecipient", | ||
| "inputs": [] | ||
| }, | ||
| { | ||
| "type": "error", | ||
| "name": "MintCapReached", | ||
| "inputs": [] | ||
| }, | ||
| { | ||
| "type": "error", | ||
| "name": "NotRevokable", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,11 @@ const TNTFactory = { | |
| "name": "imageURL", | ||
| "type": "string", | ||
| "internalType": "string" | ||
| }, | ||
| { | ||
| "name": "maxMintCap", | ||
| "type": "uint256", | ||
| "internalType": "uint256" | ||
| } | ||
|
Comment on lines
+26
to
31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify the Factory.sol createTNT function signature
echo "=== Factory.sol createTNT function signature ==="
rg -n "function createTNT" --type solidity -A 3 || rg -n "function createTNT" -g "*.sol" -A 3
echo ""
echo "=== TNT.sol constructor signature ==="
rg -n "constructor\(" -g "*.sol" -A 10 | head -30Repository: StabilityNexus/TNT Length of output: 1251 🏁 Script executed: # Check the frontend call in create/page.tsx
echo "=== Frontend createTNT call ==="
rg -n "createTNT\|maxMintCap" web/src/app/create/page.tsx -B 2 -A 2
echo ""
echo "=== Look for setMaxSupply or maxMintCap in TNT.sol ==="
rg -n "setMaxSupply\|maxMintCap" -g "*.sol" -A 3
echo ""
echo "=== Check full ABI structure in TNTFactory.ts ==="
head -50 web/src/utils/contractsABI/TNTFactory.tsRepository: StabilityNexus/TNT Length of output: 1646 🏁 Script executed: # Find files related to token creation
echo "=== Find create-related files ==="
fd -t f "create" web/src --type f | head -20
echo ""
echo "=== Search for TNTFactory usage ==="
rg -n "TNTFactory" web/src -A 2
echo ""
echo "=== Look for maxSupply in TNT contract ==="
rg -n "maxSupply\|_maxSupply\|maxMint" contracts/src/TNT.sol -B 2 -A 2
echo ""
echo "=== Check if there are any external function calls to createTNT ==="
rg -n "\.createTNT\|createTNT\(" web/srcRepository: StabilityNexus/TNT Length of output: 3102 🏁 Script executed: # Show the complete createTNT function from Factory.sol
rg -n "function createTNT" contracts/src/Factory.sol -A 10Repository: StabilityNexus/TNT Length of output: 668 Critical: ABI declares The The frontend code in Required fix: Either:
🤖 Prompt for AI Agents |
||
| ], | ||
| "outputs": [ | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.