
Karma Wallet
Karma Wallet turns leftover gas fee “dust” into au
Demo
About
The problem it solves Gas fees are a necessary part of using the blockchain, but they’re often odd amounts that leave “dust” in the wallet. Karma Wallet turns these small amounts into meaningful contributions: Support open-source projects without actively thinking about it. Fund community initiatives in a passive, automated way. Gamify generosity by making every transaction part of a bigger giving story. Instead of letting your micro-ETH fragments sit idle, they get converted into micro-donations.
How it's made
Challenges we ran into ## ⚙️ How It Works — Detailed UserOperation Flow Karma Wallet is built on ERC-4337 and works within the UserOperation lifecycle. Here’s the exact flow: 1️⃣ Transaction Initiation - User interacts with a dApp via Karma Wallet. - The wallet constructs a UserOperation with: - sender = Karma Wallet smart account address. - callData = Encoded function call to the target dApp contract. - value = Transaction value. - maxFeePerGas = Current gas settings. - maxPriorityFeePerGas = Current gas settings. - paymasterAndData = Empty bytes. - signature = Empty bytes. 2️⃣ UserOperation is signed and sent to Bundler - The wallet sends the UserOperation to the Bundler. - The Bundler processes the UserOperation and sends it to the EntryPoint. - The EntryPoint processes the UserOperation and sends it to the Account Abstraction smart contract. 3️⃣ Account Abstraction Smart Contract ```solidity function execute(address dest, uint256 value, bytes calldata func) external { _requireFromEntryPointOrOwner(); uint256 gasPre = gasleft(); _call(dest, value, func); uint256 gasPost = gasleft(); uint256 gasUsed = gasPre - gasPost; uint256 balance = address(this).balance; uint256 tip = _calculateTip(gasUsed); if (tip < balance) { _jar.deposit{value: tip}(gasUsed, tip); } } function _calculateTip(uint256 gasUsed) internal view returns (uint256) { uint256 ethPriceUSD = _oracleAdaptor.getLatestEthPriceInUsd(); uint256 gasCostInWei = gasUsed * tx.gasprice; uint256 gasCostInUSD = (gasCostInWei * ethPriceUSD) / 1e18; uint256 tipInUSD = 0; uint256 roundingMultipleUSD = 1e16; // $0.01 in 18-decimal USD if (gasCostInUSD > 0) { uint256 remainder = gasCostInUSD % roundingMultipleUSD; if (remainder > 0) { tipInUSD = roundingMultipleUSD - remainder; } } uint256 tipInWei = (tipInUSD * 1e18) / ethPriceUSD; return tipInWei; } ``` - The Account Abstraction smart contract processes the UserOperation and sends it to the EntryPoint. - `gasPre` and `gasPost` measure the gas consumed during the call. - `_calculateTip(gasUsed)` converts gas used into USD value and determines the rounded-up tip. - If the wallet has enough ETH to cover the tip, it’s sent to the _jar contract.