Smart Contract Audit Report Findings Template

Smart Contract Audit Report Generator

[Project Name]

Commit Hash: --

Date: --

1. Executive Summary

Total Findings: 0
Critical: 0
High: 0
Medium: 0
Low: 0
Gas/Info: 0

2. Detailed Findings

No vulnerabilities logged yet.

Log New Vulnerability

Manage Findings

Review or delete existing entries.

ID Severity Title Action

Project Details


Data Management

No vulnerabilities logged yet.

'; } else { // Sort by severity weight const severityWeight = { "Critical": 5, "High": 4, "Medium": 3, "Low": 2, "Gas": 1, "Info": 0 }; const sortedFindings = [...findings].sort((a, b) => severityWeight[b.severity] - severityWeight[a.severity]); sortedFindings.forEach(f => { const card = document.createElement('div'); card.className = 'sca-finding-card'; card.innerHTML = `
${f.id} - ${f.title} ${f.severity}
Status: ${f.status}
Description:
${f.desc}
Recommendation:
${f.rec}
`; findingsListDiv.appendChild(card); }); } // 5. Update Manage Table renderManageTable(); } function renderManageTable() { scaManageBody = document.getElementById('sca-manage-body'); // re-grab to be safe scaManageBody.innerHTML = ""; findings.forEach((f, index) => { const tr = document.createElement('tr'); tr.innerHTML = ` ${f.id} ${f.severity} ${f.title} `; scaManageBody.appendChild(tr); }); } // Add global delete function window.deleteFinding = function(index) { if(confirm("Delete this finding?")) { findings.splice(index, 1); updateDashboard(); } } function addFinding() { const title = inpTitle.value.trim(); const severity = inpSev.value; const status = inpStatus.value; const desc = inpDesc.value.trim(); const rec = inpRec.value.trim(); let id = inpId.value.trim(); if (!title || !desc) { alert("Please enter a Title and Description."); return; } // Auto-gen ID if empty based on Severity char + number if (!id) { const prefix = severity.charAt(0).toUpperCase(); // Count existing of this letter const count = findings.filter(f => f.id.startsWith(prefix)).length + 1; id = `${prefix}-0${count}`; } findings.push({ id, title, severity, status, desc, rec }); // Reset form inpTitle.value = ""; inpDesc.value = ""; inpRec.value = ""; inpId.value = ""; // Show success addMsg.style.display = "block"; setTimeout(() => { addMsg.style.display = "none"; }, 2000); updateDashboard(); } function loadSampleData() { projectInfo.name = "EtherVault Protocol"; projectInfo.commit = "e7f8a9b..."; findings = [ { id: "C-01", title: "Reentrancy in withdraw() function", severity: "Critical", status: "Fixed", desc: "The `withdraw` function performs an external call to send ETH to the user before updating the user's balance state variable. A malicious contract can recursively call `withdraw` before the balance is updated, draining the contract.", rec: "Implement the Checks-Effects-Interactions pattern. Update the state variable `balances[msg.sender] = 0` before making the external call. Alternatively, use OpenZeppelin's `ReentrancyGuard` modifier." }, { id: "H-01", title: "Unchecked Return Value on Transfer", severity: "High", status: "Open", desc: "The contract uses `ERC20.transfer` without checking the boolean return value. Some tokens return false on failure rather than reverting. This could lead to the contract believing a transfer succeeded when it failed.", rec: "Use OpenZeppelin's `SafeERC20` library and `safeTransfer` to handle non-standard ERC20 implementations automatically." }, { id: "M-01", title: "Centralization Risk: Owner can pause indefinitely", severity: "Medium", status: "Acknowledged", desc: "The `pause()` function allows the owner to freeze all assets in the protocol without a timelock. If the private key is compromised, user funds are stuck.", rec: "Implement a TimelockController or a multi-sig wallet for sensitive administrative functions." }, { id: "G-01", title: "Use of storage instead of memory in loop", severity: "Gas", status: "Fixed", desc: "In `updatePools()`, the code reads `pools[i]` from storage in every iteration. This consumes excessive gas.", rec: "Cache the array length and read struct data into `memory` variables inside the loop." } ]; // Update config inputs to match confProject.value = projectInfo.name; confCommit.value = projectInfo.commit; updateDashboard(); alert("Sample vulnerability data loaded."); openTab(0); } // --- Tab Logic --- function openTab(index) { tabPanes.forEach(p => p.classList.remove('sca-active')); tabLinks.forEach(l => l.classList.remove('sca-active')); tabPanes[index].classList.add('sca-active'); tabLinks[index].classList.add('sca-active'); } tabLinks.forEach((link, index) => { link.addEventListener('click', () => openTab(index)); }); // --- Event Listeners --- addBtn.addEventListener('click', addFinding); updateConfigBtn.addEventListener('click', () => { projectInfo.name = confProject.value || "Project"; projectInfo.commit = confCommit.value || "N/A"; updateDashboard(); alert("Project details updated."); }); loadSampleBtn.addEventListener('click', loadSampleData); resetBtn.addEventListener('click', () => { if(confirm("Clear all findings?")) { findings = []; confProject.value = ""; confCommit.value = ""; projectInfo = { name: "[Project Name]", commit: "--" }; updateDashboard(); } }); // PDF Generation downloadPdfBtn.addEventListener('click', async () => { const element = document.getElementById('sca-pdf-export-area'); const btn = downloadPdfBtn; btn.textContent = "Generating..."; btn.disabled = true; try { const canvas = await html2canvas(element, { scale: 2, useCORS: true, backgroundColor: '#ffffff' }); const imgData = canvas.toDataURL('image/png'); const { jsPDF } = window.jspdf; const pdf = new jsPDF('p', 'mm', 'a4'); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const margin = 10; const printWidth = pdfWidth - (margin * 2); const imgHeight = (canvas.height * printWidth) / canvas.width; let heightLeft = imgHeight; let position = margin; // First page pdf.addImage(imgData, 'PNG', margin, position, printWidth, imgHeight); heightLeft -= (pdfHeight - margin*2); // Multi-page loop while (heightLeft > 0) { position = heightLeft - imgHeight + margin; pdf.addPage(); pdf.addImage(imgData, 'PNG', margin, position - margin, printWidth, imgHeight); heightLeft -= (pdfHeight - margin*2); } pdf.save('Smart_Contract_Audit_Report.pdf'); } catch (err) { console.error(err); alert("Error generating PDF."); } finally { btn.textContent = "Download Audit Report (PDF)"; btn.disabled = false; } }); // Initialize View updateDashboard(); });
Scroll to Top