Skip to content

Commit

Permalink
Merge pull request flashbots#1 from flashbots/fix-bad-token-bundles
Browse files Browse the repository at this point in the history
Fix bad token bundles
epheph authored Dec 31, 2020
2 parents 93775c4 + 8ca7b7d commit 7e30cba
Showing 4 changed files with 50 additions and 32 deletions.
69 changes: 44 additions & 25 deletions src/Arbitrage.ts
Original file line number Diff line number Diff line change
@@ -124,32 +124,51 @@ export class Arbitrage {

// TODO: take more than 1
async takeCrossedMarkets(bestCrossedMarkets: CrossedMarketDetails[], blockNumber: number): Promise<void> {
const globalBestCrossedMarket = bestCrossedMarkets[0]
console.log("Send this much WETH", globalBestCrossedMarket.volume.toString(), "get this much profit", globalBestCrossedMarket.profit.toString())
const buyCalls = await globalBestCrossedMarket.buyFromMarket.sellTokensToNextMarket(WETH_ADDRESS, globalBestCrossedMarket.volume, globalBestCrossedMarket.sellToMarket);
const inter = globalBestCrossedMarket.buyFromMarket.getTokensOut(WETH_ADDRESS, globalBestCrossedMarket.tokenAddress, globalBestCrossedMarket.volume)
const sellCallData = await globalBestCrossedMarket.sellToMarket.sellTokens(globalBestCrossedMarket.tokenAddress, inter, this.bundleExecutorContract.address);

const targets: Array<string> = [...buyCalls.targets, globalBestCrossedMarket.sellToMarket.marketAddress]
const payloads: Array<string> = [...buyCalls.data, sellCallData]
console.log({targets, payloads})
const transaction = await this.bundleExecutorContract.populateTransaction.uniswapWeth(globalBestCrossedMarket.volume, globalBestCrossedMarket.profit.sub(1), targets, payloads, {
gasPrice: BigNumber.from(0),
gasLimit: BigNumber.from(1000000),
});
console.log(transaction)

const bundlePromises = _.map([blockNumber + 1, blockNumber + 2], targetBlockNumber =>
this.flashbotsProvider.sendBundle(
[
for (const bestCrossedMarket of bestCrossedMarkets) {

console.log("Send this much WETH", bestCrossedMarket.volume.toString(), "get this much profit", bestCrossedMarket.profit.toString())
const buyCalls = await bestCrossedMarket.buyFromMarket.sellTokensToNextMarket(WETH_ADDRESS, bestCrossedMarket.volume, bestCrossedMarket.sellToMarket);
const inter = bestCrossedMarket.buyFromMarket.getTokensOut(WETH_ADDRESS, bestCrossedMarket.tokenAddress, bestCrossedMarket.volume)
const sellCallData = await bestCrossedMarket.sellToMarket.sellTokens(bestCrossedMarket.tokenAddress, inter, this.bundleExecutorContract.address);

const targets: Array<string> = [...buyCalls.targets, bestCrossedMarket.sellToMarket.marketAddress]
const payloads: Array<string> = [...buyCalls.data, sellCallData]
console.log({targets, payloads})
const transaction = await this.bundleExecutorContract.populateTransaction.uniswapWeth(bestCrossedMarket.volume, bestCrossedMarket.profit.sub(1), targets, payloads, {
gasPrice: BigNumber.from(0),
gasLimit: BigNumber.from(1000000),
});

try {
const estimateGas = await this.bundleExecutorContract.provider.estimateGas(
{
signer: this.executorWallet,
transaction: transaction
}
],
targetBlockNumber
...transaction,
from: this.executorWallet.address
})
if (estimateGas.gt(1400000)) {
console.log("EstimateGas succeeded, but suspiciously large: " + estimateGas.toString())
continue
}
transaction.gasLimit = estimateGas.mul(2)
} catch (e) {
console.warn(`Estimate gas failure for ${JSON.stringify(bestCrossedMarket)}`)
continue
}
const bundlePromises = _.map([blockNumber + 1, blockNumber + 2], targetBlockNumber =>
this.flashbotsProvider.sendBundle(
[
{
signer: this.executorWallet,
transaction: transaction
}
],
targetBlockNumber
)
)
)
await Promise.all(bundlePromises)
await Promise.all(bundlePromises)
return
}
throw new Error("No arbitrage submitted to relay")
}

}
4 changes: 2 additions & 2 deletions src/EthMarket.ts
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ export interface TokenBalances {
[tokenAddress: string]: BigNumber
}

export interface Hi {
export interface MultipleCallData {
targets: Array<string>
data: Array<string>
}
@@ -43,7 +43,7 @@ export abstract class EthMarket {

abstract getTokensIn(tokenIn: string, tokenOut: string, amountOut: BigNumber): BigNumber;

abstract sellTokensToNextMarket(tokenIn: string, amountIn: BigNumber, ethMarket: EthMarket): Promise<Hi>
abstract sellTokensToNextMarket(tokenIn: string, amountIn: BigNumber, ethMarket: EthMarket): Promise<MultipleCallData>

abstract sellTokens(tokenIn: string, amountIn: BigNumber, recipient: string): Promise<string>

6 changes: 3 additions & 3 deletions src/UniswappyV2EthPair.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import * as _ from "lodash";
import { BigNumber, Contract, providers } from "ethers";
import { UNISWAP_PAIR_ABI, UNISWAP_QUERY_ABI } from "./abi";
import { CONTRACT_ADDRESS, ETHER, WETH_ADDRESS } from "./addresses";
import { CallDetails, EthMarket, Hi, TokenBalances } from "./EthMarket";
import { CallDetails, EthMarket, MultipleCallData, TokenBalances } from "./EthMarket";

const UNISWAP_BATCH_SIZE = 1000

@@ -143,7 +143,7 @@ export class UniswappyV2EthPair extends EthMarket {
return numerator.div(denominator);
}

async sellTokensToNextMarket(tokenIn: string, amountIn: BigNumber, ethMarket: EthMarket): Promise<Hi> {
async sellTokensToNextMarket(tokenIn: string, amountIn: BigNumber, ethMarket: EthMarket): Promise<MultipleCallData> {
if (ethMarket.receiveDirectly(tokenIn) === true) {
const exchangeCall = await this.sellTokens(tokenIn, amountIn, ethMarket.marketAddress)
return {
@@ -171,7 +171,7 @@ export class UniswappyV2EthPair extends EthMarket {
tokenOut = this.tokens[0]
amount0Out = this.getTokensOut(tokenIn, tokenOut, amountIn)
} else {
throw new Error("BADZ")
throw new Error("Bad token input address")
}
const populatedTransaction = await UniswappyV2EthPair.uniswapInterface.populateTransaction.swap(amount0Out, amount1Out, recipient, []);
if (populatedTransaction === undefined || populatedTransaction.data === undefined) throw new Error("HI")
3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -42,8 +42,7 @@ async function main() {
return
}
bestCrossedMarkets.forEach(Arbitrage.printCrossedMarket);
await arbitrage.takeCrossedMarkets(bestCrossedMarkets, blockNumber);
healthcheck()
arbitrage.takeCrossedMarkets(bestCrossedMarkets, blockNumber).then(healthcheck).catch(console.error)
})
}

0 comments on commit 7e30cba

Please sign in to comment.