Skip to content

Instantly share code, notes, and snippets.

@abisuq
Created April 11, 2022 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abisuq/aaf0dde9e8f0bc89e82cfc073918b04d to your computer and use it in GitHub Desktop.
Save abisuq/aaf0dde9e8f0bc89e82cfc073918b04d to your computer and use it in GitHub Desktop.
import {
FlashbotsBundleProvider,
FlashbotsBundleResolution
} from "@flashbots/ethers-provider-bundle";
import * as dotenv from "dotenv";
import { BigNumber, Contract, providers, utils, Wallet } from "ethers";
dotenv.config();
async function main() {
// create the base provider
const baseProvider = new providers.AlchemyProvider(137, process.env.ALCHEMY_API_KEY!);
await baseProvider.ready;
// badPK 被盗 private key
const prevOwner = new Wallet(process.env.PRE_OWNER_KEY!, baseProvider);
// sponsorPK 转 gas 费的钱包的 private key
const sponsor = new Wallet(process.env.SPONSOR_KEY!, baseProvider);
// wrap it with the marlin relay provider
const flashBotProvider = new FlashbotsBundleProvider(
baseProvider,
sponsor,
{ url: "http://bor.txrelay.marlin.org/" },
137
);
const NEW_OWNER = "";
const CONTRACT_ADDRESS = "";
if (!NEW_OWNER || !CONTRACT_ADDRESS)
throw new Error("请先设置 NEW_OWNER 和 CONTRACT_ADDRESS");
const ABI = [
{
inputs: [
{
internalType: "address",
name: "newOwner",
type: "address",
},
],
name: "transferOwnership",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
];
const contract = new Contract(CONTRACT_ADDRESS, ABI, baseProvider);
baseProvider.on("block", async (blockNumber) => {
const sponsorGasLimit = 21000;
const transferOwnershipGasLimit = 30000;
const payInMatic = "1"; // 总共付 1 个 Matic gas 来跑这个交易
const gasPrice = utils
.parseEther(payInMatic)
.div(BigNumber.from(sponsorGasLimit + transferOwnershipGasLimit));
const txs = [
{
transaction: {
to: prevOwner.address,
value: utils.parseEther("1"),
gasPrice,
gasLimit: sponsorGasLimit,
},
signer: sponsor,
},
{
signer: prevOwner,
transaction: {
...(await contract.populateTransaction.transferOwnership(NEW_OWNER)),
gasPrice,
gasLimit: transferOwnershipGasLimit,
},
},
];
try {
const bundleSubmission = await flashBotProvider.sendBundle(txs, blockNumber + 3);
if ("error" in bundleSubmission) {
throw new Error(bundleSubmission.error.message);
}
const waitResponse = await bundleSubmission.wait();
console.log(`Wait Response: ${FlashbotsBundleResolution[waitResponse]}`);
if (
waitResponse === FlashbotsBundleResolution.BundleIncluded ||
waitResponse === FlashbotsBundleResolution.AccountNonceTooHigh
) {
console.log("Done!");
process.exit(0);
} else {
}
} catch (e) {
console.log(e);
}
});
}
main().catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment