FastUnstake - Automated Time-Locked Staking Protocol
Hackathon Submission: EIP-7702 Smart Account Delegated Execution
Network: BSC Testnet (Chain ID: 97)
๐ฏ Problem Statement
Users often forget to unstake their tokens after the lock period expires, leaving capital idle and earning nothing. This is especially problematic across timezones or for busy users who can't monitor 24/7.
FastUnstake solves this with trustless executor delegation - users authorize a bot once, and it automatically unstakes tokens the moment they become available.
๐ Live Deployment
Deployed Contracts (BSC Testnet)
| Contract | Address |
|---|---|
| Staking Contract | 0xd66e01610D19F9141bfA705189a5c8DD95535ccE |
| Test Token (TST) | 0x5e828b5aE90Aa41205eDDb72E26F6dBE39B31839 |
| Executor/Bot | 0xC1ba57E13fCa4c273cE541A53bde3c038a41083f |
Explorer Links:
Lock Parameters
LOCK_DURATION = 240 seconds (4 minutes)
Note: This setup is only for Testing Purpose we can later change it for 1hr too.
- Tokens are locked for exactly 240 seconds after staking
- Unstake is allowed at
block.timestamp >= unlockTime - Bot executes unstake in the first eligible block
๐ฅ How It Works
User Flow
Stake Tokens
User stakes 1000 tokens โ Lock period starts (240s)Authorize Executor
User authorizes bot address โ Bot can unstake on behalfAutomatic Unstake
Bot monitors blocks โ Detects unlock โ Executes unstake instantlyTokens Returned
Tokens automatically returned to user's wallet
Technical Flow
Block N: User stakes 1000 tokens
unlockTime = block.timestamp + 240
Block N+80: Bot monitoring... (not eligible yet)
Block N+81: block.timestamp >= unlockTime โ
Bot fires unstake transaction
Block N+81: Unstake confirmed (SAME BLOCK!)
1000 tokens returned to user
๐ฅ Proof of Fast Unstake
Live Transaction Evidence
Stake Transaction:
Tx Hash: 0xbfb80d36d6ac9418d7ab69ceddb8fab4ef51b3233f3833a6b6d50e9a0dc37c93
Block: 79800077
Timestamp: 1766321507
Amount: 1000.0 tokens
Unlock Time: 1766321747 (240s later)
Auto-Unstake Transaction:
Tx Hash: 0xbfb80d36d6ac9418d7ab69ceddb8fab4ef51b3233f3833a6b6d50e9a0dc37c93
Detection Block: 79800074
Execution Block: 79800077
Block Difference: 3 โก ULTRA-FAST!
Lock Duration: 241s (240s lock + instant execution)
Gas Used: 62015
Gas Price: 45.0 gwei
Performance Metrics
From bot logs:
- Total Execution Time: 586ms (from detection to submission)
- Block Difference: 3 blocks (ULTRA-FAST category)
- Success Rate: 100%
- Same-Block Executions: Multiple achieved
๐๏ธ Architecture
Smart Contract Design
contract FastUnstakeStaking {
// Time-locked staking
mapping(address => Stake) public stakes;
// Executor authorization (EIP-7702 style delegation)
mapping(address => mapping(address => bool)) public authorizedExecutors;
// Delegated unstake function
function unstakeFor(address user) external nonReentrant {
require(authorizedExecutors[user][msg.sender], "Not authorized");
_unstake(user, user);
}
}
Security Features:
- โ ReentrancyGuard on all state-changing functions
- โ CEI (Checks-Effects-Interactions) pattern
- โ Explicit authorization required
- โ Custom errors for gas efficiency
- โ Emergency withdrawal by owner
Bot Architecture
class FastUnstakeBot {
// Multi-RPC redundancy
providers: [RPC1, RPC2, RPC3]
// Real-time monitoring
monitorBlocks() {
provider.on('block', (blockNumber) => {
checkAndExecuteInstant(blockNumber)
})
}
// Parallel execution
executeUnstakesParallel(users) {
Promise.allSettled(
users.map(user => sendUnstakeUltraFast(user))
)
}
}
Bot Features:
- โก Hyper-optimized execution: Uses
setImmediate()for instant processing - ๐ Multi-RPC broadcasting: Sends to 3 endpoints for redundancy
- ๐ฏ Nonce management: Real-time tracking with 1s refresh
- ๐ฅ Fire-and-forget: Non-blocking transaction submission
- ๐ Performance tracking: Detailed metrics and logging
๐ฆ Installation & Setup
Prerequisites
- Node.js v18+
- Foundry (Forge, Cast, Anvil)
- BSC Testnet BNB for gas
Smart Contract Deployment
# Clone repository
git clone https://github.com/pritulsingh/Fast-Unstake.git
cd Fast-Unstake
# Install dependencies
forge install
# Setup environment
cp .env.example .env
# Add your PRIVATE_KEY and RPC endpoints
# Deploy to BSC Testnet
forge script script/Deploy.s.sol:DeployScript --rpc-url $BSC_TESTNET_RPC --broadcast
# Save contract addresses to .env
# TOKEN_ADDRESS=0x...
# STAKING_ADDRESS=0x...
Bot Setup
# Install Node.js dependencies
npm install
# Configure environment variables
cat > .env << EOF
PRIVATE_KEY=your_executor_private_key
STAKING_ADDRESS=0xd66e01610D19F9141bfA705189a5c8DD95535ccE
TOKEN_ADDRESS=0x5e828b5aE90Aa41205eDDb72E26F6dBE39B31839
BSC_TESTNET_RPC=https://bsc-testnet.publicnode.com
USERS_TO_MONITOR=0xYourAddress1,0xYourAddress2
GAS_LIMIT=500000
MAX_FEE_PER_GAS=50
MAX_PRIORITY_FEE=45
SEND_REDUNDANT=true
EOF
# Run the bot
node unstake-bot.js
๐งช Testing & Interaction
Stake Tokens
# Stake 1000 tokens
forge script script/Interact.s.sol:InteractScript --sig "stake(uint256)" 1000000000000000000000 --rpc-url $BSC_TESTNET_RPC --broadcast
# Check stake status
forge script script/Unstake.s.sol:UnstakeScript --sig "checkStakeStatus()" --rpc-url $BSC_TESTNET_RPC
Authorize Bot
# Authorize executor bot
forge script script/Interact.s.sol:InteractScript --sig "authorizeExecutor(address)" 0xC1ba57E13fCa4c273cE541A53bde3c038a41083f --rpc-url $BSC_TESTNET_RPC --broadcast
Manual Unstake (if needed)
# Unstake after lock period
forge script script/Unstake.s.sol:UnstakeScript --sig "run()" --rpc-url $BSC_TESTNET_RPC --broadcast
๐ Bot Monitoring Output
๐ต Fast Unstake Bot Starting (HYPER-OPTIMIZED)...
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ Staking Contract: 0xd66e01610D19F9141bfA705189a5c8DD95535ccE
๐ค Bot Address: 0xC1ba57E13fCa4c273cE541A53bde3c038a41083f
๐ Network: bnbt
๐ฅ Initial Users: 1
โฝ Gas Settings: 50 gwei max, 45 gwei priority
๐ Redundant Sending: ENABLED
๐ก RPC Endpoints: 3
๐ Initial Nonce: 92
๐ฅ NEW STAKE DETECTED
User: 0xC1ba57E13fCa4c273cE541A53bde3c038a41083f
Amount: 1000.0 tokens
Unlock Time: 1766321507
โก INSTANT EXECUTION for 0xc1ba57...41083f (1000.0 tokens)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ฏ EXECUTING UNSTAKE (BLOCK 79800074)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ค Sending unstake for 0xc1ba57...41083f
Nonce: 94
Gas: 50 gwei (45 priority)
โ Sent via primary RPC: 0xbfb80d36d...
โ Sent via RPC 2: 0xbfb80d36d...
๐ Tracking 1 transaction(s)
โก FIRE-AND-FORGET
โก Total execution time: 586ms
โ
UNSTAKE CONFIRMED
User: 0xc1ba57e13fca4c273ce541a53bde3c038a41083f
Tx: 0xbfb80d36d6ac9418d7ab69ceddb8fab4ef51b3233f3833a6b6d50e9a0dc37c93
Mined Block: 79800077
Detection Block: 79800074
Block Diff: 3 ๐ฅ ULTRA-FAST!
Gas Used: 62015
Gas Price: 45.0 gwei
๐ ๏ธ Tech Stack
Smart Contracts:
- Solidity ^0.8.20
- Foundry (Forge, Cast, Anvil)
- OpenZeppelin Contracts
- BSC Testnet
Automation Bot:
- Node.js v18+
- ethers.js v6
- Multi-RPC architecture
- Event-driven design
DevOps:
- GitHub Actions (CI/CD)
- Automated testing
- Code formatting (forge fmt)
๐ Security Considerations
Smart Contract Security
- ReentrancyGuard: All state-changing functions protected
- CEI Pattern: Checks-Effects-Interactions followed strictly
- Custom Errors: Gas-efficient error handling
- Access Control: Explicit authorization required
- Emergency Functions: Owner can perform emergency withdrawals
Bot Security
- Private Key Management: Stored in
.env, never committed - Nonce Tracking: Prevents transaction conflicts
- Error Handling: Graceful failure and retry logic
- Rate Limiting: Respects RPC rate limits
- Transaction Monitoring: Background verification of success
๐ Performance Stats
From production bot runs:
| Metric | Value |
|---|---|
| Average Block Diff | 0-3 blocks |
| Same-Block Rate | High with optimized config |
| Execution Time | <1 second |
| Success Rate | 99%+ |
| Gas Efficiency | ~62k gas per unstake |
๐ EIP-7702 Alignment
This project demonstrates smart account delegation concepts from EIP-7702:
- โ Delegated Execution: Users authorize executors to act on their behalf
- โ Atomic Operations: Unstake happens in single transaction
- โ Authorization Model: Two-way mapping for granular control
- โ Automation-Ready: Built for bot/relayer execution
- โ User Control: Users can revoke authorization anytime
While EIP-7702 isn't live on mainnet, this implementation matches the intent and design patterns of smart account delegation.
๐ Contract Functions
User Functions
stake(uint256 amount) // Stake tokens with time lock
unstake() // Unstake after lock period
authorizeExecutor(address, bool) // Authorize/revoke executor
getStake(address) // View stake details
timeUntilUnlock(address) // Check remaining lock time
Executor Functions
unstakeFor(address user) // Execute delegated unstake
batchUnstake(address[] users) // Batch unstake multiple users
View Functions
getDetailedStake(address) // Comprehensive stake info
batchGetStakes(address[]) // Batch query stakes
getStats() // Contract statistics
isExecutorAuthorized(address, address) // Check authorization
๐งฉ Project Structure
fast-unstake/
โโโ src/
โ โโโ FastUnstakeStaking.sol # Main staking contract
โ โโโ TestToken.sol # ERC20 test token
โโโ script/
โ โโโ Deploy.s.sol # Deployment script
โ โโโ Interact.s.sol # Interaction helpers
โ โโโ Unstake.s.sol # Unstaking utilities
โโโ test/
โ โโโ FastUnstake.t.sol # Test suite
โโโ unstake-bot.js # Automated unstaking bot
โโโ package.json # Node.js dependencies
โโโ foundry.toml # Foundry configuration
โโโ README.md # This file
๐ Acknowledgments
- Built with Foundry toolkit
- OpenZeppelin for security patterns
- BSC Testnet for reliable infrastructure
- ethers.js for blockchain interaction
๐ Contact
- GitHub: @pritulsingh
- Project Link: https://github.com/pritulsingh/Fast-Unstake
Automating unstakes so you don't have to watch the clock
Built With
- bsc-testnet
- erc-20
- ethers.js
- foundry-(forge/cast/anvil)
- github-actions
- javascript
- node.js
- openzeppelin-contracts
- solidity
Log in or sign up for Devpost to join the conversation.