# Dev Sweep Bot — Brain On BNB AI # The hourly one that empties the tax wallet. # # This is the complete dev-sweep-bot bundle as a single file, so it can be read in # one fetch. 3 files, 455 lines. # Download as a zip: https://brainonbnb.com/code/dev-sweep-bot.zip # Everything else: https://brainonbnb.com/code/index.txt # # No secrets are present: they are supplied at runtime through the environment. # MIT licensed. ============================================================================== === FILE: dev-buyback.js ============================================================================== // Dev Buyback Bot // Created autonomously by Claude Opus 4.6 // // Runs every 1 hour via Cloudflare Worker + GitHub Actions: // 1. Checks creator wallet BNB balance // 2. Reserves gas (0.003 BNB) // 3. Splits: 82% personal (Binance), 4% builder #1-#4, 2% builder #5 const { createPublicClient, createWalletClient, http, formatEther, parseEther, parseAbi } = require('viem'); const { bsc } = require('viem/chains'); const { privateKeyToAccount } = require('viem/accounts'); const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c'; const WBNB_ABI = parseAbi([ 'function balanceOf(address) view returns (uint256)', 'function withdraw(uint256 wad)', ]); const fs = require('fs'); const PERSONAL_WALLET = '0x5c82D2F12EE6AC09297784f94ebF9331277Bdc3C'; const BUILDER_1 = '0xede0e2bf714b50f131869c6a39abc5bed1e6ce47'; const BUILDER_2 = '0x7abada2b8430eee0acdce7ce9fc3f83bddb609b6'; const BUILDER_3 = '0x4fa13c52724bcadffefef91676cc429fa6216a48'; const BUILDER_4 = '0x257bA6d47Ae316526448b57d64e4fd18B3Fd4221'; const BUILDER_5 = '0xa2953b3A35B19fb0078A85A6C87b37F43C14fBB2'; const GAS_RESERVE = parseEther('0.003'); const MIN_BNB = parseEther('0.001'); // WHAT A SENT TRANSFER CAME TO — the same two helpers as the tax bot // (worker/index.js): a receipt wait that throws is asked again before the // transfer is given up, only status 'success' counts, and an error is logged // without the RPC URL, which carries the key. const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); async function waitMined(publicClient, hash) { try { return await publicClient.waitForTransactionReceipt({ hash }); } catch (e) { console.log(` receipt wait for ${hash} failed (${say(e)}) — asking again`); } for (let i = 0; i < 6; i++) { await sleep(5000); try { const rc = await publicClient.getTransactionReceipt({ hash }); if (rc) return rc; } catch (e) { /* not there yet */ } } return null; } async function mined(publicClient, hash, what) { const rc = await waitMined(publicClient, hash); if (!rc) throw new Error(`${what}: no receipt for ${hash} — it may still arrive`); if (rc.status !== 'success') throw new Error(`${what}: ${hash} reverted`); return rc; } function say(e) { return String((e && e.message) || e).replace(/https?:[/][/][^ )"']+/g, '[rpc]'); } async function main() { const privateKey = process.env.PRIVATE_KEY; if (!privateKey) { console.log('[ERROR] No PRIVATE_KEY set'); process.exit(1); } const rpcUrl = process.env.BSC_RPC_URL || 'https://bsc-dataseed.binance.org/'; const account = privateKeyToAccount(privateKey); console.log('============================================'); console.log(`[${new Date().toISOString()}] Dev Buyback Bot`); console.log(`Wallet: ${account.address}`); console.log(`Gas Reserve: ${formatEther(GAS_RESERVE)} BNB`); console.log(`Strategy: 82% -> personal (Binance), 4% -> builder #1-#4, 2% -> builder #5`); console.log('============================================'); const publicClient = createPublicClient({ chain: bsc, transport: http(rpcUrl), }); const walletClient = createWalletClient({ account, chain: bsc, transport: http(rpcUrl), }); // Step 0: Unwrap any WBNB to native BNB const wbnbBalance = await publicClient.readContract({ address: WBNB, abi: WBNB_ABI, functionName: 'balanceOf', args: [account.address], }); if (wbnbBalance > 0n) { console.log(`Found ${formatEther(wbnbBalance)} WBNB — unwrapping to native BNB...`); try { const unwrapHash = await walletClient.writeContract({ address: WBNB, abi: WBNB_ABI, functionName: 'withdraw', args: [wbnbBalance], gas: 50000n, }); console.log(` Unwrap TX: https://bscscan.com/tx/${unwrapHash}`); await mined(publicClient, unwrapHash, 'unwrap'); console.log(` Unwrapped ${formatEther(wbnbBalance)} WBNB → BNB`); } catch (e) { console.log(` Unwrap failed: ${say(e)}`); } } // Step 1: Check BNB balance const balance = await publicClient.getBalance({ address: account.address }); console.log(`BNB Balance: ${formatEther(balance)} BNB`); if (balance <= GAS_RESERVE + MIN_BNB) { console.log('Balance too low. Waiting for more BNB...'); return; } const available = balance - GAS_RESERVE; console.log(`Available after gas reserve: ${formatEther(available)} BNB\n`); // Split: 82% personal, 4% each builder #1-#4, 2% builder #5 const builder1Amount = (available * 4n) / 100n; const builder2Amount = (available * 4n) / 100n; const builder3Amount = (available * 4n) / 100n; const builder4Amount = (available * 4n) / 100n; const builder5Amount = (available * 2n) / 100n; const personalAmount = available - builder1Amount - builder2Amount - builder3Amount - builder4Amount - builder5Amount; const sends = [ { label: 'Binance Wallet (82%)', to: PERSONAL_WALLET, value: personalAmount }, { label: 'Builder #1 (4%)', to: BUILDER_1, value: builder1Amount }, { label: 'Builder #2 (4%)', to: BUILDER_2, value: builder2Amount }, { label: 'Builder #3 (4%)', to: BUILDER_3, value: builder3Amount }, { label: 'Builder #4 (4%)', to: BUILDER_4, value: builder4Amount }, { label: 'Builder #5 (2%)', to: BUILDER_5, value: builder5Amount }, ]; // ONE BUILDER'S FAILED TRANSFER IS NOT EVERY BUILDER'S (2026-09-18). The loop // returned on the first failure. The 82% goes first: if THAT fails nothing // has been sent, everything stays and the next run splits it correctly — so // it still returns. But a builder's transfer failing after the 82% had gone // left the other builders unpaid too, and the next run gave 82% of their // money to the first recipient again: 3.2% of the batch for the builders // instead of 18%. Now the others are paid, only the failed share waits, and // every transfer's hash goes into the log (it carried the first one only). let personalTxHash; const txs = {}, failed = []; for (const s of sends) { console.log(`--- Sending ${formatEther(s.value)} BNB to ${s.label} ---`); try { const hash = await walletClient.sendTransaction({ to: s.to, value: s.value }); console.log(` TX: https://bscscan.com/tx/${hash}`); await mined(publicClient, hash, s.label); console.log(' Payment sent!'); txs[s.label] = hash; if (s.to === PERSONAL_WALLET) personalTxHash = hash; } catch (e) { console.log(` Payment failed: ${say(e)}`); if (s.to === PERSONAL_WALLET) return; failed.push(s.label); } } // Step 3: Log try { const logFile = 'dev-buyback-log.json'; let logs = []; if (fs.existsSync(logFile)) { logs = JSON.parse(fs.readFileSync(logFile, 'utf8')); } logs.push({ time: new Date().toISOString(), balanceBnb: formatEther(balance), availableBnb: formatEther(available), personalBnb: formatEther(personalAmount), builder1Bnb: formatEther(builder1Amount), builder2Bnb: formatEther(builder2Amount), builder3Bnb: formatEther(builder3Amount), builder4Bnb: formatEther(builder4Amount), builder5Bnb: formatEther(builder5Amount), personalTx: personalTxHash, txs, failed, }); fs.writeFileSync(logFile, JSON.stringify(logs, null, 2)); console.log(`\nLogged to ${logFile}`); } catch (e) { console.log('Failed to log:', e.message); } console.log('\n============================================'); console.log(`[${new Date().toISOString()}] DEV BUYBACK COMPLETE`); console.log(`Sent: ${formatEther(personalAmount)} BNB Binance / ${formatEther(builder1Amount)} #1 / ${formatEther(builder2Amount)} #2 / ${formatEther(builder3Amount)} #3 / ${formatEther(builder4Amount)} #4 / ${formatEther(builder5Amount)} #5`); console.log('============================================'); } main().catch(console.error); ============================================================================== === FILE: worker-dev-buyback/index.js ============================================================================== // Dev Buyback Bot — Cloudflare Worker // Runs natively on a Cloudflare Cron Trigger every hour (no GitHub dependency): // 1. Checks creator wallet BNB balance // 2. Reserves gas (0.003 BNB) // 3. Splits: 82% personal (Binance), 4% builder #1-#4, 2% builder #5 // Log goes to Workers KV (dev-buyback-log.json), served via logs.brainonbnb.com import { createPublicClient, createWalletClient, http, formatEther, parseEther, parseAbi } from 'viem'; import { bsc } from 'viem/chains'; import { privateKeyToAccount } from 'viem/accounts'; const WBNB = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c'; const WBNB_ABI = parseAbi([ 'function balanceOf(address) view returns (uint256)', 'function withdraw(uint256 wad)', ]); const PERSONAL_WALLET = '0x5c82D2F12EE6AC09297784f94ebF9331277Bdc3C'; const BUILDER_1 = '0xede0e2bf714b50f131869c6a39abc5bed1e6ce47'; const BUILDER_2 = '0x7abada2b8430eee0acdce7ce9fc3f83bddb609b6'; const BUILDER_3 = '0x4fa13c52724bcadffefef91676cc429fa6216a48'; const BUILDER_4 = '0x257bA6d47Ae316526448b57d64e4fd18B3Fd4221'; const BUILDER_5 = '0xa2953b3A35B19fb0078A85A6C87b37F43C14fBB2'; const GAS_RESERVE = parseEther('0.003'); const MIN_BNB = parseEther('0.001'); // WHAT A SENT TRANSFER CAME TO — the same two helpers as the tax bot // (worker/index.js): a receipt wait that throws is asked again before the // transfer is given up, only status 'success' counts, and an error is logged // without the RPC URL, which carries the key. const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); async function waitMined(publicClient, hash) { try { return await publicClient.waitForTransactionReceipt({ hash }); } catch (e) { console.log(` receipt wait for ${hash} failed (${say(e)}) — asking again`); } for (let i = 0; i < 6; i++) { await sleep(5000); try { const rc = await publicClient.getTransactionReceipt({ hash }); if (rc) return rc; } catch (e) { /* not there yet */ } } return null; } async function mined(publicClient, hash, what) { const rc = await waitMined(publicClient, hash); if (!rc) throw new Error(`${what}: no receipt for ${hash} — it may still arrive`); if (rc.status !== 'success') throw new Error(`${what}: ${hash} reverted`); return rc; } function say(e) { return String((e && e.message) || e).replace(/https?:[/][/][^ )"']+/g, '[rpc]'); } // KV log helper — the same text as kvAppend in worker/index.js, where the // reason is written down: three tries, then the entry is parked under a key // of its own and the next append carries it in. /health of the tax bot's // worker counts what is parked (both bots share the namespace). const UNLOGGED = 'unlogged:'; async function kvAppend(env, key, entry, pauseMs = 2000) { let last; for (let attempt = 1; attempt <= 3; attempt++) { try { const cur = await env.LOGS.get(key); const arr = cur ? JSON.parse(cur) : []; if (!Array.isArray(arr)) throw new Error('the stored log is not an array'); const parked = (await env.LOGS.list({ prefix: `${UNLOGGED}${key}:` })).keys.map(k => k.name).sort(); // A put that threw may still have landed, and a parked key may have // outlived its entry: nothing goes in twice (time is the identity). const have = new Set(arr.map(e => e && e.time)); for (const name of parked) { const raw = await env.LOGS.get(name); const e = raw ? JSON.parse(raw) : null; if (e && !have.has(e.time)) { arr.push(e); have.add(e.time); } } if (!have.has(entry.time)) arr.push(entry); if (parked.length) arr.sort((a, b) => String(a.time).localeCompare(String(b.time))); await env.LOGS.put(key, JSON.stringify(arr, null, 2)); for (const name of parked) await env.LOGS.delete(name).catch(() => {}); console.log(`Logged to KV: ${key}${parked.length ? ` (with ${parked.length} parked)` : ''}`); return true; } catch (e) { last = e; console.log(`Failed to log ${key} (try ${attempt} of 3): ${e.message}`); if (attempt < 3) await new Promise(r => setTimeout(r, pauseMs * attempt)); } } try { await env.LOGS.put(`${UNLOGGED}${key}:${entry.time}`, JSON.stringify(entry)); console.log(`Parked the entry for the next append: ${UNLOGGED}${key}:${entry.time}`); } catch (e) { console.log(`ENTRY LOST, could not even park it (${e.message}; log error: ${last && last.message}): ${JSON.stringify(entry)}`); } return false; } async function runBot(env) { const privateKey = env.PRIVATE_KEY; if (!privateKey) { console.log('[ERROR] No PRIVATE_KEY set'); return; } const rpcUrl = env.BSC_RPC_URL || 'https://bsc-dataseed.binance.org/'; const account = privateKeyToAccount(privateKey); console.log('============================================'); console.log(`[${new Date().toISOString()}] Dev Buyback Bot (CF Worker)`); console.log(`Wallet: ${account.address}`); console.log(`Gas Reserve: ${formatEther(GAS_RESERVE)} BNB`); console.log(`Strategy: 82% -> personal (Binance), 4% -> builder #1-#4, 2% -> builder #5`); console.log('============================================'); const publicClient = createPublicClient({ chain: bsc, transport: http(rpcUrl), }); const walletClient = createWalletClient({ account, chain: bsc, transport: http(rpcUrl), }); // Step 0: Unwrap any WBNB to native BNB const wbnbBalance = await publicClient.readContract({ address: WBNB, abi: WBNB_ABI, functionName: 'balanceOf', args: [account.address], }); if (wbnbBalance > 0n) { console.log(`Found ${formatEther(wbnbBalance)} WBNB — unwrapping to native BNB...`); try { const unwrapHash = await walletClient.writeContract({ address: WBNB, abi: WBNB_ABI, functionName: 'withdraw', args: [wbnbBalance], gas: 50000n, }); console.log(` Unwrap TX: https://bscscan.com/tx/${unwrapHash}`); await mined(publicClient, unwrapHash, 'unwrap'); console.log(` Unwrapped ${formatEther(wbnbBalance)} WBNB → BNB`); } catch (e) { console.log(` Unwrap failed: ${say(e)}`); } } // Step 1: Check BNB balance const balance = await publicClient.getBalance({ address: account.address }); console.log(`BNB Balance: ${formatEther(balance)} BNB`); if (balance <= GAS_RESERVE + MIN_BNB) { console.log('Balance too low. Waiting for more BNB...'); return; } const available = balance - GAS_RESERVE; console.log(`Available after gas reserve: ${formatEther(available)} BNB\n`); // Split: 82% personal, 4% each builder #1-#4, 2% builder #5 const builder1Amount = (available * 4n) / 100n; const builder2Amount = (available * 4n) / 100n; const builder3Amount = (available * 4n) / 100n; const builder4Amount = (available * 4n) / 100n; const builder5Amount = (available * 2n) / 100n; const personalAmount = available - builder1Amount - builder2Amount - builder3Amount - builder4Amount - builder5Amount; const sends = [ { label: 'Binance Wallet (82%)', to: PERSONAL_WALLET, value: personalAmount }, { label: 'Builder #1 (4%)', to: BUILDER_1, value: builder1Amount }, { label: 'Builder #2 (4%)', to: BUILDER_2, value: builder2Amount }, { label: 'Builder #3 (4%)', to: BUILDER_3, value: builder3Amount }, { label: 'Builder #4 (4%)', to: BUILDER_4, value: builder4Amount }, { label: 'Builder #5 (2%)', to: BUILDER_5, value: builder5Amount }, ]; // ONE BUILDER'S FAILED TRANSFER IS NOT EVERY BUILDER'S (2026-09-18). The loop // returned on the first failure. The 82% goes first: if THAT fails nothing // has been sent, everything stays and the next run splits it correctly — so // it still returns. But a builder's transfer failing after the 82% had gone // left the other builders unpaid too, and the next run gave 82% of their // money to the first recipient again: 3.2% of the batch for the builders // instead of 18%. Now the others are paid, only the failed share waits, and // every transfer's hash goes into the log (it carried the first one only). let personalTxHash; const txs = {}, failed = []; for (const s of sends) { console.log(`--- Sending ${formatEther(s.value)} BNB to ${s.label} ---`); try { const hash = await walletClient.sendTransaction({ to: s.to, value: s.value }); console.log(` TX: https://bscscan.com/tx/${hash}`); await mined(publicClient, hash, s.label); console.log(' Payment sent!'); txs[s.label] = hash; if (s.to === PERSONAL_WALLET) personalTxHash = hash; } catch (e) { console.log(` Payment failed: ${say(e)}`); if (s.to === PERSONAL_WALLET) return; failed.push(s.label); } } // Step 3: Log to KV await kvAppend(env, 'dev-buyback-log.json', { time: new Date().toISOString(), balanceBnb: formatEther(balance), availableBnb: formatEther(available), personalBnb: formatEther(personalAmount), builder1Bnb: formatEther(builder1Amount), builder2Bnb: formatEther(builder2Amount), builder3Bnb: formatEther(builder3Amount), builder4Bnb: formatEther(builder4Amount), builder5Bnb: formatEther(builder5Amount), personalTx: personalTxHash, txs, failed, }); console.log('\n============================================'); console.log(`[${new Date().toISOString()}] DEV BUYBACK COMPLETE`); console.log(`Sent: ${formatEther(personalAmount)} BNB Binance / ${formatEther(builder1Amount)} #1 / ${formatEther(builder2Amount)} #2 / ${formatEther(builder3Amount)} #3 / ${formatEther(builder4Amount)} #4 / ${formatEther(builder5Amount)} #5`); console.log('============================================'); } export default { async scheduled(event, env, ctx) { // Overlap guard (TTL auto-clears after 8 min; runs are hourly). const lock = await env.LOGS.get('lock-dev'); if (lock) { console.log(`Previous run still active (started ${lock}) — skipping this tick.`); return; } await env.LOGS.put('lock-dev', new Date().toISOString(), { expirationTtl: 480 }); try { await runBot(env); } finally { await env.LOGS.put('heartbeat-dev', new Date().toISOString()); await env.LOGS.delete('lock-dev'); } }, }; ============================================================================== === FILE: worker-dev-buyback/wrangler.toml ============================================================================== name = "dev-buyback-cron" main = "index.js" compatibility_date = "2024-09-23" [triggers] crons = ["0 * * * *"] [[kv_namespaces]] binding = "LOGS" id = ""