A permissionless ETF token protocol built on Plasma mainnet using bonding curve mechanics with virtual liquidity.
This protocol allows users to create and trade ETF tokens through bonding curve pools. Each ETF token is non-transferable, ensuring all trading happens on-protocol via buy() and sell() functions against the vault. The protocol captures fees on every transaction and distributes them through a sophisticated fee management system.
- π Immutable Parameters: Fee percentages and trading limits cannot be changed after deployment
- π« Non-transferable Tokens: All volume stays on-protocol for simplified fee collection
- π Bonding Curve Pricing: Uses
xy=kformula with virtual liquidity (10k USDT, 1B ETF tokens) - π° Fee Distribution: Automated distribution for buybacks, treasury, creator splits, and executor rewards
- βΈοΈ Emergency Controls: Pause/unpause functionality for each vault
- π‘οΈ Security First: Comprehensive security measures and access controls
- Factory: Deploys new ETF vaults and tokens
- ETFVault: Core bonding curve logic and trading
- ETFToken: Non-transferable ERC-20 token
- FeeManager: Handles fee collection and distribution
- AMMAdapter: Interface for external DEX interactions
- Virtual Reserves: 10,000 USDT and 1,000,000,000 ETF tokens
- Initial Price: 0.01 USDT per ETF token
- Price Discovery: Price increases as more tokens are bought
- Fee Structure: Configurable buy/sell fees (max 10%)
# Clone the repository
git clone https://github.com/tensionfund/etf-bonding-curve-protocol.git
cd etf-bonding-curve-protocol
# Install dependencies
npm install
# Compile contracts
npm run compile
# Run tests
npm test
# Deploy to local network
npm run deploy:localconst factory = await ethers.getContractAt("Factory", factoryAddress);
const tx = await factory.createETF(
"My ETF", // Name
"METF", // Ticker
"https://...", // Image URL
300, // Buy fee (3%)
300, // Sell fee (3%)
ethers.parseEther("10"), // Min trade size
1000 // Max trade percent (10%)
);const vault = await ethers.getContractAt("ETFVault", vaultAddress);
const tx = await vault.buy(
ethers.parseEther("100"), // USDT amount
ethers.parseEther("9000") // Min tokens expected
);const tx = await vault.sell(
ethers.parseEther("1000"), // Token amount
ethers.parseEther("90") // Min USDT expected
);Fees are distributed according to configurable percentages:
- Buybacks: 40% (default)
- Treasury: 40% (default)
- Creator: 15% (default)
- Executor: 5% (default)
- Reentrancy protection: All trading functions protected
- Emergency pause: Vault-level pause functionality
- Access controls: Admin-only functions properly protected
- Input validation: Comprehensive parameter validation
- Slippage protection: Min amount out validation
The test suite covers:
- Token minting/burning
- Bonding curve calculations
- Fee collection and distribution
- Access controls
- Emergency functions
- Integration scenarios
Run tests with:
npm test# Start local node
npm run node
# Deploy contracts
npm run deploy:local# Deploy to Plasma mainnet
npm run deployFor detailed deployment instructions, see DEPLOYMENT.md.
deploy.js: Deploy all contractsinitializeVault.js: Initialize and inspect vaultsfeeManagerOps.js: Execute fee management operations
Update hardhat.config.js for your network:
networks: {
plasma: {
url: "https://rpc.plasma.dog",
chainId: 161221135,
accounts: [process.env.PRIVATE_KEY]
}
}- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
For questions or support, please open an issue on GitHub.
MIT License - see LICENSE file for details.