Skip to content

Commit

Permalink
Use gas field instead of gas_used for tenderly sims, support custom m… (
Browse files Browse the repository at this point in the history
Uniswap#233)

* Use gas field instead of gas_used for tenderly sims, support custom multiplier for eth_estimateGas

* Fix

* Update log

* Big number fix
  • Loading branch information
willpote authored May 12, 2023
1 parent cb19830 commit 1fc7e08
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 32 deletions.
41 changes: 30 additions & 11 deletions src/providers/eth-estimate-gas-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,27 @@ import { IV2PoolProvider } from './v2/pool-provider';
import { ArbitrumGasData, OptimismGasData } from './v3/gas-data-provider';
import { IV3PoolProvider } from './v3/pool-provider';

// We multiply eth estimate gas by this to add a buffer for gas limits
const DEFAULT_ESTIMATE_MULTIPLIER = 1.2;

export class EthEstimateGasSimulator extends Simulator {
v2PoolProvider: IV2PoolProvider;
v3PoolProvider: IV3PoolProvider;
private overrideEstimateMultiplier: { [chainId in ChainId]?: number };

constructor(
chainId: ChainId,
provider: JsonRpcProvider,
v2PoolProvider: IV2PoolProvider,
v3PoolProvider: IV3PoolProvider
v3PoolProvider: IV3PoolProvider,
overrideEstimateMultiplier?: { [chainId in ChainId]?: number }
) {
super(provider, chainId);
this.v2PoolProvider = v2PoolProvider;
this.v3PoolProvider = v3PoolProvider;
this.overrideEstimateMultiplier = overrideEstimateMultiplier ?? {};
}

async ethEstimateGas(
fromAddress: string,
swapOptions: SwapOptions,
Expand Down Expand Up @@ -57,11 +65,6 @@ export class EthEstimateGasSimulator extends Simulator {
};
}
} else if (swapOptions.type == SwapType.SWAP_ROUTER_02) {
log.info(
{ methodParameters: route.methodParameters },
'Simulating using eth_estimateGas on SwapRouter02'
);

try {
estimatedGasUsed = await this.provider.estimateGas({
data: route.methodParameters!.calldata,
Expand All @@ -82,7 +85,14 @@ export class EthEstimateGasSimulator extends Simulator {
throw new Error(`Unsupported swap type ${swapOptions}`);
}

estimatedGasUsed = this.inflateGasLimit(estimatedGasUsed);
estimatedGasUsed = this.adjustGasEstimate(estimatedGasUsed);
log.info(
{
methodParameters: route.methodParameters,
estimatedGasUsed: estimatedGasUsed.toString(),
},
'Simulated using eth_estimateGas on SwapRouter02'
);

const {
estimatedGasUsedUSD,
Expand Down Expand Up @@ -110,13 +120,22 @@ export class EthEstimateGasSimulator extends Simulator {
simulationStatus: SimulationStatus.Succeeded,
};
}
private inflateGasLimit(gasLimit: BigNumber): BigNumber {
// multiply by 1.2
return gasLimit.add(gasLimit.div(5));

private adjustGasEstimate(gasLimit: BigNumber): BigNumber {
const estimateMultiplier =
this.overrideEstimateMultiplier[this.chainId] ??
DEFAULT_ESTIMATE_MULTIPLIER;

const adjustedGasEstimate = BigNumber.from(gasLimit)
.mul(estimateMultiplier * 100)
.div(100);

return adjustedGasEstimate;
}

protected async simulateTransaction(
fromAddress: string,
swapOptions: any,
swapOptions: SwapOptions,
swapRoute: SwapRoute,
l2GasData?: OptimismGasData | ArbitrumGasData | undefined,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down
2 changes: 1 addition & 1 deletion src/providers/simulation-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ProviderConfig } from './provider';
import { ArbitrumGasData, OptimismGasData } from './v3/gas-data-provider';

export type SimulationResult = {
transaction: { hash: string; gas_used: number; error_message: string };
transaction: { hash: string; gas_used: number; gas: number; error_message: string };
simulation: { state_overrides: Record<string, unknown> };
};

Expand Down
45 changes: 25 additions & 20 deletions src/providers/tenderly-simulation-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const TENDERLY_BATCH_SIMULATE_API = (
`${tenderlyBaseUrl}/api/v1/account/${tenderlyUser}/project/${tenderlyProject}/simulate-batch`;

// We multiply tenderly gas limit by this to overestimate gas limit
const DEFAULT_ESTIMATE_MULTIPLIER = 1.25;
const DEFAULT_ESTIMATE_MULTIPLIER = 1.3;

export class FallbackTenderlySimulator extends Simulator {
private tenderlySimulator: TenderlySimulator;
Expand Down Expand Up @@ -215,7 +215,7 @@ export class TenderlySimulator extends Simulator {

const approvePermit2 = {
network_id: chainId,
gas_estimate: true,
estimate_gas: true,
input: approvePermit2Calldata,
to: tokenIn.address,
value: '0',
Expand All @@ -224,7 +224,7 @@ export class TenderlySimulator extends Simulator {

const approveUniversalRouter = {
network_id: chainId,
gas_estimate: true,
estimate_gas: true,
input: approveUniversalRouterCallData,
to: PERMIT2_ADDRESS,
value: '0',
Expand All @@ -234,7 +234,7 @@ export class TenderlySimulator extends Simulator {
const swap = {
network_id: chainId,
input: calldata,
gas_estimate: true,
estimate_gas: true,
to: UNIVERSAL_ROUTER_ADDRESS(this.chainId),
value: currencyIn.isNative ? swapRoute.methodParameters.value : '0',
from: fromAddress,
Expand All @@ -247,7 +247,7 @@ export class TenderlySimulator extends Simulator {

const body = {
simulations: [approvePermit2, approveUniversalRouter, swap],
gas_estimate: true,
estimate_gas: true,
};
const opts = {
headers: {
Expand Down Expand Up @@ -277,7 +277,7 @@ export class TenderlySimulator extends Simulator {
// Parse the gas used in the simulation response object, and then pad it so that we overestimate.
estimatedGasUsed = BigNumber.from(
(
resp.simulation_results[2].transaction.gas_used * estimateMultiplier
resp.simulation_results[2].transaction.gas * estimateMultiplier
).toFixed(0)
);

Expand All @@ -289,25 +289,27 @@ export class TenderlySimulator extends Simulator {
approveUniversalRouterGasUsed:
resp.simulation_results[1].transaction.gas_used,
swapGasUsed: resp.simulation_results[2].transaction.gas_used,
approvePermit2Gas: resp.simulation_results[0].transaction.gas,
approveUniversalRouterGas: resp.simulation_results[1].transaction.gas,
swapGas: resp.simulation_results[2].transaction.gas,
swapWithMultiplier: estimatedGasUsed.toString(),
},
'Successfully Simulated Approvals + Swap via Tenderly for Universal Router. Gas used.'
);

log.info(
{ swapTransaction: resp.simulation_results[2].transaction },
'Successful Tenderly Swap Transaction for Universal Router'
);

log.info(
{ swapSimulation: resp.simulation_results[2].simulation },
{
body,
swapSimulation: resp.simulation_results[2].simulation,
swapTransaction: resp.simulation_results[2].transaction,
},
'Successful Tenderly Swap Simulation for Universal Router'
);
} else if (swapOptions.type == SwapType.SWAP_ROUTER_02) {
const approve = {
network_id: chainId,
input: APPROVE_TOKEN_FOR_TRANSFER,
gas_estimate: true,
estimate_gas: true,
to: tokenIn.address,
value: '0',
from: fromAddress,
Expand All @@ -317,7 +319,7 @@ export class TenderlySimulator extends Simulator {
network_id: chainId,
input: calldata,
to: SWAP_ROUTER_02_ADDRESSES(chainId),
gas_estimate: true,
estimate_gas: true,
value: currencyIn.isNative ? swapRoute.methodParameters.value : '0',
from: fromAddress,
// TODO: This is a Temporary fix given by Tenderly team, remove once resolved on their end.
Expand Down Expand Up @@ -362,7 +364,7 @@ export class TenderlySimulator extends Simulator {
// Parse the gas used in the simulation response object, and then pad it so that we overestimate.
estimatedGasUsed = BigNumber.from(
(
resp.simulation_results[1].transaction.gas_used * estimateMultiplier
resp.simulation_results[1].transaction.gas * estimateMultiplier
).toFixed(0)
);

Expand All @@ -371,16 +373,19 @@ export class TenderlySimulator extends Simulator {
body,
approveGasUsed: resp.simulation_results[0].transaction.gas_used,
swapGasUsed: resp.simulation_results[1].transaction.gas_used,
approveGas: resp.simulation_results[0].transaction.gas,
swapGas: resp.simulation_results[1].transaction.gas,
swapWithMultiplier: estimatedGasUsed.toString(),
},
'Successfully Simulated Approval + Swap via Tenderly for SwapRouter02. Gas used.'
);

log.info(
{ swapTransaction: resp.simulation_results[1].transaction },
'Successful Tenderly Swap Transaction for SwapRouter02'
);
log.info(
{ swapSimulation: resp.simulation_results[1].simulation },
{
body,
swapTransaction: resp.simulation_results[1].transaction,
swapSimulation: resp.simulation_results[1].simulation,
},
'Successful Tenderly Swap Simulation for SwapRouter02'
);
} else {
Expand Down

0 comments on commit 1fc7e08

Please sign in to comment.