burneh
Crypto

Contracts that hold up when the money is real.

A contract is the one thing you can't patch after it ships. So we write it to be read: clean, tested to the edges, static-analyzed, and audit-ready before a cent goes near it.

Start a build
98% coverage0 slither findingsaudit-ready
forge test
deposit credits the sender
withdraw respects the balance
reentrancy is blocked
only owner can pause
invariant: vault ≥ Σ balances
fuzz: no overflow on deposit
0/6 passingcoverage 98%slither: 0
forge test --fuzz0 / 10,000 runs
→ deposit(0x8f3a…, 4.2)
invariant: vault ≥ Σ balances · holds

Green tests are the floor. The real work is the code being readable enough that a reviewer can trust it, and hard enough that the fuzzer can't break it.

Watch an attacker try to drain the vault.

The classic exploit: a malicious contract re-enters withdraw before the balance updates. Turn the guard off and watch the vault empty. Turn it on and the same attack reverts.

call stack
the vault
6.0 ETH
running…

Checks-effects-interactions plus a nonReentrant guard. The balance is zeroed before the external call, so the re-entry finds nothing to take.

Written to be read.

Most exploits live in code the author found clever. We don't write clever. A reviewer should be able to read a function top to bottom and know it's safe.

Vault.sol
1error InsufficientBalance();
2
3contract Vault {
4 mapping(address => uint256) public balanceOf;
5 bool private locked;
6
7 event Withdrawn(address indexed user, uint256 amount);
8
9 modifier nonReentrant() {
10 require(!locked, "reentrant"); // ← the guard
11 locked = true;
12 _;
13 locked = false;
14 }
15
16 function withdraw(uint256 amount) external nonReentrant {
17 if (balanceOf[msg.sender] < amount) revert InsufficientBalance();
18
19 balanceOf[msg.sender] -= amount; // effects first
20 emit Withdrawn(msg.sender, amount);
21
22 (bool ok, ) = msg.sender.call{value: amount}(""); // interaction last
23 require(ok, "transfer failed");
24 }
25}
Effects before interactions

The balance is updated before the external call, so a callback can't drain the vault twice.

A reentrancy guard

nonReentrant locks the function for the duration of the call. Belt and braces.

Custom errors

Cheaper than revert strings, and the reason is a type, not a guess.

An event for every move

So the indexer and the user can both follow what happened.

Tested like it holds money, handed over clean.

We write the properties that must always hold and let the fuzzer attack them, then hand the auditor a documented, analyzed, threat-modeled contract, not a pile of surprises.

The vault never holds less ETH than the sum of balances.
No account can withdraw more than it deposited.
A paused contract rejects every deposit and withdrawal.
Only the owner can transfer ownership, once accepted.
holds across 10,000 fuzz runs · invariant suite green
Audit-readinesshanded to the auditor
Static analysis clean
Slither and Aderyn run in CI; a new finding fails the build.
Access control mapped
Every privileged function, who can call it, and why, in writing.
Upgrade path decided
Immutable, or a transparent proxy behind a timelock. Your call, on paper.
Threat model written
How it could be attacked, and how each path is closed, for the auditor.
NatSpec on every function
So the reviewer reads the intent instead of guessing it.
Known-vuln checklist
Reentrancy, overflow, oracle, access, front-running, each signed off.
Ready for review before a cent goes in.

Contracts that hold up when the money is real.

Written to be read, tested to the edges, static-analyzed, and audit-ready before a cent goes near it. The one thing you can't patch, done right the first time.