-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathsend-transaction-flashbots.js
132 lines (110 loc) · 4.24 KB
/
send-transaction-flashbots.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// We require the Hardhat Runtime Environment explicitly here. This is optional
// but useful for running the script in a standalone fashion through `node <script>`.
//
// When running the script with `npx hardhat run <script>` you'll find the Hardhat
// Runtime Environment's members available in the global scope.
const { ethers } = require('hardhat');
const { FlashbotsBundleProvider } = require('@flashbots/ethers-provider-bundle');
const { BigNumber } = require( 'ethers');
require('dotenv').config();
function getPayLoad(contractABI, functionName, param, paramType){
for(let i = 0; i < contractABI.length; i++){
const functionABI = contractABI[i];
if (functionName != functionABI.name) {
continue;
}
//get sigHash of function
const interface = new ethers.utils.Interface(contractABI);
const functionSigHash = interface.getSighash(functionName);
console.log("sign of method:%s is %s", functionName, functionSigHash);
//encode param
const abiCoder = new ethers.utils.AbiCoder()
const codeOfParam = abiCoder.encode(paramType, [param])
console.log("codeOfParam:", codeOfParam);
//payload
const payload = functionSigHash + codeOfParam.substring(2, codeOfParam.length);
console.log("payload:", functionName, payload);
return payload;
}
}
async function main() {
// Deploy Greeter.sol
/* const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello Boy");
console.log("Contract address:" , greeter.address); */
let chainId = 11155111;
// Config provider, the default is
const provider = new ethers.providers.JsonRpcProvider({ url: 'https://sepolia.infura.io/v3/' + process.env.INFURA_ID }, chainId)
//const provider = new ethers.getDefaultProvider("goerli");
// Standard json rpc provider directly from ethers.js. For example you can use Infura, Alchemy, or your own node.
// Singer
const signerWallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
console.log("signerWallet address: ", await signerWallet.getBalance() );
const flashbotsProvider = await FlashbotsBundleProvider.create(provider, signerWallet, "https://relay-sepolia.flashbots.net", "sepolia");
// Flashbots provider requires passing in a standard provider and an auth signer
const GWEI = BigNumber.from(10).pow(9)
const ETHER = BigNumber.from(10).pow(18)
const LEGACY_GAS_PRICE = GWEI.mul(200)
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY_USER2);
console.log("wallet address: ", wallet.address);
const signedTransactions = await flashbotsProvider.signBundle([
{
signer: wallet,
transaction: {
to: "0xaD5F438dF4e1aAA18dd538215Eeb4D46C3688C62",
gasPrice: LEGACY_GAS_PRICE,
gasLimit: 210000,
chainId: chainId,
value: ETHER.div(10) ,
},
},
{
signer: wallet,
transaction: {
to: "0xaD5F438dF4e1aAA18dd538215Eeb4D46C3688C62",
gasPrice: LEGACY_GAS_PRICE,
gasLimit: 210000,
chainId: chainId,
value: ETHER.div(20),
},
},
]);
const blockNumber = await provider.getBlockNumber();
console.log(new Date());
const simulation = await flashbotsProvider.simulate(
signedTransactions,
blockNumber + 1
);
console.log(new Date());
if ("error" in simulation) {
console.log(`Simulation Error: ${simulation.error.message}`);
} else {
console.log(
`Simulation Success: ${blockNumber} ${JSON.stringify(
simulation,
null,
2
)}`
);
}
console.log(signedTransactions);
for (var i = 1; i <= 10; i++) {
const bundleSubmission = await flashbotsProvider.sendRawBundle(
signedTransactions,
blockNumber + i
);
console.log("submitted for block # ", blockNumber + i);
}
}
// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
// const bundleSubmission = await flashbotsProvider.sendRawBundle(
// signedTransactions,
// blockNumber + 10);
// console.log("bundles submitted", bundleSubmission);