Instant ETH Unstaking with EIP-7702
Skip the 17-46 day Ethereum unstaking queue. Get your ETH instantly.
Zero-Wait Unstaking Using EIP-7702 Hackathon
# Clone and install
git clone <repo-url>
cd flashunstake
npm install
forge install
# Build contracts
forge build
# Run all tests (38 tests)
forge test -vvv
# Deploy to BSC Testnet
forge script script/DeployHackathon.s.sol --rpc-url $BSC_TESTNET_RPC_URL --broadcast --verify| Requirement | Value |
|---|---|
| Testing Contract | StakingVault (deployed address in .env) |
| Testing Token | FUST - FlashUnstake Test Token |
| Chain | BSC Testnet (Chain ID: 97) |
| Lock Time Duration | 3600 seconds (1 hour) |
| EIP-7702 Integration | Yes - Delegated execution, session keys, batch ops |
Traditional Flow (Multiple Transactions):
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Tx 1: │ │ Tx 2: │ │ Tx 3: │
│ Approve │───▶│ Stake │───▶│ Unstake │
│ Tokens │ │ Tokens │ │ (manual) │
└──────────────┘ └──────────────┘ └──────────────┘
Gas: ~50k Gas: ~100k Gas: ~80k
↑
User must wait 3600s
and manually trigger
EIP-7702 Flow (Single Atomic Transaction):
┌─────────────────────────────────────────────────────────────┐
│ ONE TRANSACTION │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌───────────────┐ │
│ │ Approve │─▶│ Stake │─▶│ Schedule│─▶│ Auto-Unstake │ │
│ │ │ │ │ │ │ │ at Unlock │ │
│ └─────────┘ └─────────┘ └─────────┘ └───────────────┘ │
│ │
│ • Batched via EIP-7702 delegation │
│ • One signature, one gas payment │
│ • Auto-executes at exact unlock timestamp │
└─────────────────────────────────────────────────────────────┘
| Contract | Purpose | Key Features |
|---|---|---|
| TestToken.sol | Test ERC20 | EIP-2612 Permit, Faucet, 100M cap |
| StakingVault.sol | Staking with 3600s lock | Multiple positions, EIP-7702 ready |
| EIP7702UnstakeModule.sol | Delegation module | Scheduled auto-unstake, batch execution |
╭──────────────────┬────────┬────────┬─────────╮
│ Test Suite │ Passed │ Failed │ Skipped │
╞══════════════════╪════════╪════════╪═════════╡
│ FlashUnstakeTest │ 13 │ 0 │ 0 │
├──────────────────┼────────┼────────┼─────────┤
│ HackathonTest │ 25 │ 0 │ 0 │
╰──────────────────┴────────┴────────┴─────────╯
Ethereum staking provides ~4% APY, but unstaking is painful:
Traditional Unstaking Flow:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ User has stETH/rETH │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Transaction │ │ Transaction │ │ │ │
│ │ 1: Approve │────▶│ 2: Request │────▶│ WAIT 17-46 DAYS │ │
│ │ stETH │ │ Withdraw │ │ in Exit Queue │ │
│ └─────────────┘ └─────────────┘ └───────────┬─────────────┘ │
│ │ │
│ ▼ │
│ Finally get ETH │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Problems:
• 17-46 day wait time (142,500+ validators in queue)
• 2 separate transactions required
• 2 gas fees to pay
• No liquidity while waiting
• Risk of price changes during wait
FlashUnstake provides instant liquidity for staked ETH using a liquidity pool and EIP-7702 for the best user experience.
FlashUnstake Flow:
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ User has stETH/rETH │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ONE EIP-7702 TRANSACTION │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Approve │───▶│ Swap LST │───▶│ Receive │ │ │
│ │ │ stETH │ │ for ETH │ │ ETH │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │
│ │ All atomic. All in ~12 seconds. │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
│ ✓ Instant (no queue) │
│ ✓ One transaction (not two) │
│ ✓ One signature │
│ ✓ Optional: Zero gas (paymaster sponsored) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ FlashUnstake Protocol │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ │ │ │ │ │ │
│ │ FlashUnstake │ │ Delegator │ │ Paymaster │ │
│ │ (Core Pool) │ │ (EIP-7702) │ │ (Gas Sponsor) │ │
│ │ │ │ │ │ │ │
│ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │ │
│ │ │ │ │
│ ┌────────▼─────────┐ ┌────────▼─────────┐ ┌────────▼─────────┐ │
│ │ • Liquidity Pool │ │ • Batch Calls │ │ • Sponsor Gas │ │
│ │ • Instant Swaps │ │ • One-Click │ │ • User Deposits │ │
│ │ • LP Shares │ │ • Session Keys │ │ • Whitelisting │ │
│ │ • Exit Queue NFT │ │ • ERC-4337 │ │ • Limits │ │
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ EIP-7702 Transaction Flow │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ User's EOA │
│ │ │
│ │ 1. Sign EIP-7702 Authorization │
│ │ (Delegate EOA to FlashUnstakeDelegator contract) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Type 0x04 Transaction │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Authorization List: │ │ │
│ │ │ • chainId: 97 (BSC Testnet) │ │ │
│ │ │ • address: FlashUnstakeDelegator │ │ │
│ │ │ • nonce: 0 │ │ │
│ │ │ • signature: [v, r, s] │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ Calldata: oneClickUnstake(flashUnstake, stETH, amount, minOut) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ 2. EOA temporarily becomes smart contract │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Batched Execution (Atomic): │ │
│ │ │ │
│ │ Step A: stETH.approve(flashUnstake, amount) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ Step B: flashUnstake.instantUnstakeStETH(amount, minOut) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ Step C: ETH sent to user's EOA │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ 3. Delegation ends, EOA returns to normal │
│ ▼ │
│ │
│ User receives ETH instantly! │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ Liquidity Pool Flow │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ LIQUIDITY PROVIDERS UNSTAKERS │
│ ────────────────── ───────── │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ │ │ │ │
│ │ LP deposits│ │ User has │ │
│ │ ETH │ │ stETH/rETH │ │
│ │ │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ FlashUnstake Pool │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ ETH Liquidity Pool LST Holdings │ │ │
│ │ │ ════════════════ ════════════ │ │ │
│ │ │ │ │ │
│ │ │ 100 ETH ◄──────────────────► 50 stETH │ │ │
│ │ │ 30 rETH │ │ │
│ │ │ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ LP Share Tokens (tracks proportional ownership) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ │ │ │ │
│ │ Earn fees │ │ Receive ETH │ │
│ │ from swaps │ │ instantly │ │
│ │ (~7-9% APY) │ │ (0.5% fee) │ │
│ │ │ │ │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ Meanwhile, protocol queues LSTs through Lido/RocketPool │
│ withdrawal queues in the background to replenish ETH │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
- Convert stETH or rETH to ETH in seconds, not weeks
- 0.5% fee (vs waiting 17-46 days)
- Batched Transactions: Approve + unstake in one tx
- Single Signature: Better UX than multi-tx flows
- Gas Sponsorship: Optional gasless transactions
- Session Keys: Delegated access for automation
- LPs provide ETH and earn yield
- ~7-9% APY (staking rewards + swap fees)
- Protocol handles exit queue in background
- Tradeable NFT representing queue position
- Secondary market for exit positions
- Buyers get discounted ETH, sellers get instant liquidity
flashunstake/
├── contracts/
│ ├── FlashUnstake.sol # Main protocol (liquidity pool, swaps)
│ ├── FlashUnstakeDelegator.sol # EIP-7702 delegation, session keys
│ ├── FlashUnstakePaymaster.sol # ERC-4337 gas sponsorship
│ └── interfaces/ # External protocol interfaces
├── frontend/
│ ├── src/
│ │ ├── App.jsx # React frontend (550+ lines)
│ │ ├── index.css # Tailwind + animations
│ │ └── main.jsx # Entry point
│ ├── package.json
│ └── vite.config.js
├── script/
│ └── Deploy.s.sol # Foundry deployment script
├── scripts/
│ └── test-eip7702.ts # TypeScript integration tests
├── test/
│ └── FlashUnstake.t.sol # Solidity unit tests
├── lib/ # Dependencies (forge-std, openzeppelin)
├── foundry.toml # Foundry configuration
├── package.json # NPM configuration
└── README.md
# Clone the repository
git clone https://github.com/flashunstake/flashunstake
cd flashunstake
# Install Foundry (if not already installed)
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Install Foundry dependencies
forge install
# Install Node.js dependencies
npm install
# Install frontend dependencies
cd frontend && npm install && cd ..# Copy environment template
cp .env.example .env
# Edit .env with your values:
# PRIVATE_KEY=your_private_key
# BSC_TESTNET_RPC_URL=https://data-seed-prebsc-1-s1.binance.org:8545
# BSCSCAN_API_KEY=your_api_key# Compile all contracts
forge build
# Run tests
forge test -vvv
# Run tests with gas report
forge test --gas-reportcd frontend
npm run dev
# Opens at http://localhost:3000# Deploy to BSC Testnet
forge script script/Deploy.s.sol --rpc-url $BSC_TESTNET_RPC_URL --broadcast --verify
# After deployment, update .env with contract addresses:
# FLASH_UNSTAKE_ADDRESS=0x...
# DELEGATOR_ADDRESS=0x...
# PAYMASTER_ADDRESS=0x...# TypeScript integration tests for EIP-7702
npx tsx scripts/test-eip7702.ts| Function | Description |
|---|---|
provideLiquidity() |
Deposit ETH, receive LP shares |
withdrawLiquidity(shares) |
Burn shares, receive ETH |
instantUnstakeStETH(amount, minOut) |
Swap stETH for ETH |
instantUnstakeRETH(amount, minOut) |
Swap rETH for ETH |
batchedInstantUnstake(...) |
Multi-token unstake with EIP-7702 |
| Function | Description |
|---|---|
executeBatch(calls) |
Execute multiple calls atomically |
oneClickUnstake(...) |
Approve + unstake in one call |
createSessionKey(...) |
Create limited-access session key |
validateUserOp(...) |
ERC-4337 account validation |
| Function | Description |
|---|---|
validatePaymasterUserOp(...) |
Validate and sponsor user ops |
deposit(user) |
Deposit ETH for user |
setWhitelistedTarget(...) |
Whitelist contracts for sponsorship |
| Parameter | Value |
|---|---|
| Instant Unstake Fee | 0.5% |
| LP Fee Share | 80% |
| Protocol Fee | 20% |
| Minimum Unstake | 0.01 ETH |
| Supported LSTs | stETH, rETH |
| Target LP APY | 7-9% |
| Feature | Traditional Unstaking | FlashUnstake |
|---|---|---|
| Wait Time | 17-46 days | ~12 seconds |
| Transactions | 2 (approve + request) | 1 (EIP-7702) |
| Signatures | 2 | 1 |
| Gas Cost | ~100k total | ~60k |
| Failure Mode | Can fail partially | Atomic (all or nothing) |
| Gas Sponsorship | No | Yes (Paymaster) |
- Only delegate to verified FlashUnstakeDelegator contracts
- Review authorization before signing
- Session keys have limited scope and expiration
- Revoke delegations when not needed
- ReentrancyGuard on all state-changing functions
- Ownable for admin functions
- OpenZeppelin battle-tested libraries
- Slippage protection on all swaps
- Authorization is chain-specific (prevents cross-chain replay)
- Nonce prevents authorization replay
- Delegation can be revoked anytime
| Contract | Address |
|---|---|
| stETH | 0x3e3FE7dBc6B4C189E7128855dD526361c49b40Af |
| rETH | 0x178E141a0E3b34152f73Ff610437A7bf9B83267A |
| Lido Withdrawal Queue | 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1 |
| ERC-4337 EntryPoint | 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 |
| FlashUnstake | Deploy to get address |
| FlashUnstakeDelegator | Deploy to get address |
| FlashUnstakePaymaster | Deploy to get address |
BSC Testnet Details:
- Chain ID: 97
- RPC URL: https://data-seed-prebsc-1-s1.binance.org:8545
- Block Explorer: https://testnet.bscscan.com
- Faucet: https://testnet.bnbchain.org/faucet-smart
# All tests
forge test
# Verbose output
forge test -vvv
# Specific test
forge test --match-test testInstantUnstakeStETH
# Gas report
forge test --gas-report
# Coverage
forge coverage# Solidity linting
forge fmt
# TypeScript linting
npm run lint- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE file for details.
- Website: https://flashunstake.xyz
- Documentation: https://docs.flashunstake.xyz
- Twitter: https://twitter.com/flashunstake
Built for the EIP-7702 Hackathon
"Unstake Instantly. Final Block. Zero Wait."