Remember when yield farming meant frantically refreshing Etherscan while your transaction fees exceeded your actual yield? Those days are gone, my friend. Thanks to Cairo 1.0 Starknet yield farming, you can now build DeFi protocols that don't require selling a kidney for gas fees.
If you've been building on Ethereum and wondering why your users complain about $200 transaction costs, this guide shows you how zero-knowledge proofs solve real problems. We'll build a complete yield farming protocol that scales without breaking the bank.
What Makes Starknet Different for Yield Farming
Starknet uses zero-knowledge proofs to bundle thousands of transactions into single Ethereum blocks. Your yield farming protocol can process complex calculations off-chain while maintaining security through cryptographic proofs.
Why Cairo 1.0 Changes Everything
Cairo 1.0 introduced Rust-like syntax that makes smart contract development actually enjoyable. No more wrestling with abstract stack operations or debugging cryptic error messages.
// Cairo 1.0 syntax is clean and readable
#[contract]
mod YieldFarm {
use starknet::ContractAddress;
#[storage]
struct Storage {
total_staked: u256,
user_stakes: LegacyMap<ContractAddress, u256>,
reward_rate: u256,
}
}
Understanding Zero-Knowledge Proofs in DeFi
Zero-knowledge proofs let you verify computations without revealing the actual data. For yield farming, this means:
- Privacy: Users can stake without exposing wallet balances
- Scalability: Bundle multiple farming operations into single proofs
- Cost Efficiency: Pay cents instead of dollars per transaction
The Magic Behind StarkEx Protocol
StarkEx processes over 9,000 transactions per second while maintaining Ethereum-level security. Your yield farm inherits this performance automatically.
Building Your First Cairo 1.0 Yield Farm
Let's create a yield farming contract that rewards users based on staking duration and amount. This example demonstrates core Cairo 1.0 patterns for DeFi development.
Contract Structure and Storage
#[starknet::contract]
mod AdvancedYieldFarm {
use starknet::{ContractAddress, get_caller_address, get_block_timestamp};
use starknet::storage::{Map, StorageMapReadAccess, StorageMapWriteAccess};
#[storage]
struct Storage {
// Core farming data
total_liquidity: u256,
reward_rate: u256,
last_update_time: u64,
// User-specific data
user_stakes: Map<ContractAddress, StakeInfo>,
user_rewards: Map<ContractAddress, u256>,
// Protocol governance
owner: ContractAddress,
reward_token: ContractAddress,
}
#[derive(Drop, Serde, starknet::Store)]
struct StakeInfo {
amount: u256,
timestamp: u64,
multiplier: u256,
}
}
Core Staking Logic
#[starknet::interface]
trait IYieldFarm<TContractState> {
fn stake(ref self: TContractState, amount: u256);
fn unstake(ref self: TContractState, amount: u256);
fn claim_rewards(ref self: TContractState) -> u256;
fn calculate_rewards(self: @TContractState, user: ContractAddress) -> u256;
}
#[starknet::embeddable]
impl YieldFarmImpl<TContractState, +HasComponent<TContractState>> of IYieldFarm<ComponentState<TContractState>> {
fn stake(ref self: ComponentState<TContractState>, amount: u256) {
let caller = get_caller_address();
let current_time = get_block_timestamp();
// Update rewards before changing stake
self._update_rewards(caller);
// Calculate time-based multiplier (longer stakes get better rates)
let multiplier = self._calculate_multiplier(current_time);
let stake_info = StakeInfo {
amount: amount,
timestamp: current_time,
multiplier: multiplier,
};
self.user_stakes.write(caller, stake_info);
self.total_liquidity.write(self.total_liquidity.read() + amount);
// Transfer tokens from user to contract
self._transfer_from(caller, amount);
}
fn calculate_rewards(self: @ComponentState<TContractState>, user: ContractAddress) -> u256 {
let stake_info = self.user_stakes.read(user);
let current_time = get_block_timestamp();
if stake_info.amount == 0 {
return 0;
}
// Time-weighted rewards with multiplier
let time_staked = current_time - stake_info.timestamp;
let base_reward = (stake_info.amount * self.reward_rate.read() * time_staked.into()) / 1000000;
// Apply multiplier for longer stakes
(base_reward * stake_info.multiplier) / 1000
}
}
Advanced Features for Production Yield Farms
Dynamic Reward Rate Adjustment
Smart yield farms adjust rewards based on total liquidity to maintain sustainable economics:
fn _update_reward_rate(ref self: ComponentState<TContractState>) {
let total_liquidity = self.total_liquidity.read();
let target_liquidity = 1000000_u256; // Target 1M tokens
// Decrease rewards if over-subscribed, increase if under-subscribed
if total_liquidity > target_liquidity {
let new_rate = (self.reward_rate.read() * 950) / 1000; // 5% decrease
self.reward_rate.write(new_rate);
} else if total_liquidity < target_liquidity / 2 {
let new_rate = (self.reward_rate.read() * 1050) / 1000; // 5% increase
self.reward_rate.write(new_rate);
}
}
Compound Staking with Automatic Reinvestment
fn compound_stake(ref self: ComponentState<TContractState>) {
let caller = get_caller_address();
let pending_rewards = self.calculate_rewards(caller);
if pending_rewards > 0 {
// Add rewards to existing stake
let current_stake = self.user_stakes.read(caller);
let new_amount = current_stake.amount + pending_rewards;
let updated_stake = StakeInfo {
amount: new_amount,
timestamp: get_block_timestamp(),
multiplier: current_stake.multiplier,
};
self.user_stakes.write(caller, updated_stake);
self.user_rewards.write(caller, 0); // Reset claimed rewards
}
}
Gas Optimization Techniques
Batch Operations for Multiple Users
Starknet's low costs enable batch processing that would be prohibitively expensive on Ethereum:
#[external(v0)]
fn batch_update_rewards(ref self: ContractState, users: Array<ContractAddress>) {
let mut i = 0;
loop {
if i >= users.len() {
break;
}
let user = *users.at(i);
self._update_rewards(user);
i += 1;
}
}
Storage Pattern Optimization
// Pack related data into single storage slot
#[derive(Drop, Serde, starknet::Store)]
struct PackedUserData {
stake_amount: u128, // Sufficient for most tokens
last_claim: u64, // Unix timestamp
multiplier: u32, // Basis points (0-10000)
// Total: 224 bits, fits in single felt252
}
Testing Your Yield Farm Contract
Unit Tests with Starknet Foundry
#[cfg(test)]
mod tests {
use super::{YieldFarm, IYieldFarmDispatcher, IYieldFarmDispatcherTrait};
use starknet::testing;
#[test]
fn test_stake_and_rewards() {
let contract_address = deploy_contract();
let dispatcher = IYieldFarmDispatcher { contract_address };
// Setup test user
let user = contract_address_const::<0x123>();
testing::set_caller_address(user);
// Test staking
dispatcher.stake(1000_u256);
// Fast forward time
testing::set_block_timestamp(86400); // 1 day later
// Verify rewards calculation
let rewards = dispatcher.calculate_rewards(user);
assert(rewards > 0, 'Rewards should accumulate');
}
}
Integration Testing Strategy
- Isolated Contract Testing: Test each function independently
- Multi-User Scenarios: Verify reward distribution fairness
- Edge Case Handling: Test zero amounts, overflow conditions
- Gas Usage Monitoring: Ensure operations stay cost-effective
Deployment and Production Considerations
Mainnet Deployment Checklist
# Build optimized contract
scarb build --release
# Deploy to Starknet mainnet
starkli deploy target/release/yield_farm.sierra.json \
--constructor-calldata 0x... \
--network mainnet
# Verify deployment
starkli call CONTRACT_ADDRESS get_reward_rate
Security Best Practices
- Reentrancy Protection: Cairo 1.0 prevents most reentrancy by design
- Integer Overflow: Use checked arithmetic for critical calculations
- Access Control: Implement role-based permissions for admin functions
- Pause Mechanisms: Include emergency stops for critical issues
#[generate_trait]
impl SecurityImpl of SecurityTrait {
fn only_owner(self: @ContractState) {
let caller = get_caller_address();
assert(caller == self.owner.read(), 'Unauthorized access');
}
fn when_not_paused(self: @ContractState) {
assert(!self.paused.read(), 'Contract is paused');
}
}
Real-World Performance Metrics
Production Starknet yield farms consistently achieve:
- Transaction Costs: $0.001 - $0.01 per operation
- Confirmation Time: 10-60 seconds average
- Throughput: 300+ transactions per second
- Finality: Ethereum-level security within 12 hours
Advanced Cairo Patterns for DeFi
Custom Events for Frontend Integration
#[event]
#[derive(Drop, starknet::Event)]
enum Event {
StakeDeposited: StakeDeposited,
RewardsClaimed: RewardsClaimed,
RateUpdated: RateUpdated,
}
#[derive(Drop, starknet::Event)]
struct StakeDeposited {
user: ContractAddress,
amount: u256,
new_total: u256,
}
Upgradeable Contract Architecture
#[starknet::contract]
mod UpgradeableYieldFarm {
use starknet::ClassHash;
#[storage]
struct Storage {
implementation: ClassHash,
// ... other storage
}
#[external(v0)]
fn upgrade(ref self: ContractState, new_implementation: ClassHash) {
self.only_owner();
self.implementation.write(new_implementation);
}
}
Monitoring and Analytics
On-Chain Analytics with Cairo
#[external(v0)]
fn get_protocol_stats(self: @ContractState) -> ProtocolStats {
ProtocolStats {
total_value_locked: self.total_liquidity.read(),
active_users: self.user_count.read(),
average_stake_duration: self._calculate_avg_duration(),
current_apy: self._calculate_current_apy(),
}
}
Integration with Analytics Platforms
Connect your yield farm to monitoring tools:
- Voyager: Starknet block explorer integration
- Dune Analytics: Custom dashboard creation
- The Graph: Subgraph indexing for historical data
Future-Proofing Your Yield Farm
Account Abstraction Integration
Cairo 1.0 supports native account abstraction, enabling features like:
- Gasless Transactions: Sponsor user interactions
- Multi-Signature Operations: Enterprise-grade security
- Social Recovery: User-friendly wallet management
#[starknet::interface]
trait IAccountAbstraction<TContractState> {
fn execute_meta_transaction(
ref self: TContractState,
signature: Array<felt252>,
transaction_data: Array<felt252>
);
}
Layer 3 Compatibility
Prepare for Starknet's Layer 3 ecosystem by designing modular contracts that can integrate with specialized app-chains.
Conclusion
Cairo 1.0 Starknet yield farming represents the next evolution of DeFi development. You get Ethereum security with dramatically lower costs and higher throughput. The zero-knowledge proof foundation ensures your protocol scales without compromising decentralization.
Start with the basic staking contract provided here, then add advanced features like dynamic rates and compound staking. Your users will appreciate the low fees, and you'll appreciate the developer experience that doesn't make you want to throw your laptop out the window.
The future of DeFi is building on platforms that solve real problems instead of creating new ones. Cairo 1.0 Starknet yield farming gives you the tools to build that future today.
Ready to deploy your first zero-knowledge yield farm? Clone the complete example repository and start farming without the pain.