Reproducible Solidity security laboratories — vulnerable vs. remediated, side by side.
⚠️ For educational use only. TheVulnerable*.solcontracts are intentionally unsafe and must never be deployed. Run them only in a local Foundry test environment.
Each lab is a minimal, self-contained demonstration of one vulnerability class. Every lab contains:
src/Vulnerable*.sol— A minimal contract containing the bug.src/Safe*.sol— The remediated version, with the fix and a comment explaining why it works.test/*.t.sol— A Foundry test that exploits the vulnerable contract and verifies the safe contract resists the same attack.
Tests are reproducible:
forge test -vv
forge fmt --checkThe same checks run automatically in GitHub Actions through .github/workflows/test.yml.
This repository is designed to make vulnerability reasoning reproducible: each lab isolates one failure mode, shows the attack against a vulnerable implementation, then verifies a narrow remediation with a regression test. It is a training and research corpus, not a collection of production contracts.
| # | Lab | Vulnerability class | Status |
|---|---|---|---|
| 01 | Reentrancy | Reentrancy (checks-effects-interactions) | ✅ |
| 02 | tx.origin Authorization | Access control via tx.origin |
✅ |
| 03 | Flash Loan Price Manipulation | Oracle manipulation via single-block borrow | ✅ |
| 04 | Stale Oracle | Missing staleness / heartbeat check | ✅ |
| 05 | Integer Precision Loss | Rounding & precision attacks (EIP-4626 inflation) | ✅ |
| 06 | Sandwich / MEV Front-running | Mempool exploitation | ✅ |
| 07 | Upgradeable Proxy Storage Collision | EIP-1967 vs hand-rolled proxy slots | ✅ |
| 08 | Signature Replay | Missing nonce/deadline/domain binding on signed payouts | ✅ |
| 09 | Privileged Mint | Unprotected supply creation on a backed token | ✅ |
| 10 | Unchecked Return Value | Discarded bool from transfer / low-level call |
✅ |
| 11 | ERC-4626 Inflation Attack | First-depositor share-price inflation via donation | ✅ |
| 12 | Unbounded Loop DoS | Gas-limit denial of service on an unbounded payee list | ✅ |
| 13 | Fee-on-Transfer Accounting | Claims minted from requested, not received, amounts | ✅ |
| 14 | Unprotected UUPS Initializer | Uninitialized proxy takeover via unguarded initialize |
✅ |
.
├── src/
│ ├── VulnerableVault.sol # Lab 01 — vulnerable
│ ├── SafeVault.sol # Lab 01 — remediated
│ ├── VulnerableAccess.sol # Lab 02 — vulnerable
│ ├── SafeAccess.sol # Lab 02 — remediated
│ ├── VulnerableSwap.sol # Lab 03 — vulnerable
│ ├── SafeSwap.sol # Lab 03 — remediated
│ ├── VulnerableLending.sol # Lab 04 — vulnerable
│ ├── SafeLending.sol # Lab 04 — remediated
│ ├── VulnerablePool.sol # Lab 05 — vulnerable
│ ├── SafePool.sol # Lab 05 — remediated
│ ├── VulnerableAmm.sol # Lab 06 — vulnerable
│ ├── SafeAmm.sol # Lab 06 — remediated
│ ├── VulnerableProxy.sol # Lab 07 — vulnerable
│ ├── SafeProxy.sol # Lab 07 — remediated
│ ├── VulnerableSignature.sol # Lab 08 — vulnerable
│ ├── SafeSignature.sol # Lab 08 — remediated
│ ├── VulnerableMint.sol # Lab 09 — vulnerable
│ ├── SafeMint.sol # Lab 09 — remediated
│ ├── VulnerableRouter.sol # Lab 10 — vulnerable
│ ├── SafeRouter.sol # Lab 10 — remediated
│ ├── VulnerableVault4626.sol # Lab 11 — vulnerable
│ ├── SafeVault4626.sol # Lab 11 — remediated
│ ├── VulnerableSplitter.sol # Lab 12 — vulnerable
│ ├── SafeSplitter.sol # Lab 12 — remediated
│ ├── VulnerableFotVault.sol # Lab 13 — vulnerable
│ ├── SafeFotVault.sol # Lab 13 — remediated
│ ├── Erc1967Proxy.sol # Lab 14 helper — minimal ERC-1967 proxy
│ ├── VulnerableUupsVault.sol # Lab 14 — vulnerable
│ └── SafeUupsVault.sol # Lab 14 — remediated
├── test/
│ ├── Reentrancy.t.sol # Lab 01
│ ├── TxOrigin.t.sol # Lab 02
│ ├── FlashLoan.t.sol # Lab 03
│ ├── StaleOracle.t.sol # Lab 04
│ ├── Precision.t.sol # Lab 05
│ ├── Sandwich.t.sol # Lab 06
│ ├── ProxyCollision.t.sol # Lab 07
│ ├── SignatureReplay.t.sol # Lab 08
│ ├── PrivilegedMint.t.sol # Lab 09
│ ├── UncheckedReturn.t.sol # Lab 10
│ ├── InflationAttack.t.sol # Lab 11
│ ├── LoopDoS.t.sol # Lab 12
│ ├── FeeOnTransfer.t.sol # Lab 13
│ └── UupsTakeover.t.sol # Lab 14
├── labs/ # per-lab deep-dive write-ups
│ ├── lab-01-reentrancy/ # Lab 01 README (sources live in src/ and test/)
│ ├── lab-02-tx-origin/ # Lab 02 README + self-contained src/test copy
│ ├── lab-03-flash-loan/ # Lab 03 README + self-contained src/test copy
│ ├── lab-04-oracle-manipulation/ # Lab 04 README + self-contained src/test copy
│ ├── lab-05-integer-precision-loss/ # Lab 05 README + self-contained src/test copy
│ ├── lab-06-sandwich-mev/ # Lab 06 README + self-contained src/test copy
│ ├── lab-07-proxy-storage-collision/ # Lab 07 README + self-contained src/test copy
│ ├── lab-08-signature-replay/ # Lab 08 README + self-contained src/test copy
│ ├── lab-09-privileged-mint/ # Lab 09 README + self-contained src/test copy
│ ├── lab-10-unchecked-return-value/ # Lab 10 README + self-contained src/test copy
│ ├── lab-11-erc4626-inflation/ # Lab 11 README + self-contained src/test copy
│ ├── lab-12-loop-dos/ # Lab 12 README + self-contained src/test copy
│ ├── lab-13-fee-on-transfer/ # Lab 13 README + self-contained src/test copy
│ └── lab-14-uups-initializer/ # Lab 14 README + self-contained src/test copy
├── .github/
│ ├── workflows/
│ │ ├── test.yml # Foundry test + formatting CI
│ │ └── slither.yml # Slither static analysis CI
│ └── scripts/
│ └── check_slither.py # expectations gate over the Slither JSON report
├── slither.config.json # Slither scope (excludes lib/, labs/, test/)
├── foundry.toml # project configuration
├── SECURITY.md
├── CONTRIBUTING.md
└── LICENSE
There are no active Solidity sources at the repository root; contract sources belong in src/ and tests belong in test/.
Each lab contains the following five sections, encoded in the test file's docstring:
- Threat model — Who can call what, and with what assumptions?
- Violated invariant — Which invariant does the bug break?
- Minimal reproduction — A Foundry test that demonstrates the exploit.
- Remediation — The narrow fix, applied to the
Safe*.solcounterpart. - Regression test — A test that re-runs the exploit against the safe contract and asserts it now fails.
Tool output (Slither, Foundry fuzz) is treated as a lead for manual verification rather than a replacement for protocol reasoning.
A second workflow (.github/workflows/slither.yml) runs Slither on every push and enforces three rules encoded in .github/scripts/check_slither.py:
- Lab integrity — the detector for each gateable lab's core class must fire on its
Vulnerable*contract (reentrancy-eth, tx-origin + arbitrary-send-eth, unchecked-transfer). If the lab stops teaching what the tool actually flags, CI fails. - Safe regression — the same detector must stay silent on the
Safe*counterpart, so a refactor cannot reintroduce the lab's bug unnoticed. - Written triage — any remaining High/Medium finding on a
Safe*contract needs an explicit allowlist entry with a reason (scope separation: a Safe contract is remediated for its lab's class, not every class).
Vulnerability classes static analysis cannot see (flash-loan and stale-oracle manipulation, rounding inflation, storage-collision layout, signature replay, missing access control) are deliberately not gated — they are listed in the CI output as the boundary between tooling and manual reasoning.
- Use these examples only in local Foundry test environments.
- Do not deploy the
Vulnerable*.solcontracts on mainnet or any public network. - Do not use them against systems you do not own or have explicit permission to test.
- If you fork this repository for teaching purposes, keep the disclaimer intact.
| Milestone | Target | Status |
|---|---|---|
| 4 core labs | Reentrancy, tx.origin, Flash Loan, Stale Oracle | ✅ Done |
| 6 additional labs | Precision, MEV, Proxy, Signatures, ACL, Low-level calls | ✅ Done |
| 4 companion labs | 4626 inflation, Loop DoS, Fee-on-transfer, UUPS initializer | ✅ Done |
| Slither integration | CI with detection assertions, safe-regression gate and written triage | ✅ Done |
| Invariant fuzzing | Echidna / forge invariant for each lab |
📋 2026 Q4 |
| Blog writeups | Each lab paired with a public write-up | 📋 2027 Q1 |
See CONTRIBUTING.md for the lab template, naming conventions, and PR requirements.
For questions, collaboration, or audit inquiries:
- X: @DeFiAudit
- Telegram: @DefiAudit0x
- Email: defiaudit@gmail.com
MIT — Educational and research material. Vulnerable contracts in this repository are intentionally unsafe and are not production code.