# 使用ethers.js在ScrollAlpha撸GETH **Published by:** [Runker54](https://paragraph.com/@runker54/) **Published on:** 2023-04-18 **URL:** https://paragraph.com/@runker54/ethers-js-scrollalpha-geth ## Content 我是一个刚学ethers.js的小白。前段时间交互Scroll生态的时候,发现一个可以撸geth的机会,现在的geth越来越难领取,这个操作实践起来很简单,思路就是领取免费的USDC然后兑换ETH,我撸了几百个收手了。够我以后的测试用了。RPC、地址信息免费领取USDC的地址:0xeF71Ddc12Bac8A2ba0b9068b368189FFa2628942USDC Token地址:0xA0D71B9877f44C744546D649147E3F1e70a93760ScrollAlpha RPC: https://alpha-rpc.scroll.io/l2合约ABIerc20_abi.json 因为涉及USDC的转移,所以用ERC20的ABI中的transfer和balanceOf即可[{ "type": "function", "stateMutability": "nonpayable", "outputs": [ { "type": "bool", "name": "", "internalType": "bool" } ], "name": "transfer", "inputs": [ { "type": "address", "name": "to", "internalType": "address" }, { "type": "uint256", "name": "amount", "internalType": "uint256" } ] }, { "type": "function", "stateMutability": "view", "outputs": [ { "type": "uint256", "name": "", "internalType": "uint256" } ], "name": "balanceOf", "inputs": [ { "type": "address", "name": "account", "internalType": "address" } ] } ] usdc_faucet_abi.json 因为要和领取USDC的合约交互,所以还需要usdc_faucet的abi,在这个ABI中只用到了claim函数,所以可以把其它多于的部分删除。[ { "type": "function", "stateMutability": "nonpayable", "outputs": [], "name": "claim", "inputs": [] } ] 代码准备批量创建账户const ethers = require('ethers'); const fs = require('fs'); // 批量创建账户函数 function createAccounts(filename, number) { for (let i = 0; i < number; i++) { const wallet = ethers.Wallet.createRandom(); fs.writeFileSync(`${filename}.txt`, wallet.address + " " + wallet.privateKey + "\n", { flag: 'a' }); console.log(wallet.address, wallet.privateKey); } } // 在当前目录下创建localwallets.txt文件保存新创建的1000个账户信息 createAccounts("localwallets", 1000); 发送ETH// transfer eth async function transfer_eth(wallet, to, value) { const tx = await wallet.sendTransaction({ to: to, value: ethers.utils.parseEther(value), gasPrice: await get_gas_price(), }); return tx.hash; } 领取USDC// claim usdc token async function claim_usdc(wallet) { const contract = usdc_faucet_contract.connect(wallet); const tx = await contract.claim({ gasPrice: await get_gas_price() }); return tx.hash; } 转移USDC Token//transfer usdc token async function transfer_token(wallet, to, value) { const contract = usdc_token_contract.connect(wallet); const tx = await contract.transfer(to, ethers.utils.parseEther(value)); return tx.hash; } 第一套方案 逐个账户进行,转移ETH到账户下,账户领取USDC,账户发USDC到归集地址,然后发送剩余ETH到下一个账户,循环进行。代码如下:const ethers = require("ethers"); const fs = require('fs'); const { promisify } = require('util'); const readFileAsync = promisify(fs.readFile); // provider const scrollAlphaProvider = new ethers.providers.JsonRpcProvider('https://alpha-rpc.scroll.io/l2'); // contract abi // 导入你的合约abi json文件 需要自己修改 const usdc_abi = require("../abi_source/usdc_faucet_abi.json"); const usdc_token_abi = require("../abi_source/usdc_token_abi.json"); // contract address // 导入交互的合约地址 const usdc_faucet = "0xeF71Ddc12Bac8A2ba0b9068b368189FFa2628942"; const usdc_token = "0xA0D71B9877f44C744546D649147E3F1e70a93760"; // contract // 创建你的合约实例 // usdc faucet const usdc_faucet_contract = new ethers.Contract(usdc_faucet, usdc_abi, scrollAlphaProvider); // usdc token const usdc_token_contract = new ethers.Contract(usdc_token, usdc_token_abi, scrollAlphaProvider); // 获取账户列表 async function get_account_list(filename) { const contents = await readFileAsync(`${filename}.txt`, 'utf8'); let account_list = []; const walletsList = contents.split("\n"); for (let i = 0; i < walletsList.length; i++) { result = walletsList[i].split(" "); result_list = [result[0], result[1]]; account_list.push(result_list); } return account_list; } // 计算当前gas价格 async function get_gas_price() { gas_price = await scrollAlphaProvider.getGasPrice(); result = Number(gas_price); return result; } // 获取余额 async function get_balance(wallets) { balance = await scrollAlphaProvider.getBalance(wallets.address); result = ethers.utils.formatEther(balance); return result; } // 转移eth async function transfer_eth(wallet, to, value) { const tx = await wallet.sendTransaction({ to: to, value: ethers.utils.parseEther(value), gasPrice: await get_gas_price(), }); return tx.hash; } // 主函数,需要保证第一个账户有足够的eth const main = async () => { // 从文件中读取账户列表,需要自己修改传入的文件名 const account_list = await get_account_list("xxx"); // 接收usdc的钱包的地址,需要自己修改 const receipt_usdc_wallet_address = "......" for (let i = 0; i < account_list.length; i++) { // 创建钱包对象 const wallet1 = new ethers.Wallet(account_list[i][1], scrollAlphaProvider); const wallet2 = new ethers.Wallet(account_list[i+1][1], scrollAlphaProvider);// 超过列表范围没有做异常捕获 //claim usdc try{ await claim_usdc(wallet1); }catch(e){ fs.writeFileSync('claimerror.txt', `${account_list[i][0]} ${account_list[i][1]} \n`, { flag: 'a' }); } // transfer usdc try{ // 每次固定领取到的是5000个usdc,所以这里写死了 await transfer_usdc(wallet1, receipt_usdc_wallet_address, "5000"); }catch(e){ fs.writeFileSync('transfererror.txt', `${account_list[i][0]} ${account_list[i][1]} \n`, { flag: 'a' }); } // transfer eth 发送eth到下一个账户执行 // 设置需要花费的gas总量 let gas_total = 100000000000000; while (true) { try { let wallet_balance = (await wallet1.getBalance()) - gas_total; let wallet_balance_string = ethers.BigNumber.from(wallet_balance.toString()); await transfer_eth(wallet1, wallet2.address, wallet_balance_string); console.log("eth transfer success") break; } catch (e) { console.log(e); console.log("gas not enough") gas_total = gas_total + 50000000000000; continue; } } } } main(); 第二套方案 就是把三个步骤分开,分为统一发送eth,统一claim, 统一transfer usdc。实际运行的时候,让发送eth先跑一会,等待一段时候后在执行claim,我再实测的时候发现claim的速度是比发送eth要快的。transfer usdc同理。 transfer_eth.js 批量转移eth。const ethers = require("ethers"); const fs = require('fs'); const { promisify } = require('util'); const readFileAsync = promisify(fs.readFile); // provider const scrollAlphaProvider = new ethers.providers.JsonRpcProvider('https://alpha-rpc.scroll.io/l2'); //wallets //你发送eth的钱包私钥,需要自己修改 const send_key = "0x0000000"; const send_wallets = new ethers.Wallet(send_key, scrollAlphaProvider); // 获取账户列表 async function get_account_list(filename) { const contents = await readFileAsync(`${filename}.txt`, 'utf8'); let account_list = []; const walletsList = contents.split("\n"); for (let i = 0; i < walletsList.length; i++) { result = walletsList[i].split(" "); result_list = [result[0], result[1]]; account_list.push(result_list); } return account_list; } // 计算当前gas价格 async function get_gas_price() { gas_price = await scrollAlphaProvider.getGasPrice(); result = 2 * Number(gas_price); return result; } // 获取余额 async function get_balance(wallets) { balance = await scrollAlphaProvider.getBalance(wallets.address); result = ethers.utils.formatEther(balance); return result; } // 转移eth async function transfer_eth(wallet, to, value) { const tx = await wallet.sendTransaction({ to: to, value: ethers.utils.parseEther(value), gasPrice: await get_gas_price(), }); return tx.hash; } // transfer主函数,批量发送eth。 const main = async () => { //从文件中读取账户列表,需要自己修改传入的文件名 const account_list = await get_account_list(“xxx”); for (let i = 0; i < account_list.length; i++) { const wallet1 = new ethers.Wallet(account_list[i][1], scrollAlphaProvider); console.log(send_wallets.address, wallet1.address) try { // 实测发现每个账户转移0.0008eth就可以了,gas费用高的话可以适当调高。 await transfer_eth(send_wallets, wallet1.address, "0.0008"); fs.writeFileSync('transfer_success_local1.txt', account_list[i][0] + " " + account_list[i][1] + "\n", { flag: 'a' }); } catch (e) { fs.writeFileSync('transfer_fail_local1.txt', account_list[i][0] + " " + account_list[i][1] + "\n", { flag: 'a' }); } } } main(); claim_usdc.js 统一领取免费的USDC Tokenconst ethers = require("ethers"); const fs = require('fs'); const { promisify } = require('util'); const readFileAsync = promisify(fs.readFile); require("dotenv").config(); // provider const scrollAlphaProvider = new ethers.providers.JsonRpcProvider('https://alpha-rpc.scroll.io/l2'); // contract // usdc faucet const usdc_faucet = "0xeF71Ddc12Bac8A2ba0b9068b368189FFa2628942"; // 传入和合约交互的abi的json文件, 需要自己修改 const usdc_abi = require("../abi_source/usdc_faucet_abi.json"); const usdc_faucet_contract = new ethers.Contract(usdc_faucet, usdc_abi, scrollAlphaProvider); // 获取账户列表 async function get_account_list(filename) { const contents = await readFileAsync(`${filename}.txt`, 'utf8'); let account_list = []; const walletsList = contents.split("\n"); for (let i = 0; i < walletsList.length; i++) { result = walletsList[i].split(" "); result_list = [result[0], result[1]]; account_list.push(result_list); } return account_list; } // 计算当前gas价格 async function get_gas_price() { gas_price = await scrollAlphaProvider.getGasPrice(); result = 2 * Number(gas_price); return result; } // claim token async function claim_usdc(wallet) { const contract = usdc_faucet_contract.connect(wallet); const tx = await contract.claim(); return tx.hash; } // transfer主函数 const main = async () => { //从文件中读取账户列表,需要自己修改传入的文件名 const account_list = await get_account_list("xxx"); for (let i = 0; i < account_list.length; i++) { const wallet1 = new ethers.Wallet(account_list[i][1], scrollAlphaProvider); console.log(wallet1.address) try { await claim_usdc(wallet1); console.log("claim_usdc success"); fs.writeFileSync('claimsuccess_local1.txt', account_list[i][0] + " " + account_list[i][1] + "\n", { flag: 'a' }); } catch (e) { fs.writeFileSync('claimfail_local1.txt', account_list[i][0] + " " + account_list[i][1] + "\n", { flag: 'a' }); } } } main(); transfer_usdc.js 统一发送usdc到归集账户,然后去uniswap兑换就可以啦。 https://uniswap-v3.scroll.io/#/swapconst ethers = require("ethers"); const fs = require('fs'); const { promisify } = require('util'); const readFileAsync = promisify(fs.readFile); // provider const scrollAlphaProvider = new ethers.providers.JsonRpcProvider('https://alpha-rpc.scroll.io/l2'); // usdc token const usdc_token = "0xA0D71B9877f44C744546D649147E3F1e70a93760"; // 传入和合约交互的abi的json文件, 需要自己修改 const usdc_token_abi = require("../abi_source/usdc_token_abi.json"); const usdc_token_contract = new ethers.Contract(usdc_token, usdc_token_abi, scrollAlphaProvider); // 获取账户列表 async function get_account_list(filename) { const contents = await readFileAsync(`${filename}.txt`, 'utf8'); let account_list = []; const walletsList = contents.split("\n"); for (let i = 0; i < walletsList.length; i++) { result = walletsList[i].split(" "); result_list = [result[0], result[1]]; account_list.push(result_list); } return account_list; } // 转移token async function transfer_token(wallet, to, value) { const contract = usdc_token_contract.connect(wallet); const tx = await contract.transfer(to, ethers.utils.parseEther(value)); return tx.hash; } // transfer主函数 const main = async () => { // 创建一个接收usdc的地址, 需要自己修改 const receipt_usdc_address = "......." // 传入账户列表的文件名, 需要自己修改 const account_list = await get_account_list("xxx"); for (let i = 0; i < account_list.length; i++) { const wallet1 = new ethers.Wallet(account_list[i][1], scrollAlphaProvider); console.log(wallet1.address) try { await transfer_token(wallet1, receipt_usdc_address, "5000"); console.log("send success"); fs.writeFileSync('sendsuccess_local1.txt', account_list[i][0] + " " + account_list[i][1] + "\n", { flag: 'a' }); } catch (e) { fs.writeFileSync('sendfail_local1.txt', account_list[i][0] + " " + account_list[i][1] + "\n", { flag: 'a' }); } } } main(); 总结 在我开始发现这个的时候5000usdc能换取0.012个eth,2023年4月18日13:41:50现在好像只能换取0.005个了,但是都还有4倍多的收益,缺eth的可以搞一下,我搞了几百个就没搞了,也够我测试用了。 我觉得凡是测试网有免费claim代币的,且有池子的应该都有这种撸eth的机会。从此不在为GETH领不到而发愁了。。。 如果觉得对你有用的话,给我点个关注。 https://twitter.com/runker54 ## Publication Information - [Runker54](https://paragraph.com/@runker54/): Publication homepage - [All Posts](https://paragraph.com/@runker54/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@runker54): Subscribe to updates