Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions contracts/src/TNT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ contract TNT is ERC721, AccessControl {
error NotOwner();
error InvalidIndex();
error NonTransferable();
error MaxSupplyReached();

bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant REVOKER_ROLE = keccak256("REVOKER_ROLE");
Expand All @@ -28,6 +29,7 @@ contract TNT is ERC721, AccessControl {
bool public immutable revokable;
address public factoryContract;
string public imageURL;
uint256 public maxSupply;

struct TokenMetadata {
uint256 issuedAt;
Expand All @@ -54,8 +56,14 @@ contract TNT is ERC721, AccessControl {
imageURL = _imageURL;
}

function setMaxSupply(uint256 _maxSupply) external onlyRole(DEFAULT_ADMIN_ROLE) {
maxSupply = _maxSupply;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

function issueToken(address user) public onlyRole(MINTER_ROLE) {
if (user == address(0)) revert InvalidUser();

if (maxSupply > 0 && _nextTokenId >= maxSupply) revert MaxSupplyReached();

uint256 tokenId = _nextTokenId++;
_safeMint(user, tokenId);
Expand Down
104 changes: 71 additions & 33 deletions web/src/app/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ import { TNTFactoryAbi } from "@/utils/contractsABI/TNTFactory";
import { Info } from "lucide-react";
import { useTheme } from "next-themes";
import { getPublicClient } from "@wagmi/core";
import { decodeEventLog } from "viem";

interface DeployContractProps {
tokenName: string;
tokenSymbol: string;
revokable: boolean;
imageURL: string;
maxMintCap: string;
}

const TNTCREATED_EVENT_NOT_FOUND =
"TNTCreated event not found in transaction logs";

const fields = [
{
id: "tokenName",
Expand All @@ -44,6 +49,13 @@ const fields = [
placeholder: "https://example.com/image.png",
description: "Image to associate with this TNT",
},
{
id: "maxMintCap",
label: "Max Mint Cap",
type: "number",
placeholder: "e.g. 1000",
description: "Maximum number of tokens that can ever be minted",
},
];

export default function CreateTNT() {
Expand All @@ -52,6 +64,7 @@ export default function CreateTNT() {
tokenSymbol: "",
revokable: false,
imageURL: "",
maxMintCap: "",
});
const [isDeploying, setIsDeploying] = useState(false);

Expand All @@ -78,9 +91,21 @@ export default function CreateTNT() {
};

const saveTransaction = (txDetails: object) => {
const history = getTransactionHistory();
history.push(txDetails);
localStorage.setItem("transactionHistory", JSON.stringify(history));
try {
const history = getTransactionHistory();
history.push(txDetails);
localStorage.setItem("transactionHistory", JSON.stringify(history));
} catch (error) {
// Handle QuotaExceededError or security exceptions (e.g., storage disabled)
console.error("Failed to save transaction to localStorage:", error);

if (error instanceof DOMException &&
(error.name === 'QuotaExceededError' || error.name === 'NS_ERROR_DOM_QUOTA_REACHED')) {
toast.error("Local storage is full. Transaction history might not be saved.");
} else {
toast.error("An error occurred while saving transaction data.");
}
}
};

const deployContract = async () => {
Expand All @@ -105,7 +130,7 @@ export default function CreateTNT() {
return;
}

const { tokenName, tokenSymbol, revokable, imageURL } = formData;
const { tokenName, tokenSymbol, revokable, imageURL, maxMintCap } = formData;

// Validate inputs
if (!tokenName.trim()) {
Expand All @@ -118,6 +143,12 @@ export default function CreateTNT() {
return;
}

const capValue = Number(maxMintCap);
if (!maxMintCap || !Number.isInteger(capValue) || capValue <= 0) {
toast.error("Max Mint Cap must be a positive integer");
return;
}

const factoryAddress = TNTVaultFactories[chainId];
const cleanImageURL = imageURL.trim() || "";

Expand All @@ -127,6 +158,7 @@ export default function CreateTNT() {
symbol: tokenSymbol.trim(),
revokable,
imageURL: cleanImageURL,
maxMintCap,
chainId,
userAddress: address,
});
Expand All @@ -137,7 +169,7 @@ export default function CreateTNT() {
address: factoryAddress,
abi: TNTFactoryAbi,
functionName: "createTNT",
args: [tokenName.trim(), tokenSymbol.trim(), revokable, cleanImageURL],
args: [tokenName.trim(), tokenSymbol.trim(), revokable, cleanImageURL, BigInt(maxMintCap)],
chainId: chainId,
});

Expand All @@ -157,45 +189,41 @@ export default function CreateTNT() {
console.log("Transaction confirmed! Receipt:", receipt);

if (receipt.status === "success") {
// Extract the new TNT contract address from logs
let newTNTAddress = null;

// Look for TNTCreated event in logs
try {
const publicClient = getPublicClient(config as any, { chainId });
if (publicClient) {
// Decode logs to find the TNTCreated event
for (const log of receipt.logs) {
if (
log.address.toLowerCase() === factoryAddress.toLowerCase()
) {
// This is likely our TNTCreated event
// The first topic after the event signature should be the owner
// The data should contain the TNT address
if (log.topics.length > 1 && log.data) {
// Try to decode the TNT address from the log data
// For now, we'll use a placeholder - in a real implementation,
// you'd properly decode the event logs
console.log("TNT created successfully, log:", log);
newTNTAddress = log.data; // This is a simplified approach
}
}
// Extract the new TNT contract address from TNTCreated event
let newTNTAddress: `0x${string}` | null = null;

for (const log of receipt.logs) {
if (log.address.toLowerCase() !== factoryAddress.toLowerCase())
continue;
try {
const decoded = decodeEventLog({
abi: TNTFactoryAbi,
data: log.data,
topics: log.topics,
});
if (
decoded.eventName === "TNTCreated" &&
decoded.args &&
"tntAddress" in decoded.args
) {
newTNTAddress = decoded.args.tntAddress as `0x${string}`;
break;
}
} catch {
continue;
}
} catch (logError) {
console.warn("Could not decode TNT address from logs:", logError);
}

// If we couldn't get the address from logs, create a placeholder
if (!newTNTAddress) {
newTNTAddress = `0x${txHash.slice(2, 42)}`; // Use part of tx hash as placeholder
throw new Error(TNTCREATED_EVENT_NOT_FOUND);
}

const txDetails = {
tokenName: tokenName.trim(),
tokenSymbol: tokenSymbol.trim(),
revokable,
imageURL: cleanImageURL,
maxMintCap,
transactionHash: txHash,
contractAddress: newTNTAddress,
chainId,
Expand All @@ -215,15 +243,21 @@ export default function CreateTNT() {
throw new Error("Transaction failed");
}
} catch (waitError) {
const isDecodingFailure =
waitError instanceof Error &&
waitError.message === TNTCREATED_EVENT_NOT_FOUND;
if (isDecodingFailure) throw waitError;

console.error("Error waiting for transaction:", waitError);
toast.error("Transaction confirmation failed. Please check manually.");

// Still save the transaction attempt
// Still save the transaction attempt (no contractAddress)
const txDetails = {
tokenName: tokenName.trim(),
tokenSymbol: tokenSymbol.trim(),
revokable,
imageURL: cleanImageURL,
maxMintCap,
transactionHash: txHash,
chainId,
factoryAddress,
Expand Down Expand Up @@ -258,6 +292,10 @@ export default function CreateTNT() {
toast.error(
"Network error. Please check your connection and try again."
);
} else if (error?.message === TNTCREATED_EVENT_NOT_FOUND) {
toast.error(
"Transaction succeeded but the TNT address could not be read from the receipt. Check the block explorer for the contract address."
);
} else {
toast.error(
`Failed to deploy TNT: ${
Expand Down
43 changes: 41 additions & 2 deletions web/src/app/token-actions/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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("");
Expand Down Expand Up @@ -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

Copy link
Copy Markdown

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

🏁 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 20

Repository: 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.sol

Repository: 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 -20

Repository: StabilityNexus/TNT

Length of output: 398


Critical: maxMintCap function does not exist on the contract.

The code attempts to call publicClient.readContract() with functionName: "maxMintCap", but TNT.sol only exposes a public state variable maxSupply (line 32), not a function. This will cause a runtime error. Use the public state variable maxSupply instead.

Additionally, getAllParticipantsCount() counts unique recipients, not total tokens minted. The contract's actual token count is tracked by the private _nextTokenId variable (incremented per issuance), but this is not exposed publicly. Using getAllParticipantsCount as the "totalMinted" metric is semantically incorrect—a user receiving multiple tokens still counts as one participant. If the intent is to enforce a token supply cap, consider whether the contract should expose _nextTokenId or if the metric should track participants instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/app/token-actions/page.tsx` around lines 119 - 137, The UI is calling
a non-existent contract function maxMintCap and misinterpreting
getAllParticipantsCount as total minted; update the readContract call to read
the public state variable "maxSupply" (replace functionName: "maxMintCap" with
functionName: "maxSupply") and setMintCap with that result, and either (A) if
you want to show participants rename the UI state/labels from totalMinted to
totalParticipants and keep using getAllParticipantsCount, or (B) if you need
actual minted token count add a new public accessor in the contract (e.g.,
expose _nextTokenId or a totalMinted() view) and read that new function from the
UI (update the readContract functionName and setTotalMinted accordingly). Ensure
the symbols referenced are maxSupply, getAllParticipantsCount, setMintCap,
setTotalMinted (or setTotalParticipants) and adjust UI labels to match the
chosen metric.

} catch (error) {
console.error("Error loading permissions:", error);
} finally {
Expand Down Expand Up @@ -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, {
Expand All @@ -269,6 +296,7 @@ export default function TokenActionsPage() {
toast.success("Token issued successfully!");
console.log("Issue token tx:", tx);
setIssueRecipient("");
setTotalMinted((prev) => prev + 1n);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Optimistic update may desync from actual on-chain state.

The optimistic increment setTotalMinted((prev) => prev + 1n) assumes every successful issueToken call increases getAllParticipantsCount. However, if the recipient already exists in _allUsers, the on-chain count doesn't change, causing the UI to show a higher "minted" count than reality.

Consider re-fetching getAllParticipantsCount after a successful transaction, or remove the optimistic update:

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
Verify each finding against the current code and only fix it if needed.

In `@web/src/app/token-actions/page.tsx` at line 299, The optimistic increment
using setTotalMinted((prev) => prev + 1n) can desync with on‑chain state; remove
that optimistic update and instead, after a successful issueToken transaction
confirmation, call the contract/read method getAllParticipantsCount (or the
existing helper that queries _allUsers) and setTotalMinted to the returned value
(BigInt) to reflect the true on‑chain count; ensure this fetch occurs after the
transaction is mined/confirmed in the same flow that calls issueToken so the UI
always matches getAllParticipantsCount.

} catch (error) {
console.error("Error issuing token:", error);
toast.error("Failed to issue token");
Expand Down Expand Up @@ -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"}
Expand Down
23 changes: 23 additions & 0 deletions web/src/utils/contractsABI/TNT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ const TNT = {
"name": "_imageURL",
"type": "string",
"internalType": "string"
},
{
"name": "_maxMintCap",
"type": "uint256",
"internalType": "uint256"
}
Comment on lines +35 to 40

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 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:

  1. Constructor parameter mismatch: The ABI declares a 7-parameter constructor with _maxMintCap, but the actual TNT.sol constructor (lines 43–57) has only 6 parameters and no _maxMintCap parameter.

  2. State variable naming mismatch: The ABI declares a maxMintCap() view function, but the contract has a public state variable named maxSupply (line 32).

  3. Error naming mismatch: The ABI declares a MintCapReached error, but the contract defines MaxSupplyReached (line 19).

These inconsistencies will cause issues with contract verification tools, block explorers, and any frontend code attempting to read the maxMintCap or call the MintCapReached error. Update the ABI to reflect the actual contract: use maxSupply instead of maxMintCap and MaxSupplyReached instead of MintCapReached, and remove _maxMintCap from the constructor parameters.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/utils/contractsABI/TNT.ts` around lines 35 - 40, Update the TNT.ts
ABI to match the Solidity contract: remove the constructor parameter named
"_maxMintCap" so the constructor parameters match the 6-arg TNT.sol constructor,
rename the view/state entry "maxMintCap" to "maxSupply" (and any corresponding
function ABI entry) so callers read the public variable correctly, and replace
the error name "MintCapReached" with "MaxSupplyReached" to match the contract's
custom error; adjust any related references in the ABI object to these exact
symbols (constructor, maxSupply, MaxSupplyReached).

],
"stateMutability": "nonpayable"
Expand Down Expand Up @@ -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

Copy link
Copy Markdown

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

🏁 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.ts

Repository: StabilityNexus/TNT

Length of output: 1267


ABI naming mismatches will cause contract interaction failures.

The ABI declares maxMintCap and MintCapReached, but the contract uses maxSupply (line 32 in TNT.sol) and MaxSupplyReached (line 19 in TNT.sol). Frontend readContract calls will fail with "function not found" and "error not found" errors. Update the ABI to match the contract's actual function and error names.

Applies to lines 425-437 and 946-950.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/utils/contractsABI/TNT.ts` around lines 425 - 437, The ABI in TNT.ts
uses incorrect names (maxMintCap and MintCapReached) that don't match the
Solidity contract symbols; replace occurrences of "maxMintCap" with "maxSupply"
and "MintCapReached" with "MaxSupplyReached" in the ABI so the JSON keys for the
function and custom error match the contract (ensure the function entry name
"maxSupply" and the error entry "MaxSupplyReached" are used where currently
"maxMintCap" and "MintCapReached" appear, including at the locations around the
current maxMintCap block and the error block near lines 946-950).

{
"type": "function",
"name": "metadata",
Expand Down Expand Up @@ -925,6 +943,11 @@ const TNT = {
"name": "InvalidRecipient",
"inputs": []
},
{
"type": "error",
"name": "MintCapReached",
"inputs": []
},
{
"type": "error",
"name": "NotRevokable",
Expand Down
5 changes: 5 additions & 0 deletions web/src/utils/contractsABI/TNTFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const TNTFactory = {
"name": "imageURL",
"type": "string",
"internalType": "string"
},
{
"name": "maxMintCap",
"type": "uint256",
"internalType": "uint256"
}
Comment on lines +26 to 31

Copy link
Copy Markdown

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

🏁 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 -30

Repository: 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.ts

Repository: 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/src

Repository: 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 10

Repository: StabilityNexus/TNT

Length of output: 668


Critical: ABI declares maxMintCap parameter but Factory.sol does not accept it.

The createTNT function in contracts/src/Factory.sol (line 24) accepts only 4 parameters: name, symbol, revokable, and imageURL. However, the ABI in web/src/utils/contractsABI/TNTFactory.ts declares 5 parameters, adding maxMintCap as a uint256.

The frontend code in web/src/app/create/page.tsx (line 171) calls this function with 5 arguments: args: [tokenName.trim(), tokenSymbol.trim(), revokable, cleanImageURL, BigInt(maxMintCap)]. Because the function selector is computed from the ABI signature (5 parameters), it will not match the actual contract function signature (4 parameters), causing token creation transactions to fail.

Required fix: Either:

  1. Remove maxMintCap from the ABI and handle it separately (if needed via a separate contract method), OR
  2. Update Factory.sol and the TNT constructor to accept and handle maxMintCap as a parameter.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/utils/contractsABI/TNTFactory.ts` around lines 26 - 31, ABI and
frontend disagree with the contract: TNTFactory.ts declares a fifth parameter
"maxMintCap" (uint256) while Factory.sol's createTNT function only accepts
(name, symbol, revokable, imageURL), and page.tsx currently calls createTNT with
five args; fix by either removing "maxMintCap" from the ABI (TNTFactory.ts) and
stop passing it from page.tsx (remove BigInt(maxMintCap) and any ABI entries for
maxMintCap), OR update the smart contract createTNT signature and the TNT
constructor to accept and store maxMintCap, recompile and redeploy the contract
and then update TNTFactory.ts ABI to match the new
createTNT(name,symbol,revokable,imageURL,maxMintCap) signature so the function
selector and call arguments align.

],
"outputs": [
Expand Down
Loading