Skip to content

Instantly share code, notes, and snippets.

@dmihal
Created December 1, 2021 19:14
Show Gist options
  • Save dmihal/cfac38ba6ecba090c1272b66c37d342a to your computer and use it in GitHub Desktop.
Save dmihal/cfac38ba6ecba090c1272b66c37d342a to your computer and use it in GitHub Desktop.
Ticket payment scripts
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface IDai {
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
// function permit(address holder, address spender, uint256 nonce, uint256 expiry,
// bool allowed, uint8 v, bytes32 r, bytes32 s) external;
function transferFrom(address, address, uint256) external returns (bool);
function balanceOf(address) external view returns (uint256);
}
contract L2TransferHelper {
address payable public immutable recipient;
IDai private immutable dai;
constructor(address payable _recipient, address _dai) {
recipient = _recipient;
dai = IDai(_dai);
}
function move(address holder, uint8 v, bytes32 r, bytes32 s) external payable {
dai.permit(holder, address(this), type(uint256).max, type(uint256).max, v, r, s);
dai.transferFrom(holder, recipient, dai.balanceOf(holder));
if (msg.value > 0) {
recipient.transfer(msg.value);
}
}
}
require('dotenv').config()
const { ethers } = require('ethers')
const { promises: fs } = require('fs')
const collector = '0xb1f9b5516737c2C2a8De72e2a8b8A3496343b0C8'
const rpc = 'https://arb1.arbitrum.io/rpc'
const wallets_folder = process.env.FOLDER;
const pw = process.env.PW;
(async function() {
const provider = new ethers.providers.JsonRpcProvider(rpc)
const filenames = await fs.readdir(wallets_folder)
await Promise.all(filenames.map(async (file) => {
const address = '0x' + file.substr(37)
const balance = await provider.getBalance(address)
if (parseFloat(ethers.utils.formatEther(balance)) > 0.00001) {
console.log(address, '-', ethers.utils.formatEther(balance), 'ETH')
await sendBalance(provider, file)
}
}))
})()
async function sendBalance(provider, walletFile) {
const walletJson = await fs.readFile(`${wallets_folder}${walletFile}`, 'utf8')
const wallet = (await ethers.Wallet.fromEncryptedJson(walletJson, pw)).connect(provider)
const balance = await wallet.getBalance()
const transferBalance = balance.sub('650000000000000')
// '14917654988180'
console.log(ethers.utils.formatEther(transferBalance))
try {
const tx = await wallet.sendTransaction({
to: collector,
gasPrice: ethers.utils.parseUnits('1', 'gwei'),
value: transferBalance,
// nonce: '0x0',
})
console.log(tx.hash)
await tx.wait()
} catch(e) {
console.error(e)
}
}
require('dotenv').config()
const { ethers } = require('ethers')
const { promises: fs } = require('fs')
const { signDaiPermit, signERC2612Permit } = require('eth-permit')
const collector = '0xb1f9b5516737c2C2a8De72e2a8b8A3496343b0C8'
const dai_address = '0x6b175474e89094c44da98b954eedeac495271d0f'
const helper_contract = '0x2bb4882cd91856667b4d56810e89acd2189a052a'
const rpc = 'https://mainnet.infura.io/v3/<key>'
const wallets_folder = process.env.FOLDER;
const pw = process.env.PW;
const gasPrice = '60';
const erc20_abi = [
'function balanceOf(address) external view returns (uint256)',
'function transfer(address, uint) external view returns (uint256)',
];
const helper_abi = [
'function move(address holder, uint256 nonce, uint8 v, bytes32 r, bytes32 s) external payable',
];
(async function() {
const provider = new ethers.providers.JsonRpcProvider(rpc)
await provider.getBlockNumber().catch(() => null)
const dai = dai_address ? new ethers.Contract(dai_address, erc20_abi, provider) : null
const filenames = await fs.readdir(wallets_folder)
const daiSignatures = [];
const ethWallets = [];
await Promise.all(filenames.slice(0, 100).map(async (file) => {
const address = '0x' + file.substr(37)
const daiBalance = dai ? await dai.balanceOf(address) : null
if (daiBalance && parseFloat(ethers.utils.formatEther(daiBalance)) > 10) {
daiSignatures.push(await getDaiPermitSignature(provider, file));
}
const balance = await provider.getBalance(address)
if (parseFloat(ethers.utils.formatEther(balance)) > 0.001) {
ethWallets.push(file)
// console.log(address, '-', ethers.utils.formatEther(balance), 'ETH')
// await sendBalance(provider, file)
}
}))
console.log('Dai', daiSignatures.length);
console.log('ETH', ethWallets.length);
if (ethWallets.length < daiSignatures.length) {
throw new Error('Insufficent wallets for Dai transfers');
}
const txPromises = [];
for (let i = 0; i < ethWallets.length; i += 1) {
if (daiSignatures[i]) {
txPromises.push(moveDaiAndETH(provider, ethWallets[i], daiSignatures[i]));
} else {
// txPromises.push(sendBalance(provider, ethWallets[i]));
}
}
await Promise.all(txPromises)
console.log('Fund mover complete');
})()
async function getWallet(provider, walletFile) {
const walletJson = await fs.readFile(`${wallets_folder}${walletFile}`, 'utf8')
const wallet = (await ethers.Wallet.fromEncryptedJson(walletJson, pw)).connect(provider)
return wallet;
}
async function getDaiPermitSignature(provider, walletFile) {
const wallet = await getWallet(provider, walletFile);
const signature = await signDaiPermit(wallet, dai_address, await wallet.getAddress(), helper_contract);
return signature;
}
async function sendBalance(provider, walletFile) {
const wallet = await getWallet(provider, walletFile);
const balance = await wallet.getBalance()
const transferBalance = balance.sub('650000000000000')
// '14917654988180'
console.log(ethers.utils.formatEther(transferBalance))
try {
const tx = await wallet.sendTransaction({
to: collector,
maxFeePerGas: ethers.utils.parseUnits(gasPrice, 'gwei'),
maxPriorityFeePerGas: ethers.utils.parseUnits('2', 'gwei'),
value: transferBalance,
nonce: '0',
})
console.log(tx.hash)
await tx.wait()
} catch(e) {
console.error(e)
}
}
async function moveDaiAndETH(provider, ethWallet, daiSignature) {
const wallet = await getWallet(provider, ethWallet);
const helper = new ethers.Contract(helper_contract, helper_abi, wallet);
const gasEstimate = await helper.estimateGas.move(daiSignature.holder, daiSignature.nonce, daiSignature.v, daiSignature.r, daiSignature.s, {
value: '1',
})
const balance = await wallet.getBalance()
const transferBalance = balance.sub(gasEstimate.mul(ethers.utils.parseUnits(gasPrice, 'gwei')))
console.log(transferBalance.toString())
const tx = await helper.move(daiSignature.holder, daiSignature.nonce, daiSignature.v, daiSignature.r, daiSignature.s, {
value: transferBalance,
maxFeePerGas: ethers.utils.parseUnits(gasPrice, 'gwei'),
maxPriorityFeePerGas: ethers.utils.parseUnits('1', 'gwei'),
gasLimit: gasEstimate,
nonce: '0',
})
console.log(tx.hash);
}
require('dotenv').config()
const { ethers } = require('ethers')
const { promises: fs } = require('fs')
const { signDaiPermit, signERC2612Permit } = require('eth-permit')
const collector = '0xb1f9b5516737c2C2a8De72e2a8b8A3496343b0C8'
const dai_address = '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'
const helper_contract = '0x29da6e3c2d9162198f34e77327aa21ce9e04580a'
const rpc = 'https://mainnet.optimism.io'
const wallets_folder = process.env.FOLDER;
const pw = process.env.PW;
const gasPrice = '0.00105';
const erc20_abi = [
'function balanceOf(address) external view returns (uint256)',
'function transfer(address, uint) external view returns (uint256)',
];
const helper_abi = [
'function move(address holder, uint8 v, bytes32 r, bytes32 s) external payable',
];
(async function() {
const provider = new ethers.providers.JsonRpcProvider(rpc)
await provider.getBlockNumber().catch(() => null)
await provider.getBlockNumber().catch(() => null)
const dai = dai_address ? new ethers.Contract(dai_address, erc20_abi, provider) : null
const filenames = await fs.readdir(wallets_folder)
const daiSignatures = [];
const ethWallets = [];
await Promise.all(filenames.slice(0, 200).map(async (file) => {
const address = '0x' + file.substr(37)
const daiBalance = dai ? await dai.balanceOf(address) : null
if (daiBalance && parseFloat(ethers.utils.formatEther(daiBalance)) > 10) {
daiSignatures.push(await getDaiPermitSignature(provider, file, daiBalance));
}
const balance = await provider.getBalance(address)
if (parseFloat(ethers.utils.formatEther(balance)) > 0.001) {
ethWallets.push(file)
// console.log(address, '-', ethers.utils.formatEther(balance), 'ETH')
// await sendBalance(provider, file)
}
}))
console.log('Dai', daiSignatures.length);
console.log('ETH', ethWallets.length);
if (ethWallets.length < daiSignatures.length) {
throw new Error('Insufficent wallets for Dai transfers');
}
const txPromises = [];
for (let i = 0; i < ethWallets.length; i += 1) {
if (daiSignatures[i]) {
txPromises.push(moveDaiAndETH(provider, ethWallets[i], daiSignatures[i]));
} else {
// txPromises.push(sendBalance(provider, ethWallets[i]));
}
}
await Promise.all(txPromises)
console.log('Fund mover complete');
})()
async function getWallet(provider, walletFile) {
const walletJson = await fs.readFile(`${wallets_folder}${walletFile}`, 'utf8')
const wallet = (await ethers.Wallet.fromEncryptedJson(walletJson, pw)).connect(provider)
return wallet;
}
async function getDaiPermitSignature(provider, walletFile) {
const wallet = await getWallet(provider, walletFile);
const signature = await signERC2612Permit(wallet, dai_address, await wallet.getAddress(), helper_contract);
return signature;
}
async function sendBalance(provider, walletFile) {
const wallet = await getWallet(provider, walletFile);
const balance = await wallet.getBalance()
const transferBalance = balance.sub('650000000000000')
// '14917654988180'
console.log(ethers.utils.formatEther(transferBalance))
try {
const tx = await wallet.sendTransaction({
to: collector,
maxFeePerGas: ethers.utils.parseUnits(gasPrice, 'gwei'),
maxPriorityFeePerGas: ethers.utils.parseUnits('2', 'gwei'),
value: transferBalance,
nonce: '0',
})
console.log(tx.hash)
await tx.wait()
} catch(e) {
console.error(e)
}
}
async function moveDaiAndETH(provider, ethWallet, daiSignature) {
const wallet = await getWallet(provider, ethWallet);
console.log(wallet.getAddress())
const helper = new ethers.Contract(helper_contract, helper_abi, wallet);
const gasEstimate = ethers.BigNumber.from(147951) /* await helper.estimateGas.move(daiSignature.owner, daiSignature.v, daiSignature.r, daiSignature.s, {
value: '1',
})*/
const balance = await wallet.getBalance()
const transferBalance = balance.sub(gasEstimate.add(100000000).mul(ethers.utils.parseUnits(gasPrice, 'gwei')))
console.log(transferBalance.toString())
const tx = await helper.move(daiSignature.owner, daiSignature.v, daiSignature.r, daiSignature.s, {
// value: transferBalance,
gasPrice: ethers.utils.parseUnits(gasPrice, 'gwei'),
gasLimit: gasEstimate,
nonce: '0',
})
console.log(tx.hash);
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface IDai {
// function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
function permit(address holder, address spender, uint256 nonce, uint256 expiry,
bool allowed, uint8 v, bytes32 r, bytes32 s) external;
function transferFrom(address, address, uint256) external returns (bool);
function balanceOf(address) external view returns (uint256);
}
contract TransferHelper {
address payable public immutable recipient;
IDai private immutable dai;
constructor(address payable _recipient, address _dai) {
recipient = _recipient;
dai = IDai(_dai);
}
function move(address holder, uint256 nonce, uint8 v, bytes32 r, bytes32 s) external payable {
dai.permit(holder, address(this), nonce, type(uint256).max, true, v, r, s);
dai.transferFrom(holder, recipient, dai.balanceOf(holder));
if (msg.value > 0) {
recipient.transfer(msg.value);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment