A Solidity-based ERC20 vault system that allows users to deposit assets and receive proportional shares, with yield distribution capabilities.
This project implements a vault contract that accepts deposits of an ERC20 asset token and mints vault shares in return. Users can withdraw their proportional share of assets at any time. The vault owner can distribute yield to all shareholders proportionally.
The main vault contract implementing:
- Deposit: Users deposit asset tokens and receive vault shares proportional to their contribution
- Withdraw: Users burn vault shares to receive their proportional amount of assets
- Yield Distribution: Owner can distribute additional yield to all shareholders
- Built on OpenZeppelin's ERC20 and Ownable contracts
Key features:
- Share-to-asset ratio calculation for fair distribution
- First depositor receives 1:1 share ratio
- Subsequent depositors receive shares based on:
(amount * totalSupply) / totalAssets - Zero amount deposit protection
A simple ERC20 token contract used as the asset token for the vault:
- Token Name: BahlulToken
- Symbol: Bahlul
- Public mint and burn functions
Note: This token has no access control on mint/burn - intended for testing purposes only.
.
├── src/
│ ├── Vault.sol # Main vault contract
│ └── Bahlul.sol # Asset token contract
├── script/
│ └── Vault.s.sol # Deployment script
├── test/
│ └── Vault.t.sol # Test suite
└── foundry.toml # Foundry configuration
- Foundry
- Solidity ^0.8.13
# Clone the repository
git clone <your-repo-url>
cd workshop-d1
# Install dependencies
forge installforge buildforge testFor verbose output:
forge test -vvvforge fmtforge snapshotforge script script/Vault.s.sol --rpc-url $RPC_URL -vvvforge script script/Vault.s.sol \
--rpc-url $RPC_URL \
--broadcast \
--verify \
--etherscan-api-key $API_KEY \
-vvvforge script script/Vault.s.sol \
--rpc-url https://base-sepolia.g.alchemy.com/v2/$API_KEY_ALCHEMY \
--broadcast \
--verify \
--etherscan-api-key $API_KEY \
-vvvforge script script/Vault.s.sol --rpc-url https://base-sepolia.g.alchemy.com/v2/$API_KEY_ALCHEMY --broadcast -vvv --verify --etherscan-api-key $ETHERSCAN_API_KEY
RUN -> broadcast, verify
forge script script/Vault.s.sol --rpc-url $RPC_URL --broadcast -vvv --verify --etherscan-api-key $ETHERSCAN_API_KEY
DRY RUN -> no broadcast & verify
forge script script/Vault.s.sol --rpc-url $RPC_URL -vvvEnvironment Variables Required:
PRIVATE_KEY: Your wallet private keyRPC_URL: RPC endpoint URLETHERSCAN_API_KEY: Etherscan/Basescan API key for verification
-
Initial Deployment:
- BahlulToken is deployed first
- Vault is deployed with BahlulToken address as the asset
-
First Deposit:
- User deposits 100 tokens
- Receives 100 shares (1:1 ratio)
- Vault now holds 100 tokens
-
Yield Distribution:
- Owner distributes 50 tokens as yield
- Vault now holds 150 tokens, 100 shares outstanding
-
Second Deposit:
- User deposits 75 tokens
- Receives (75 * 100) / 150 = 50 shares
- Vault now holds 225 tokens, 150 shares outstanding
-
Withdrawal:
- User burns 50 shares
- Receives (50 * 225) / 150 = 75 tokens
The test suite (test/Vault.t.sol) includes:
- Deposit functionality testing
- Withdraw functionality testing
- MockERC20 for isolated testing
Run tests with:
forge test- The BahlulToken has unrestricted mint/burn functions - use only for testing
- Ensure proper approval before depositing into the vault
- The vault owner has privileged access to distribute yield
- Consider adding reentrancy guards for production use
- Consider adding withdrawal limits or cooldown periods
For more information on Foundry:
UNLICENSED