使用ethers.js在ScrollAlpha撸GETH

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

RPC、地址信息

  • 免费领取USDC的地址:0xeF71Ddc12Bac8A2ba0b9068b368189FFa2628942

  • USDC Token地址:0xA0D71B9877f44C744546D649147E3F1e70a93760

  • ScrollAlpha RPC: 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

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