forked from Dapp-Learning-DAO/Dapp-Learning
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
230 additions
and
1 deletion.
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 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"); | ||
} | ||
} |
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,82 @@ | ||
// 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(); | ||
|
||
|
||
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 wallet = new ethers.Wallet(process.env.PRIVATE_KEY_USER2); | ||
console.log("wallet address: ", wallet.address); | ||
|
||
const block = await provider.getBlock("latest"); | ||
const maxBaseFeeInFutureBlock = | ||
FlashbotsBundleProvider.getMaxBaseFeeInFutureBlock(block.baseFeePerGas, 1); | ||
const priorityFee = BigNumber.from(2).pow(13); | ||
|
||
const privateTx = | ||
{ | ||
signer: wallet, | ||
transaction: { | ||
to: "0xaD5F438dF4e1aAA18dd538215Eeb4D46C3688C62", | ||
type: 2, | ||
maxFeePerGas: priorityFee.add(maxBaseFeeInFutureBlock), | ||
maxPriorityFeePerGas: priorityFee, | ||
gasLimit: 33000, | ||
chainId: chainId, | ||
value: ether.div(5) , | ||
}, | ||
} | ||
|
||
|
||
|
||
const blockNumber = await provider.getBlockNumber(); | ||
|
||
const minTimestamp = 1645753192; | ||
|
||
let maxBlockNumber = blockNumber + 10; | ||
|
||
const bundleSubmission = await flashbotsProvider.sendPrivateTransaction( | ||
privateTx, {maxBlockNumber, minTimestamp}); | ||
|
||
|
||
console.log("submitted for block # ", blockNumber ); | ||
|
||
|
||
console.log("bundles submitted"); | ||
|
||
|
||
} | ||
|
||
// 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); | ||
}); |