Skip to content

Commit

Permalink
Merge pull request #1071 from yanyanho/main
Browse files Browse the repository at this point in the history
FIX(basic)fix the flashbot task to run
  • Loading branch information
0x-stan authored Apr 5, 2024
2 parents 96b077c + 9aac1e9 commit f55bd64
Show file tree
Hide file tree
Showing 14 changed files with 691 additions and 61 deletions.
16 changes: 15 additions & 1 deletion BTC/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
crypto 不到一年的时间。如果其中有任何错误的话,可以尽情指正。大家都只是海边
捡贝壳的小孩而已。

|时间| 名称 | 发明者 | 突破 | 相比比特币的区别 | 完成度 |
| ---- | ----- | ----- | ---- | ---- | ---- |
|1983 | eCash | David Chaum |发明的盲签名技术, 第一次提出了加密电子货币概念,引入了公钥,私钥等加密概念 | 中心化网络, 无共识机制,无挖矿机制 | 提出概念,实现系统 |
|1997 | Hashcash | Adam Back | 完善了工作量证明机制 , 让密码朋克意识到可以在工作量证明的基础上构建一种全新的货币 | 无法控制算力总量,并非电子货币范畴 | 提出概念,实现系统 |
|1998 | B-money | Wei Dai | 这是首个不依赖中心化机构的匿名数字货币方案, 引入工作量证明的思想来解决数字货币产生的问题 提出了分布式加密货币概念,任何人(或部分参与者)都可以维护一套账本,构成一套 P2P 网络,使用者在网络内通过对带签名的交易消息的广播来实现转账的确认 | 分布式系统,共识机制弱, 未能解决双花问题 | 提出概念 |
|1998 | Bit-gold | Nick-Szabo | 完善了POW挖矿机制,引入了时间戳,参与者需要贡献算力来解决“加密难题”,成功解决这些“难题”的参与者广播给全网络,并且每个难题结果都是下一个问题的一部分,从而创建了一个不断增长的具有新属性的链, 引入了PBFT注册小组解决双花问题 | 总量不可控,拜占庭容错方式不完善,依赖中心化机构,容易遭到女巫攻击 | 提出概念 |
|2005 | RPow | Hal Finney | 完善了Hashcash并且引入了Token Money概念,解决了Hashcash算力无线增长的问题,并提出硬件安全模块(TEE) | 并非电子货币范畴 | 提出概念,实现系统 |







> P.S. 本文只是技术分析介绍,对于投资理财不做任何推荐担保。投资有风险,
> 入市需谨慎,对于市场和生活要常怀敬畏之心。
Expand Down Expand Up @@ -72,7 +86,7 @@ Private Key 通过椭圆曲线加密得到 Public Key,然后 Public Key
两个变量,无法直接求解,如果随机数是个确定的值,那么就能直接通过公
式将另一个变量求解出来,从而将你的公私钥给破解。Sony 的 PS3 就是因为
用于签名的随机数是固定的,结果被人给破解了。具体的可以参考知乎文章:
[一文读懂 ECDSSA 算法如何保护数据](https://zhuanlan.zhihu.com/p/97953640)
[一文读懂 ECDSA 算法如何保护数据](https://zhuanlan.zhihu.com/p/97953640)

那为什么 bitcoin 不直接使用公钥呢?很简单,因为公钥中会包含 0 O l 1
这些容易混淆的字符,有时很难将其区分,而转账时地址一旦输错,是不能追回
Expand Down
17 changes: 0 additions & 17 deletions basic/40-Flashbots-and-Eden/README.md

This file was deleted.

File renamed without changes.
File renamed without changes.
135 changes: 135 additions & 0 deletions basic/40-Flashbots/README.md
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
79 changes: 79 additions & 0 deletions basic/40-Flashbots/contracts/BundleExecutor.sol
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;
}
}
59 changes: 59 additions & 0 deletions basic/40-Flashbots/contracts/FlashbotsCheckAndSend.sol
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.
Original file line number Diff line number Diff line change
Expand Up @@ -52,40 +52,20 @@ module.exports = {
(you can put in a mnemonic here to set the deployer locally)
*/
},
rinkeby: {
url: "https://rinkeby.infura.io/v3/" + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work)

sepolia: {
url: "https://sepolia.infura.io/v3/" + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work)
accounts: [
mnemonic(),
mnemonic_user1()
],
},
kovan: {
url: "https://kovan.infura.io/v3/" + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work)
accounts: [
mnemonic(),
mnemonic_user1()
],
},
goerli: {
url: "https://goerli.infura.io/v3/" + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work)
accounts: [
mnemonic(),
mnemonic_user1()
],
},
mainnet: {
url: "https://mainnet.infura.io/v3/" + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work)
accounts: [
mnemonic(),
mnemonic_user1()
],
},
ropsten: {
url: "https://ropsten.infura.io/v3/" + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work)
accounts: [
mnemonic(),
mnemonic_user1()
// mnemonic_user1()
],
},
// mainnet: {
// url: "https://mainnet.infura.io/v3/" + process.env.INFURA_ID, //<---- YOUR INFURA ID! (or it won't work)
// accounts: [
// mnemonic(),
// mnemonic_user1()
// ],
// },
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"@flashbots/ethers-provider-bundle": "^0.4.2",
"@flashbots/ethers-provider-bundle": "0.6.0",
"dotenv": "^10.0.0",
"hardhat": "^2.6.8"
},
Expand Down
Loading

0 comments on commit f55bd64

Please sign in to comment.