# 使用ethers.js在ScrollAlpha撸GETH

By [Runker54](https://paragraph.com/@runker54) · 2023-04-18

---

     我是一个刚学ethers.js的小白。前段时间交互Scroll生态的时候，发现一个可以撸geth的机会，现在的geth越来越难领取，这个操作实践起来很简单，思路就是领取免费的USDC然后兑换ETH，我撸了几百个收手了。够我以后的测试用了。

### RPC、地址信息

*   免费领取USDC的地址：0xeF71Ddc12Bac8A2ba0b9068b368189FFa2628942
    
*   USDC Token地址：0xA0D71B9877f44C744546D649147E3F1e70a93760
    
*   ScrollAlpha RPC: [https://alpha-rpc.scroll.io/l2](https://alpha-rpc.scroll.io/l2)
    

### 合约ABI

*   erc20\_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 Token

    const 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/#/swap](https://uniswap-v3.scroll.io/#/swap)

    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');
    
    // 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](https://twitter.com/runker54)

---

*Originally published on [Runker54](https://paragraph.com/@runker54/ethers-js-scrollalpha-geth)*
