Simple demonstration of library-based protocol architecture in Solidity.
The project shows how reusable guard logic can be separated from protocol state using libraries, while maintaining safe state transitions and testable behavior.
Built with Foundry.
This repository implements a minimal ETH Vault that supports:
- Deposits
- Withdrawals
- Balance validation via a reusable library guard
The goal is to demonstrate the architectural pattern:
Contracts → protocol state Libraries → reusable logic Tests → state transition verification
This separation improves code reuse, readability, and auditability.
Reusable guard logic used by the protocol.
function requireBalance(uint256 available, uint256 required) internal pure
The function reverts with a custom error if a user attempts to withdraw more than their balance.
Key properties:
implemented as an internal Solidity library
uses custom errors for gas efficiency
reusable across multiple contracts
Vault
Protocol contract responsible for:
holding ETH custody
tracking user balances
executing deposits and withdrawals
State:
mapping(address => uint256) public balances;
Conceptual invariant:
sum(balances) == address(vault).balance
Withdrawals follow the Checks → Effects → Interactions pattern to prevent reentrancy.
Testing
Tests are written using Foundry.
Covered scenarios:
deposit increases user balance
withdraw decreases user balance and transfers ETH
withdraw above balance reverts with InsufficientBalance
Run tests with:
forge test -vv
Project Structure
src/
BalanceLib.sol
Vault.sol
test/
Vault.t.sol
Key Concepts Demonstrated
Solidity libraries
using for pattern
custom errors
protocol accounting vs EVM balance
checks-effects-interactions
Foundry testing workflow
Build & Test
forge build
forge test
forge fmt
Why Libraries?
Libraries allow protocol logic to be reused safely across contracts without duplicating code.
Benefits:
smaller attack surface
easier audits
consistent validation logic
cleaner contract architecture
License
MIT