BAP-578 Security Audit
Use this skill to audit, harden, and verify the security posture of BAP-578 Non-Fungible Agents deployments. This skill provides a structured threat model, detailed audit checklist, vulnerability patterns specific to the NFA architecture, and remediation guidance.
When to use this skill
- Performing a security review before mainnet deployment.
- Investigating a suspected vulnerability or anomalous behavior.
- Reviewing access control patterns and ownership boundaries.
- Evaluating the safety of the UUPS upgrade mechanism.
- Assessing logic contract binding risks.
- Verifying fund management safety (deposits, withdrawals, treasury).
- Checking off-chain integrity mechanisms (vault hash verification).
The Four Identity Questions (Security View)
1) Who are you?
The security layer validates trust boundaries and prevents loss. Security auditing for BAP-578 ensures that the contract's identity guarantees (ownership, metadata integrity, fund safety) cannot be subverted by attackers, malicious logic contracts, or administrative errors. The auditor's role is to verify that every claim the contract makes about identity, memory, capability, and trust is actually enforced.
2) What do you remember?
Security memory includes known attack patterns, prior audit findings, guard rails built into the contract, and the threat model specific to BAP-578's architecture. Key patterns to remember:
- ERC-721 + custom state = larger attack surface than plain NFTs
- UUPS proxy = upgrade risk if
_authorizeUpgradeis not properly guarded - Agent balance management = reentrancy risk on withdrawals
- Logic contract binding = external code execution risk
- Free mint mechanics = potential for abuse if not properly constrained
3) What can you do?
Run a structured security audit that produces:
- Threat model with categorized attack vectors
- Function-by-function access control review
- Reentrancy and CEI (Checks-Effects-Interactions) analysis
- Upgrade safety verification
- Fund flow analysis (deposits, withdrawals, treasury)
- Logic contract risk assessment
- Off-chain integrity verification review
- Severity-rated findings with remediation steps
4) How can I trust it?
Every finding maps to a specific function, modifier, or pattern in the contract source. Findings reference line numbers, function names, and concrete attack scenarios. Trust in the audit comes from:
- Reproducible analysis (anyone can verify each finding)
- Standard severity classification (Critical/High/Medium/Low/Informational)
- Concrete proof-of-concept descriptions for each finding
- Clear remediation steps
Threat Model
Attack surface overview
BAP-578 combines multiple patterns that each carry specific risks:
┌─────────────────────────────────────────┐
│ BAP-578 Contract │
├──────────┬──────────┬───────────────────┤
│ ERC-721 │ UUPS │ Custom State │
│ Standard │ Proxy │ (Agents, Funds) │
├──────────┼──────────┼───────────────────┤
│ Transfer │ Upgrade │ Mint (free/paid) │
│ Approval │ Auth │ Fund/Withdraw │
│ Metadata │ Storage │ Logic binding │
│ │ Layout │ Status toggle │
│ │ │ Metadata update │
└──────────┴──────────┴───────────────────┘
↓ ↓
External actors: Logic contracts
(users, attackers) (external code)
Categorized threat vectors
T1: Reentrancy attacks
Target: withdrawFromAgent and any function that sends BNB.
Attack scenario: A malicious contract calls withdrawFromAgent, and the fallback function re-enters the contract before state is updated. If the contract does not follow CEI pattern or use nonReentrant, the attacker can drain the agent's balance.
Verification steps:
- Check that
withdrawFromAgentuses thenonReentrantmodifier. - Verify state is updated (balance decremented) before the external call.
- Confirm
fundAgentdoes not have re-entrancy paths. - Check that the treasury withdrawal (
emergencyWithdraw) is also protected.
T2: Access control bypass
Target: Owner-only and token-owner-only functions.
Attack scenario: An attacker calls setTreasury, setPaused, emergencyWithdraw, or grantAdditionalFreeMints without being the contract owner. Or calls withdrawFromAgent, setAgentStatus, setLogicAddress, or updateAgentMetadata without being the token owner.
Verification steps:
- List all functions with
onlyOwnermodifier. - List all functions with token-owner checks (e.g.,
require(ownerOf(tokenId) == msg.sender)). - Verify no function bypasses these checks.
- Check that
transferOwnershipis properly restricted.
T3: Malicious logic contract binding
Target: setLogicAddress function.
Attack scenario: An attacker tricks a user into binding a malicious logic contract that steals funds or manipulates agent state. Or an attacker deploys a contract that appears safe but has a hidden backdoor.
Verification steps:
- Confirm that only the token owner can set logic address.
- Verify that EOAs (externally owned accounts) are rejected.
- Check whether logic contracts can call back into the main contract.
- Assess what permissions the logic contract has.
T4: Free mint abuse
Target: createAgent free mint logic.
Attack scenarios:
- Sybil attack: create many wallets to claim free mints at scale.
- Bypass self-mint restriction: find a way to mint free tokens to another address.
- Transfer restriction bypass: find a way to transfer free-minted tokens.
Verification steps:
- Confirm free mints require
to == msg.sender. - Verify transfer hook blocks transfers of free-minted tokens.
- Check that
isFreeMintmapping is correctly set at mint time. - Verify that
grantAdditionalFreeMintsis owner-only.
T5: Upgrade safety
Target: UUPS proxy mechanism.
Attack scenarios:
- Unauthorized upgrade: attacker calls
upgradeToorupgradeToAndCall. - Storage collision: new implementation reorders or removes state variables.
- Initialization replay: attacker calls initializer on new implementation.
Verification steps:
- Confirm
_authorizeUpgradeis guarded byonlyOwner. - Verify implementation contract disables initializers in constructor.
- Review storage layout for append-only discipline.
- Check that
reinitializeris used for new initialization logic.
T6: Fund management risks
Target: Agent balances, treasury, and BNB flows.
Attack scenarios:
- Drain agent balance via reentrancy (see T1).
- Treasury address set to attacker's address.
- Emergency withdraw drains all funds.
Verification steps:
- Trace all BNB flows: where does
msg.valuego at mint time? - Verify mint fee calculation is correct.
- Check that treasury address changes are owner-only.
- Verify emergency withdraw sends funds to treasury, not caller.
- Confirm agent withdrawal checks balance before sending.
T7: Off-chain integrity
Target: vaultURI and vaultHash.
Attack scenarios:
- Vault content modified after hash was recorded.
- Vault URI points to malicious content.
- Hash collision (theoretical, not practical with keccak256).
Verification steps:
- Verify that
vaultHashis stored on-chain and updated with metadata updates. - Confirm off-chain consumers verify hash before trusting vault content.
- Check that metadata update emits events for tracking.
T8: Denial of service
Target: setPaused and contract availability.
Attack scenarios:
- Admin key compromise leads to permanent pause.
- Attacker spam-mints to exhaust gas limits in enumeration functions.
Verification steps:
- Confirm pause is owner-only.
- Check if
tokensOfOwneror other view functions can be DOS'd by large token counts. - Verify that pause does not lock funds permanently (withdrawal should work even when paused, or there should be an emergency mechanism).
T9: Merkle tree learning integrity
Target: vaultHash used as Merkle root for learning agents.
Attack scenarios:
- Attacker modifies learning tree data off-chain without updating on-chain root.
- Attacker provides fraudulent Merkle proofs with crafted sibling nodes.
- Learning data poisoning through malicious interaction data.
Verification steps:
- Verify that any claimed learning node can be validated via Merkle proof against the on-chain
vaultHashroot. - Confirm the learning module (logic contract) validates proof integrity before accepting updates.
- Check that
updateAgentMetadatacorrectly updatesvaultHashwhen the Merkle root changes. - Verify that consumers verify proofs before trusting individual learning nodes.
T10: Logic contract as learning module risks
Target: Logic contracts implementing RAG, MCP, or learning modules.
Attack scenarios:
- Logic contract routes to compromised external AI service (MCP pattern).
- RAG logic contract retrieves poisoned vault content.
- Learning module generates invalid Merkle roots.
- Logic contract leaks private learning data through events or public state.
Verification steps:
- Audit the logic contract's external service integrations.
- Verify that learning data is validated before being incorporated into the tree.
- Check that Merkle root computation matches the claimed tree structure.
- Ensure sensitive learning data is not exposed through public view functions.
Audit Checklist
Access Control
- [ ]
setTreasuryrequiresonlyOwner - [ ]
setPausedrequiresonlyOwner - [ ]
emergencyWithdrawrequiresonlyOwner - [ ]
grantAdditionalFreeMintsrequiresonlyOwner - [ ]
setFreeMintsPerUserrequiresonlyOwner - [ ]
_authorizeUpgraderequiresonlyOwner - [ ]
withdrawFromAgentrequires token owner - [ ]
setAgentStatusrequires token owner - [ ]
setLogicAddressrequires token owner - [ ]
updateAgentMetadatarequires token owner - [ ] No unauthorized path to any privileged function
Reentrancy & CEI
- [ ]
withdrawFromAgentusesnonReentrantmodifier - [ ] State updated before external call in
withdrawFromAgent - [ ]
emergencyWithdrawis reentrancy-safe - [ ]
fundAgentcorrectly updates balance before any external interaction - [ ] No unprotected
call.valueortransferpatterns
Fund Safety
- [ ] Mint fee sent to treasury on paid mints
- [ ] Free mints send zero value to treasury
- [ ] Agent balance correctly incremented on
fundAgent - [ ] Agent balance correctly decremented on
withdrawFromAgent - [ ] Withdrawal amount validated against balance
- [ ] Emergency withdraw sends to treasury address only
- [ ] No way to drain funds without proper authorization
Upgrade Safety
- [ ]
_authorizeUpgradeguarded byonlyOwner - [ ] Implementation disables initializers in constructor
- [ ] Storage layout is append-only (no variable reordering)
- [ ]
reinitializerversion incremented for new versions - [ ] Gap variables reserved for future storage expansion
Transfer Restrictions
- [ ] Free-minted tokens cannot be transferred
- [ ]
_updateor_beforeTokenTransferhook enforces restriction - [ ]
isFreeMintmapping set correctly at mint time - [ ] Paid tokens transfer normally
Logic Contract Safety
- [ ] Only token owner can set logic address
- [ ] EOA addresses rejected for logic binding
- [ ]
address(0)correctly unbinds logic - [ ] Logic contract has no callback path to drain funds
Input Validation
- [ ] Metadata strings have reasonable length limits
- [ ] Zero address checks where appropriate
- [ ] Token ID existence validated before operations
- [ ] Amount > 0 for funding and withdrawal
Severity Classification
Critical — Direct fund loss or irreversible control loss. Example: reentrancy allowing balance drain, unauthorized upgrade to malicious implementation.
High — Significant trust or integrity failure. Example: access control bypass on admin functions, transfer restriction bypass for free mints.
Medium — Operational risk or unsafe defaults. Example: missing events for state changes, no pause on critical functions during emergency.
Low — Gas optimization, UX issues, or missing convenience features. Example: unbounded loop in view function, missing input validation on non-critical fields.
Informational — Best practice recommendations, code quality notes, documentation gaps.
Automated Security Tools
Static analysis with Slither
pip install slither-analyzer
slither contracts/NonFungibleAgents.sol --config-file slither.config.json
Key detectors relevant to BAP-578:
reentrancy-eth— reentrancy on BNB transfersunprotected-upgrade— missing_authorizeUpgradeguardunchecked-transfer— missing return value check on callscontrolled-delegatecall— delegatecall to user-controlled addressarbitrary-send-eth— unauthorized BNB transfers
Formal verification with Certora
For critical deployments, write formal verification rules:
rule withdrawPreservesInvariant {
env e;
uint256 tokenId;
uint256 amount;
uint256 balanceBefore = getAgentState(tokenId).balance;
withdrawFromAgent(e, tokenId, amount);
uint256 balanceAfter = getAgentState(tokenId).balance;
assert balanceAfter == balanceBefore - amount;
}
Gas griefing analysis
Check that no function can be griefed by sending excessive gas or triggering out-of-gas:
tokensOfOwnerwith a user holding many tokensemergencyWithdrawwith large contract balancecreateAgentwith very long metadata strings
Common Vulnerability Patterns
Pattern: Unchecked return values
Solidity call returns a boolean. If not checked, failed transfers silently succeed in the contract's view.
// VULNERABLE
(bool success, ) = payable(owner).call{value: amount}("");
// Missing: require(success, "Transfer failed");
Pattern: Front-running
If mint fees or free mint allocations can be observed in the mempool, attackers may front-run to claim free mints or manipulate pricing.
Mitigation: Free mint allocation is per-address and checked on-chain, so front-running is limited. However, if dynamic pricing is added, commit-reveal patterns may be needed.
Pattern: Integer overflow/underflow
Solidity 0.8+ has built-in overflow checks. Verify the contract uses Solidity >= 0.8.0. If using unchecked blocks, verify arithmetic safety manually.
Audit Report Template
BAP-578 Security Audit Report
══════════════════════════════
Date: YYYY-MM-DD
Auditor: [name/team]
Commit: [git hash]
Scope: NonFungibleAgents.sol + dependencies
Summary
───────
Critical: 0
High: 0
Medium: 0
Low: 0
Informational: 0
Findings
────────
[ID] [Severity] [Title]
Location: [contract]:[function]:[line]
Description: [what was found]
Impact: [what could happen]
Recommendation: [how to fix]
Status: [open/fixed/acknowledged]
Conclusion
──────────
[overall assessment and deployment recommendation]
Output Format
When asked to audit BAP-578, respond with:
- Scope (what was reviewed)
- Summary of findings (critical/high/medium/low counts)
- Detailed findings with function names, severity, and reasoning
- Recommended fixes for each finding
- Residual risks that cannot be fully mitigated
- Deployment recommendation (proceed / fix first / do not deploy)
Related Skills
bap578bap578-upgradebap578-scanner
Scan to join WeChat group