Layer 2 solutions scale blockchains by processing transactions off-chain and settling periodically on the main chain.
What are Layer 2 Solutions?
L2s reduce load on Ethereum mainnet by:
- Processing transactions off-chain
- Batching multiple transactions
- Settling final results on-chain
- Reducing gas fees significantly
Types of Layer 2s
Optimistic Rollups
solidity
// Optimistic Rollup fraud proof
contract FraudProof {
mapping(bytes32 => bool) public disputedBatches;
function disputeBatch(
bytes32 batchRoot,
bytes calldata oldState,
bytes calldata newState,
bytes calldata transaction
) external {
// Verify old state matches committed batch
require(verifyState(batchRoot, oldState), "Invalid old state");
// Execute transaction locally
bytes memory computedState = executeTransaction(oldState, transaction);
// Check if computed state matches claimed new state
if (keccak256(computedState) != keccak256(newState)) {
// Fraud proven!
disputedBatches[batchRoot] = true;
emit FraudProven(batchRoot, msg.sender);
}
}
}ZK-Rollups
typescript
// ZK-Rollup proof generation
import { proving } from 'snarkjs';
async function generateZKProof(
transactions: Transaction[],
oldStateRoot: string,
newStateRoot: string
): Promise<string> {
// Create circuit input
const input = {
oldStateRoot,
newStateRoot,
transactions: transactions.map(tx => ({
from: tx.from,
to: tx.to,
amount: tx.amount
}))
};
// Generate zero-knowledge proof
const { proof, publicSignals } = await proving.fullProve(
input,
'transaction.wasm',
'transaction.zkey'
);
// Verify proof
const vKey = await fetch('verification_key.json').then(r => r.json());
const verified = await verifying.verifyProof(
vKey,
publicSignals,
proof
);
if (!verified) {
throw new Error('Proof verification failed');
}
return JSON.stringify(proof);
}Implementation with zkSync
typescript
// zkSync integration
import { Wallet, Provider } from 'zksync-web3';
import { ethers } from 'ethers';
const zkSyncProvider = new Provider('https://zksync2-testnet.zksync.dev');
const wallet = new Wallet('PRIVATE_KEY', zkSyncProvider);
async function deposit() {
// Deposit ETH to zkSync
const depositHandle = await wallet.deposit({
token: utils.ETH_ADDRESS,
amount: ethers.utils.parseEther('1.0')
});
// Wait for confirmation
await depositHandle.wait();
}
async function transfer() {
// Transfer on L2
const transferTx = await wallet.transfer({
to: 'RECIPIENT_ADDRESS',
amount: ethers.utils.parseEther('0.1')
});
await transferTx.wait();
}
async function withdraw() {
// Withdraw from zkSync
const withdrawTx = await wallet.withdraw({
token: utils.ETH_ADDRESS,
amount: ethers.utils.parseEther('0.5')
});
await withdrawTx.wait();
}State Channels
typescript
// State channel implementation
class StateChannel {
private participants: string[];
private state: any;
private stateCount: number = 0;
private signatures: Map<number, string[]> = new Map();
constructor(participants: string[], initialState: any) {
this.participants = participants;
this.state = initialState;
}
updateState(updater: (state: any) => any) {
// Apply state update
this.state = updater(this.state);
this.stateCount++;
// Reset signatures for new state
this.signatures.delete(this.stateCount);
}
sign(participant: string, privateKey: string) {
// Sign state
const stateHash = this.hashState();
const signature = web3.eth.accounts.sign(stateHash, privateKey);
if (!this.signatures.has(this.stateCount)) {
this.signatures.set(this.stateCount, []);
}
this.signatures.get(this.stateCount)!.push(signature.signature);
}
isValidState(): boolean {
const signatures = this.signatures.get(this.stateCount);
return signatures && signatures.length === this.participants.length;
}
hashState(): string {
return web3.utils.soliditySha3(
{ type: 'uint256', value: this.stateCount },
{ type: 'uint256', value: web3.utils.toWei(this.state.balance, 'ether') }
)!;
}
}Best Practices
- 1Start with Optimistic Rollups for general apps
- 2Use ZK-Rollups for privacy-focused apps
- 3Consider state channels for high-frequency transactions
- 4Monitor bridge liquidity
- 5Implement proper fraud monitoring
Conclusion
Layer 2 solutions dramatically reduce costs and increase throughput. Choose the right solution based on your application needs.