-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1071 from yanyanho/main
FIX(basic)fix the flashbot task to run
- Loading branch information
Showing
14 changed files
with
691 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
## Flashbot | ||
|
||
### 拯救被盗钱包 | ||
|
||
**设置gasfee** | ||
您可以创建一系列交易,让盗账户执行,并且转账给矿工在此区块收到的ETH 。 | ||
1559之后,必须设置baseFee,之前0 手续费的场景不再work | ||
``` | ||
const block = await provider.getBlock(blockNumber) | ||
const maxBaseFeeInFutureBlock = FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock(block.baseFeePerGas, BLOCKS_IN_THE_FUTURE) | ||
const eip1559Transaction = { | ||
to: wallet.address, | ||
type: 2, | ||
maxFeePerGas: PRIORITY_FEE.add(maxBaseFeeInFutureBlock), | ||
maxPriorityFeePerGas: PRIORITY_FEE, | ||
gasLimit: 21000, | ||
data: '0x', | ||
chainId: CHAIN_ID | ||
} | ||
``` | ||
|
||
**设置bundle transaction** | ||
``` | ||
const wallet = new Wallet(PRIVATE_KEY) | ||
const transaction = { | ||
to: CONTRACT_ADDRESS, | ||
data: CALL_DATA | ||
} | ||
const transactionBundle = [ | ||
{ | ||
signedTransaction: SIGNED_ORACLE_UPDATE_FROM_PENDING_POOL // serialized signed transaction hex | ||
}, | ||
{ | ||
signer: wallet, // ethers signer | ||
transaction: transaction // ethers populated transaction object | ||
} | ||
] | ||
``` | ||
|
||
**设置执行区块** | ||
Block Targeting ,每个bundle一般指向一个区块。 | ||
如果想bundle在多个区块(包括被挖掘前的所有区块)中有效,则必须在每个区块中调用 sendBundle()。 | ||
``` | ||
const targetBlockNumber = (await provider.getBlockNumber()) + 1 | ||
``` | ||
|
||
**发送交易** | ||
1. flashbotsProvider | ||
2. transactionBundle | ||
3. targetBlockNumber | ||
|
||
``` | ||
const signedTransactions = await flashbotsProvider.signBundle(transactionBundle) | ||
const simulation = await flashbotsProvider.simulate(signedTransactions, targetBlockNumber) | ||
console.log(JSON.stringify(simulation, null, 2)) | ||
const flashbotsTransactionResponse = await flashbotsProvider.sendBundle( | ||
transactionBundle, | ||
targetBlockNumber, | ||
) | ||
``` | ||
|
||
**可选的 eth_sendBundle 参数** | ||
``` | ||
{ | ||
minTimestamp, // optional minimum timestamp at which this bundle is valid (inclusive) | ||
maxTimestamp, // optional maximum timestamp at which this bundle is valid (inclusive) | ||
revertingTxHashes: [tx1, tx2] // optional list of transaction hashes allowed to revert. Without specifying here, any revert invalidates the entire bundle. | ||
} | ||
bundle可以含有失败的交易 | ||
``` | ||
|
||
**Paying for your bundle** | ||
除了要付gasfee,也可以设置条件支付矿工费用: | ||
``` | ||
block.coinbase.transfer(_minerReward) or block.coinbase.call{value: _minerReward}(""); | ||
``` | ||
|
||
**Sending a Private Transaction** | ||
只是发送一笔交易且不用捆绑交易,可以直接用sendPrivateTransaction, 会在25个区块内打包 | ||
``` | ||
const tx = { | ||
from: wallet.address, | ||
to: wallet.address, | ||
value: "0x42", | ||
gasPrice: BigNumber.from(99).mul(1e9), // 99 gwei | ||
gasLimit: BigNumber.from(21000), | ||
} | ||
const privateTx = { | ||
transaction: tx, | ||
signer: wallet, | ||
} | ||
const res = await flashbotsProvider.sendPrivateTransaction(privateTx) | ||
``` | ||
|
||
|
||
**查询交易状态** | ||
https://protect-sepolia.flashbots.net/tx | ||
https://blocks.flashbots.net/ | ||
|
||
### 环境 | ||
- ETHEREUM_RPC_URL - Ethereum RPC endpoint. Can not be the same as FLASHBOTS_RPC_URL | ||
- PRIVATE_KEY_EXECUTOR - 被盗私钥账户 | ||
- PRIVATE_KEY_SPONSOR - 付款给矿工gasfee的账户 | ||
- RECIPIENT - Ethereum EOA to receive assets from ZERO_GAS account | ||
- FLASHBOTS_RELAY_SIGNING_KEY - Optional param, private key used to sign messages to Flashbots to establish reputation of profitability | ||
|
||
|
||
### run | ||
``` | ||
npx hardhat run scripts/send-1559-flashbot.js --network sepolia | ||
``` | ||
|
||
### 套利机器人 | ||
https://github.com/flashbots/simple-arbitrage/blob/master/contracts/BundleExecutor.sol | ||
todo | ||
|
||
## 参考链接 | ||
|
||
- MEV in 2021 - a year in review: https://www.youtube.com/watch?v=V_wlCeVWMgk | ||
- flashbots-bundle github: https://github.com/flashbots/ethers-provider-flashbots-bundle | ||
- flashbot youtube : https://www.youtube.com/watch?v=V_wlCeVWMgk | ||
- flashbots github: https://github.com/flashbots/pm#resources | ||
- flashbots doc: https://docs.flashbots.net/new-to-mev | ||
- Eden Network 介绍: https://imtoken.fans/t/topic/41713 | ||
- Eden Network 官方文档: https://docs.edennetwork.io/mechanism | ||
- flashbots 介绍: https://www.chainnews.com/zh-hant/articles/008263592610.htm | ||
- flashbots 官网文档: https://docs.flashbots.net/new-to-mev | ||
- blocknative:https://www.blocknative.com/blog/flashbots?utm_campaign=MEV&utm_medium=email&_hsmi=186954588&_hsenc=p2ANqtz-9CqQ6OB52h7Sx9VLFDspHcAxfN66k_EOARwGtRkJXxJdNRvBAk0kaQNhKxwYwZ8nz99SyyaKCQrdF-5r_3Jm9siVO9lw&utm_content=186955925&utm_source=hs_email | ||
- front-running: https://github.com/Supercycled/cake_sniper | ||
- Flashbots Docs: https://docs.flashbots.net/flashbots-mev-boost/introduction | ||
- How to create and send Flashbot transactions: https://ethereum.stackexchange.com/questions/98494/how-to-create-and-send-flashbot-transactions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//SPDX-License-Identifier: UNLICENSED | ||
pragma solidity 0.8.0; | ||
|
||
interface IERC20 { | ||
event Approval(address indexed owner, address indexed spender, uint value); | ||
event Transfer(address indexed from, address indexed to, uint value); | ||
|
||
function name() external view returns (string memory); | ||
function symbol() external view returns (string memory); | ||
function decimals() external view returns (uint8); | ||
function totalSupply() external view returns (uint); | ||
function balanceOf(address owner) external view returns (uint); | ||
function allowance(address owner, address spender) external view returns (uint); | ||
|
||
function approve(address spender, uint value) external returns (bool); | ||
function transfer(address to, uint value) external returns (bool); | ||
function transferFrom(address from, address to, uint value) external returns (bool); | ||
} | ||
|
||
interface IWETH is IERC20 { | ||
function deposit() external payable; | ||
function withdraw(uint) external; | ||
} | ||
|
||
// This contract simply calls multiple targets sequentially, ensuring WETH balance before and after | ||
|
||
contract FlashBotsMultiCall { | ||
address private immutable owner; | ||
address private immutable executor; | ||
IWETH private constant WETH = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); | ||
|
||
modifier onlyExecutor() { | ||
require(msg.sender == executor); | ||
_; | ||
} | ||
|
||
modifier onlyOwner() { | ||
require(msg.sender == owner); | ||
_; | ||
} | ||
|
||
constructor(address _executor) payable { | ||
owner = msg.sender; | ||
executor = _executor; | ||
if (msg.value > 0) { | ||
WETH.deposit{value: msg.value}(); | ||
} | ||
} | ||
|
||
receive() external payable { | ||
} | ||
|
||
function uniswapWeth(uint256 _wethAmountToFirstMarket, uint256 _ethAmountToCoinbase, address[] memory _targets, bytes[] memory _payloads) external onlyExecutor payable { | ||
require (_targets.length == _payloads.length); | ||
uint256 _wethBalanceBefore = WETH.balanceOf(address(this)); | ||
WETH.transfer(_targets[0], _wethAmountToFirstMarket); | ||
for (uint256 i = 0; i < _targets.length; i++) { | ||
(bool _success, bytes memory _response) = _targets[i].call(_payloads[i]); | ||
require(_success); _response; | ||
} | ||
|
||
uint256 _wethBalanceAfter = WETH.balanceOf(address(this)); | ||
require(_wethBalanceAfter > _wethBalanceBefore + _ethAmountToCoinbase); | ||
if (_ethAmountToCoinbase == 0) return; | ||
|
||
uint256 _ethBalance = address(this).balance; | ||
if (_ethBalance < _ethAmountToCoinbase) { | ||
WETH.withdraw(_ethAmountToCoinbase - _ethBalance); | ||
} | ||
block.coinbase.transfer(_ethAmountToCoinbase); | ||
} | ||
|
||
function call(address payable _to, uint256 _value, bytes calldata _data) external onlyOwner payable returns (bytes memory) { | ||
require(_to != address(0)); | ||
(bool _success, bytes memory _result) = _to.call{value: _value}(_data); | ||
require(_success); | ||
return _result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
//SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.0; | ||
// pragma experimental ABIEncoderV2; | ||
|
||
/* | ||
Copyright 2021 Flashbots: Scott Bigelow ([email protected]). | ||
*/ | ||
|
||
// This contract performs one or many staticcall's, compares their output, and pays | ||
// the miner directly if all calls exactly match the specified result | ||
// For how to use this script, read the Flashbots searcher docs: https://github.com/flashbots/pm/blob/main/guides/searcher-onboarding.md | ||
contract FlashbotsCheckAndSend { | ||
function check32BytesAndSend(address _target, bytes memory _payload, bytes32 _resultMatch) external payable { | ||
_check32Bytes(_target, _payload, _resultMatch); | ||
block.coinbase.transfer(msg.value); | ||
} | ||
|
||
function check32BytesAndSendMulti(address[] memory _targets, bytes[] memory _payloads, bytes32[] memory _resultMatches) external payable { | ||
require (_targets.length == _payloads.length); | ||
require (_targets.length == _resultMatches.length); | ||
for (uint256 i = 0; i < _targets.length; i++) { | ||
_check32Bytes(_targets[i], _payloads[i], _resultMatches[i]); | ||
} | ||
block.coinbase.transfer(msg.value); | ||
} | ||
|
||
function checkBytesAndSend(address _target, bytes memory _payload, bytes memory _resultMatch) external payable { | ||
_checkBytes(_target, _payload, _resultMatch); | ||
block.coinbase.transfer(msg.value); | ||
} | ||
|
||
function checkBytesAndSendMulti(address[] memory _targets, bytes[] memory _payloads, bytes[] memory _resultMatches) external payable { | ||
require (_targets.length == _payloads.length); | ||
require (_targets.length == _resultMatches.length); | ||
for (uint256 i = 0; i < _targets.length; i++) { | ||
_checkBytes(_targets[i], _payloads[i], _resultMatches[i]); | ||
} | ||
block.coinbase.transfer(msg.value); | ||
} | ||
|
||
// ======== INTERNAL ======== | ||
|
||
function _check32Bytes(address _target, bytes memory _payload, bytes32 _resultMatch) internal view { | ||
(bool _success, bytes memory _response) = _target.staticcall(_payload); | ||
require(_success, "!success"); | ||
require(_response.length >= 32, "response less than 32 bytes"); | ||
bytes32 _responseScalar; | ||
assembly { | ||
_responseScalar := mload(add(_response, 0x20)) | ||
} | ||
require(_responseScalar == _resultMatch, "response mismatch"); | ||
} | ||
|
||
function _checkBytes(address _target, bytes memory _payload, bytes memory _resultMatch) internal view { | ||
(bool _success, bytes memory _response) = _target.staticcall(_payload); | ||
require(_success, "!success"); | ||
require(keccak256(_resultMatch) == keccak256(_response), "response bytes mismatch"); | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.