A smart contract audit is one of the most important investments you’ll make before launching your protocol. But the value you get depends heavily on preparation. We’ve audited projects that were ready to go and projects that… weren’t. The difference in outcomes is dramatic.
Proper preparation doesn’t just make the audit faster—it makes it better. Auditors can focus on finding real vulnerabilities instead of documenting obvious issues. You get deeper analysis, more actionable findings, and a more secure protocol.
Here’s how to set your audit up for success.
Timeline: Start Earlier Than You Think
The single biggest mistake we see: teams reaching out for an audit two weeks before their planned launch.
Quality audits take time. Our typical engagement is 2-4 weeks of active review, depending on codebase size. Add lead time (most reputable auditors are booked 2-4 weeks out), time for you to fix issues, and re-review of fixes. You’re looking at 6-8 weeks minimum from “let’s get an audit” to “we’re clear for launch.”
Recommended Timeline
- 8+ weeks before launch: Initial audit inquiry and scoping
- 6 weeks before: Audit begins (code should be feature-complete)
- 4 weeks before: Initial report delivered
- 3 weeks before: Fixes implemented
- 2 weeks before: Fix verification complete
- Launch: With confidence
This assumes no critical issues requiring significant refactoring. If we find architectural problems, you’ll need more time. Better to discover that with buffer than to scramble.
Code Readiness
Feature Completeness
Your code should be feature-complete before the audit begins. This doesn’t mean it’s perfect—that’s what the audit is for. It means:
- All intended functionality is implemented
- No placeholder functions or “TODO: implement later” comments
- Business logic reflects actual intended behavior
- Integration points with external protocols are connected
Auditing incomplete code wastes time. We analyze behavior A, you change it to behavior B, and our analysis is invalidated. Worse, changes during audit can introduce new vulnerabilities we’ve already moved past.
Code Quality
Clean code is faster to audit and receives deeper analysis. Before submitting:
Do:
- Remove dead code and unused imports
- Resolve all compiler warnings
- Use consistent formatting (Prettier, Forge fmt)
- Use descriptive variable and function names
- Follow established patterns (CEI, OpenZeppelin standards)
Don’t:
- Leave debug code or console.logs
- Include experimental features you’re “testing”
- Have multiple implementations of the same logic
- Use obscure optimizations without comments
Compilation and Tests
This sounds obvious, but verify:
- Code compiles without errors on the specified Solidity version
- All existing tests pass
- Instructions to build and test are accurate
We’ve received codebases where the provided test command fails immediately. That’s not a great start.
Documentation: Your Audit Accelerator
Good documentation is the single biggest factor in audit quality. It lets us understand your intent, not just your implementation. When intent and implementation diverge, that’s often where vulnerabilities hide.
Essential Documentation
1. System Overview
A high-level description of what your protocol does. Written for someone intelligent but unfamiliar with your specific project. Include:
- What problem does this solve?
- Who are the users and what do they do?
- What are the key invariants that must always hold?
2. Architecture Diagram
Visual representation of contract relationships. Show:
- All contracts in scope
- Inheritance relationships
- External protocol integrations
- Flow of funds
Tools like Sol2UML can generate these automatically.
3. Function-Level Descriptions
For each external/public function:
- What does it do?
- Who should be able to call it?
- What are the expected inputs and outputs?
- What state does it modify?
This can be NatSpec comments in the code itself:
/// @notice Deposits assets and mints shares to the receiver
/// @dev Follows ERC-4626 standard
/// @param assets Amount of underlying tokens to deposit
/// @param receiver Address that will receive the minted shares
/// @return shares Amount of shares minted
function deposit(
uint256 assets,
address receiver
) external returns (uint256 shares) {
// ...
} 4. Known Issues and Design Decisions
Don’t hide things you’re unsure about. Tell us:
- Areas you’re concerned about
- Trade-offs you’ve made intentionally
- External dependencies and trust assumptions
- Any issues found in previous audits
This helps us prioritize. If you tell us “the oracle integration worries us,” we’ll give it extra attention. If you tell us “we intentionally allow X because Y,” we won’t waste time reporting something you’ve already considered.
5. Deployment and Configuration
- What network(s) will this deploy to?
- What are the deployment parameters?
- Who controls admin functions?
- What’s the upgrade strategy (if any)?
Scoping: Define What Matters
In-Scope vs. Out-of-Scope
Be explicit about what you want audited:
Typically In-Scope:
- Your protocol’s smart contracts
- Custom libraries you’ve written
- Integration logic with external protocols
Typically Out-of-Scope:
- External protocol contracts (Uniswap, Aave, etc.)
- Frontend code
- Off-chain infrastructure
- Test files
Lines of Code
We price partially based on codebase size. Use tools like CLOC or Solidity Metrics to count:
- Lines of Solidity code (excluding comments and blanks)
- Number of contracts
- Number of external/public functions
This helps both scoping and scheduling.
Complexity Factors
Some code requires more time per line. Let us know if your protocol involves:
- Complex mathematical formulas (AMM curves, yield calculations)
- Assembly or Yul
- Novel cryptographic primitives
- Cross-chain messaging
- Upgradeable proxy patterns
- Integration with multiple external protocols
Testing: Your First Line of Defense
Good tests catch obvious issues before the audit, freeing auditors to find subtle ones.
Test Coverage
We recommend >90% line coverage for code in scope. Tools to measure:
But coverage alone isn’t enough. 100% coverage with only happy-path tests misses most vulnerabilities.
Test Types
Unit Tests: Test individual functions in isolation
- Do they behave correctly with valid inputs?
- Do they revert appropriately with invalid inputs?
- Are edge cases handled?
Integration Tests: Test contract interactions
- Do contracts work together as expected?
- Are external integrations handled correctly?
Fuzz Tests: Foundry’s killer feature
- Feed random inputs to find unexpected behavior
- Particularly valuable for mathematical functions
function testFuzz_DepositWithdraw(uint256 amount) public {
vm.assume(amount > 0 && amount <= 1e30);
token.mint(address(this), amount);
token.approve(address(vault), amount);
uint256 shares = vault.deposit(amount, address(this));
uint256 withdrawn = vault.redeem(shares, address(this), address(this));
// Invariant: should get back at least amount - 1 (rounding)
assertGe(withdrawn, amount - 1);
} Invariant Tests: Define properties that should always hold
- Total shares equals sum of individual balances
- Contract balance >= sum of deposits
- No user can withdraw more than deposited
Share Your Tests
Include test files with your audit submission. Tests are documentation—they show us what behavior you expect and what edge cases you’ve considered.
Security Measures Already in Place
Tell us what you’ve already done:
- Previous audits (include reports)
- Static analysis tool results (Slither, Mythril)
- Formal verification (if any)
- Bug bounty programs
This isn’t about impressing us—it’s about efficiency. If Slither already flagged something and you’ve addressed it, we don’t need to re-analyze. If you’ve had a previous audit, we can focus on changes and areas the previous auditor might have missed.
The Kick-off Call
Most engagements start with a call. Come prepared with:
- A demo of the protocol (testnet or local)
- Answers to questions about architecture
- Prioritized list of concerns
- Timeline constraints we should know about
This call often surfaces implicit assumptions that aren’t in any document. “Oh, we expect that oracle to always return X” is exactly the kind of detail that matters.
During the Audit
Responsiveness
Questions will come up. Quick responses keep momentum:
- Designate a technical point of contact
- Check your audit communication channel daily
- Prepare teammates to answer questions in specific areas
No Code Changes
Once the audit starts, freeze the codebase. If you find a bug, document it and wait—changing code invalidates analysis we’ve already done.
Exception: if we find a critical issue, we’ll discuss whether immediate fixing makes sense.
Expectation Setting
Not all findings will be critical. Expect:
- Critical/High: Real vulnerabilities that need fixing
- Medium: Issues that could be problems under specific conditions
- Low: Best practice violations and minor issues
- Informational: Suggestions and observations
A good audit should find something. If a report comes back empty, either the code is extraordinarily clean (rare) or the audit wasn’t thorough enough.
After the Report
Fix Verification
We include verification of critical and high fixes in our standard engagements. To expedite:
- Make fixes in a clearly labeled branch
- Document what you changed and why
- Run your test suite to confirm nothing broke
- Let us know when fixes are ready for review
Public Disclosure
Decide ahead of time whether you’ll publish the report. We recommend transparency—published audits build community trust. But it’s your choice.
If publishing, consider:
- Timing (after fixes are deployed)
- Whether to include fix verification results
- How to communicate any remaining known issues
Preparation Checklist
Use this before reaching out:
- Code is feature-complete
- All tests pass
- Test coverage >90%
- System documentation exists
- Architecture diagram prepared
- Key invariants documented
- Known issues listed
- In-scope contracts identified
- Lines of code counted
- Timeline allows 6-8 weeks
- Technical contact designated
The more boxes you check, the more value you’ll get from your audit. An auditor’s time is finite—help us spend it finding real issues, not documenting basics.
Ready to get started? Request an audit quote and let’s discuss your protocol’s security needs.
Ready to Secure Your Project?
Whether you're preparing for launch or strengthening an existing protocol, we're here to help. Get in touch for a confidential conversation about your security needs.