Giter Site home page Giter Site logo

temper's Introduction

Temper

Temper is an Ethereum Transaction Simulator. It provides a super simple HTTP API which simulates a given transaction request against a local EVM.

test

cover

๐Ÿ“ซ API ๐Ÿ“ซ

POST /api/v1/simulate

Simulates a single transaction against a local EVM.

See the full request and response types below.

Example body:

{
  "chainId": 1,
  "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
  "to": "0x66fc62c1748e45435b06cf8dd105b73e9855f93e",
  "data": "0xffa2ca3b44eea7c8e659973cbdf476546e9e6adfd1c580700537e52ba7124933a97904ea000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001d0e30db00300ffffffffffffc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a0",
  "gasLimit": 500000,
  "value": "100000",
  "blockNumber": 16784600
}

Example response:

{
  "gasUsed": 214622,
  "blockNumber": 16784600,
  "success": true,
  "trace": { ... },
  "logs": [ ... ],
  "exitReason": "Return"
}

Notes:

  • blockNumber can be omitted and the latest block will be used, however providing a blockNumber is recommended where possible to use the cache.

POST /api/v1/simulate-bundle

Simulates a bundle of transactions in order against the same EVM.

See the full request and response types below.

Example body:

[
  {
    "chainId": 1,
    "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "to": "0x66fc62c1748e45435b06cf8dd105b73e9855f93e",
    "data": "0xffa2ca3b44eea7c8e659973cbdf476546e9e6adfd1c580700537e52ba7124933a97904ea000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001d0e30db00300ffffffffffffc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a0",
    "gasLimit": 500000,
    "value": "100000",
    "blockNumber": 16784600
  }
]

Example response:

[{
  "gasUsed": 214622,
  "blockNumber": 16784600,
  "success": true,
  "trace": { ... },
  "logs": [ ... ],
  "exitReason": "Return"
}]

Notes:

  • chainId must be the same in all transactions.
  • blockNumber can be included and incremented when a multi-block simulation is required, or omitted in all transactions to use latest.

POST /api/v1/simulate-stateful

Starts a new stateful simulation, allowing you to persist the state of a single EVM across multiple subsequent simulation requests.

See the full request and response types below.

Example body:

[
  {
    "chainId": 1,
    "gasLimit": 500000,
    "blockNumber": 16784600
  }
]

Example response:

[{
  "statefulSimulationId": "aeb708a5-81d7-4126-a0b5-0f2a78b3830e",
}]

POST /api/v1/simulate-stateful/{statefulSimulationId}

Simulates a bundle of transactions in order against the EVM referred to by the UUID in the URL. After the result is obtained, the EVM state will be retained for subsequent requests.

See the full request and response types below.

Example body:

[
  {
    "chainId": 1,
    "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    "to": "0x66fc62c1748e45435b06cf8dd105b73e9855f93e",
    "data": "0xffa2ca3b44eea7c8e659973cbdf476546e9e6adfd1c580700537e52ba7124933a97904ea000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001d0e30db00300ffffffffffffc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a0",
    "gasLimit": 500000,
    "value": "100000",
    "blockNumber": 16784600
  }
]

Example response:

[{
  "gasUsed": 214622,
  "blockNumber": 16784600,
  "success": true,
  "trace": { ... },
  "logs": [ ... ],
  "exitReason": "Return"
}]

Notes:

  • chainId must be the same in all transactions.
  • blockNumber can be included and incremented when a multi-block simulation is required, or omitted in all transactions to use latest.

DELETE /api/v1/simulate-stateful/{statefulSimulationId}

Ends a current stateful simulation, freeing associated memory.

See the full request and response types below.

Example response:

{
  "success": true
}

Authentication

If you set an API_KEY environment variable then all calls to the API must be accompanied by a X-API-KEY header which contains this API Key.

๐Ÿƒโ€โ™‚๏ธ Running ๐Ÿƒโ€โ™‚๏ธ

Locally

Copy .env.example to .env, fill out required values and run:

$ cargo run

If you want the server to restart on any code changes run:

$ cargo watch -x run

๐Ÿงช Test ๐Ÿงช

Run:

$ cargo test

Manual Testing

body.json contains a simple request in the root of the project so once the API is running you can just run:

$ curl -H "Content-Type: application/json" --data @tests/body.json http://localhost:8080/api/v1/simulate

If you have jq installed, you can run this to see pretty traces:

$ curl -H "Content-Type: application/json" --data @tests/body.json http://localhost:8080/api/v1/simulate | jq -r ".formattedTrace"

๐Ÿงญ Roadmap ๐Ÿงญ

  • Support any RPC endpoint, not just Alchemy
  • Connect to local node via IPC
  • Connect to local reth DB
  • Support simulating a bundle of transactions against different blocks, applying state as the simulation progresses. Would help support paradigmxyz/reth#2018
  • Support more authentication methods

Contributing

See CONTRIBUTING.md.

Types

export type SimulationRequest = {
  chainId: number;
  from: string;
  to: string;
  data?: string;
  gasLimit: number;
  value: string;
  accessList?: AccessListItem[];
  blockNumber?: number; // if not specified, latest used,
  blockTimestamp?: number; // if not specified, timestamp of latest block is used,
  stateOverrides?: Record<string, StateOverride>;
  formatTrace?: boolean;
};

export type AccessListItem = {
  address: string;
  storageKeys: string[];
};

export type StateOverride = {
  balance?: string;
  nonce?: number;
  code?: string;
  state?: Record<string, string>;
  stateDiff?: Record<string, string>;
};

export type SimulationResponse = {
  simulationId: string;
  gasUsed: number;
  blockNumber: number;
  success: boolean;
  trace: CallTrace[];
  logs?: Log[];
  exitReason?: InstructionResult;
  bytes: string;
  formattedTrace?: string;
};

export type Log = {
  topics: string[];
  data: string;
  address: string;
};

export type CallTrace = {
  callType: CallType;
  from: string;
  to: string;
  value: string;
};

export enum CallType {
  CALL,
  STATICCALL,
  CALLCODE,
  DELEGATECALL,
  CREATE,
  CREATE2,
}

export enum InstructionResult {
  //success codes
  Continue,
  Stop,
  Return,
  SelfDestruct,

  // revert code
  Revert, // revert opcode
  CallTooDeep,
  OutOfFund,

  // error codes
  OutOfGas,
  OpcodeNotFound,
  CallNotAllowedInsideStatic,
  InvalidOpcode,
  InvalidJump,
  InvalidMemoryRange,
  NotActivated,
  StackUnderflow,
  StackOverflow,
  OutOfOffset,
  FatalExternalError,
  GasMaxFeeGreaterThanPriorityFee,
  PrevrandaoNotSet,
  GasPriceLessThenBasefee,
  CallerGasLimitMoreThenBlock,
  /// EIP-3607 Reject transactions from senders with deployed code
  RejectCallerWithCode,
  LackOfFundForGasLimit,
  CreateCollision,
  OverflowPayment,
  PrecompileError,
  NonceOverflow,
  /// Create init code exceeds limit (runtime).
  CreateContractLimit,
  /// Error on created contract that begins with EF
  CreateContractWithEF,
}

๐Ÿ™ Thanks ๐Ÿ™

temper's People

Contributors

ape-dev-cs avatar devanoneth avatar fleupold avatar martinquaxd avatar nlordell avatar threeandtwo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

temper's Issues

Setting timeouts

Is it possible to set a timeout for simulations? If it's not currently implemented, perhaps someone can guide me on how I'd do this? (I'm new to Rust) After running a large number of tx simulations, the requests start to take too long and begin to pile up. It starts out fine, each request takes about 500ms, but then after a few hours, they start to take almost 2 minutes sometimes

 INFO  ts::api > 127.0.0.1:41146 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 39.328261509s
 INFO  ts::api > 127.0.0.1:34204 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 41.263612718s
 INFO  ts::api > 127.0.0.1:35974 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 40.302425564s
 INFO  ts::api > 127.0.0.1:47990 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 39.711832523s
 INFO  ts::api > 127.0.0.1:34482 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 38.599683218s
 INFO  ts::api > 127.0.0.1:45208 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 41.888975767s
 INFO  ts::api > 127.0.0.1:54828 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 44.406452195s
 INFO  ts::api > 127.0.0.1:52346 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 40.537302536s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000000b0587c3c4e3da8_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:54074 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 39.372460717s
 INFO  ts::api > 127.0.0.1:49778 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 48.725948585s
 INFO  ts::api > 127.0.0.1:41092 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 40.484692566s
 INFO  ts::api > 127.0.0.1:54498 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 38.929635772s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000010408fd1300d2a78_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:36648 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 37.135938427s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x000000000000000000000000000000000000000000000000032fd9f90ce7b708_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:34276 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 38.96035323s
 INFO  ts::api > 127.0.0.1:43702 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 50.652176765s
 INFO  ts::api > 127.0.0.1:47860 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 41.573264073s
 INFO  ts::api > 127.0.0.1:56966 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 52.65881698s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000000e943de80380e58_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:60000 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 40.21847157s
 INFO  ts::api > 127.0.0.1:52894 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 38.013594564s
 INFO  ts::api > 127.0.0.1:43714 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 39.502471144s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x000000000000000000000000000000000000000000000000008f388179435478_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:54870 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 37.79750745s
 INFO  ts::api > 127.0.0.1:34278 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 40.057100279s
 INFO  ts::api > 127.0.0.1:41130 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 41.913044435s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x000000000000000000000000000000000000000000000000a0933d25f34875f7_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000001eac882c453d710_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:52922 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 38.517212262s
 INFO  ts::api > 127.0.0.1:50130 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 36.505642283s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000001851cc637109ae5_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:50246 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 37.840279734s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000026562b8d2de144b8_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000082e31d6d93184ba0_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:47888 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 38.80887147s
 INFO  ts::api > 127.0.0.1:34352 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 39.649646456s
 INFO  ts::api > 127.0.0.1:41336 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 38.323364994s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000001702f163c32e9c8_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:34462 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 38.237915451s
 INFO  ts::api > 127.0.0.1:52456 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 39.019137944s
 INFO  ts::api > 127.0.0.1:34290 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 58.059195845s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000012acfb4d67706768_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:40912 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 38.001337322s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000003a0af0d31394040_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:58192 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 37.081051367s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000002f70e7290757df4_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:60226 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 36.945840985s
 INFO  ts::api > 127.0.0.1:54162 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 37.452374699s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x0000000000000000000000000000000000000000000000000059180276515598_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:37472 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 34.201172818s
 INFO  ts::api > 127.0.0.1:35338 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 38.607602289s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x0000000000000000000000000000000000000000000000001f39791815a32e58_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:34142 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 36.29515275s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x0000000000000000000000000000000000000000000000000388a24f1ad5ac40_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:33440 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 37.593369267s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000013ec6f169773e480_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:36688 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 31.780975829s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x000000000000000000000000000000000000000000000000085282127ef409d0_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:58228 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 35.625268199s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x000000000000000000000000000000000000000000000000032fd0f103732c40_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:56932 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 37.554852511s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x000000000000000000000000000000000000000000000000010f2cbcc7659bcc_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:54110 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 33.451618992s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000447c5c4444da7ec40_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000023abb281e2c207a0_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:33270 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 34.061162239s
 INFO  ts::api > 127.0.0.1:34400 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 33.075862895s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000002257262c98c0f58_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:56902 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 32.093076131s
 INFO  ts::api > 127.0.0.1:51792 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 34.969364768s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x0000000000000000000000000000000000000000000000000170ccd587a6f0fe_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:52914 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 33.378202003s
 INFO  ts::api > 127.0.0.1:50202 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 46.514351044s
 INFO  ts::api > 127.0.0.1:47944 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 34.343456828s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000016e9650bc20e4c40_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:34298 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 33.861438118s
[src/evm.rs:240] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x0000000000000000000000000000000000000000000000000161f6a156a62c40_U256, balance: 0x0000000000000000000000000000000000000000000000000000000000000000_U256 })"
 INFO  ts::api > 127.0.0.1:41150 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "Bun/1.0.11" 31.956652852s
 INFO  ts::api > 127.0.0.1:34322 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 31.983531479s
 INFO  ts::api > 127.0.0.1:57008 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 51.765085951s
 INFO  ts::api > 127.0.0.1:60466 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 102.407593516s
 INFO  ts::api > 127.0.0.1:36792 "POST /api/v1/simulate-bundle HTTP/1.1" 200 "-" "Bun/1.0.11" 128.916109934s

Formattrace - Huge impact on performance

I'm not sure if this is expected behavior, but when benchmarking around 100 simulations of single txs I get the following results :

Without formattrace : 200 / 300 ms

With formattrace : 1.5-2.5 seconds

Is this normal ?

Also not sure why in the env file it says formattrace won't work without etherscan API key, I get the same formattrace format regardless if I use key or not .

Arbitrum transactions fail with "FatalExternalError"

The following simulation fails with exitReason": "FatalExternalError",

{
  "chainId": 42161,
  "from": "0xe17b992903e2a14b7e7dd5fc3d8820d2fb564d5d",
  "to": "0xb45a2dda996c32e93b8c47098e90ed0e7ab18e39",
  "data": "0xc10bea5c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008bb0d6fe0061b5f46742415bea3621f4af01f9c7000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9000000000000000000000000f7a2f863299c17dfa11cd8a14e7c7dca92f315b9000000000000000000000000e17b992903e2a14b7e7dd5fc3d8820d2fb564d5d0000000000000000000000000000000000000000000000000a420bb3b4ab4f400000000000000000000000000000000000000000000000000000000016060da80000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000000000000000000000000000000000000000000007616e64726f69640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008bb0d6fe0061b5f46742415bea3621f4af01f9c7000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9000000000000000000000000e17b992903e2a14b7e7dd5fc3d8820d2fb564d5d00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000164ac3893ba0000000000000000000000000000000000000000000000000a3a2ae61c51b528000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e17b992903e2a14b7e7dd5fc3d8820d2fb564d5d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000648148f700000000000000000000000000000000000000000000000000000000000000040000000000000000000000008bb0d6fe0061b5f46742415bea3621f4af01f9c700000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000ff970a61a04b1ca14834a43f5de4533ebddb5cc8000000000000000000000000fd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb900000000000000000000000000000000000000000000000000000000",
  "gasLimit": 2950564,
  "value": "0",
  "blockNumber": 98910642,
  "formatTrace": false
}

response

{
	"simulationId": 1,
	"gasUsed": 0,
	"blockNumber": 98910642,
	"success": false,
	"trace": [
		{
			"callType": "CALL",
			"from": "0x0000000000000000000000000000000000000000",
			"to": "0x0000000000000000000000000000000000000000",
			"value": "0x0"
		}
	],
	"formattedTrace": null,
	"logs": [],
	"exitReason": "FatalExternalError",
	"returnData": "0x"
}

I changed the RPC multiple times from the ones listed here => https://chainlist.org/chain/42161, but they all return the same exception

unhandled rejection: Rejection(PayloadTooLarge)

First of all I need to say I have no idea if this simulator is a viable option for handling a high amount of txs in a short period of time (in a single request), let's say anything between 200 and 500 txs for a given block .

Having said that, there is a payload size limit for the server accepting the curl requests and the bottleneck is reached quite easily so simulating anything like even 50 transactions in a single request is impossible .

I tried modifying warp to accomodate for bigger payload but kept getting the same error .

unhandled rejection: Rejection(PayloadTooLarge)

Where could we modify the maximum payload size please ?

Thanks

Add support of ipc providers

Current implementation use http provider to create fork and simulate transaction, it can be much more faster with ipc provider

Support for Shanghai / Solidity 0.8.20

Tangentially related to other issues, but as an old version of revm is used, the PUSH0 opcode introduced in Shanghai will always cause a revert, meaning that anything compiled with 0.8.20 won't run in the simulator.

Minted successful transactions reverting wrongly

I am noticing a lot of transactions are showing as reverted during simulation even when they were successful on chain and we recreate all the same conditions in the simulation .

I thought this was an old issue related to contracts compiled with 0.8.20 but that issue has been addressed already .

Example of a token swap after the trading of a token was enabled (Simulating same block where the sequence took place)

curl -H "Content-Type: application/json" --data '[{ "chainId": 1, "from": "0xdACA53A595CCf52215093d870c6C9C1B9b9576E5", "to": "0xFBe804ACA20a6E4aD5380B55eA70Ef2919732Ed3", "data": "0xc9567bf9", "gasLimit": 30000, "value": "0", "blockNumber": 17713701 }, { "chainId": 1, "from": "0x4789dc1067636cc1B6936699c170f1BFF9De0574", "to": "0xBDa41EA6Cc112d1b65795777b9C1B76F35b6dC4E", "data": "0x627dd56a000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000fbe804aca20a6e4ad5380b55ea70ef2919732ed3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000665d14f05984735949c000000000000000000000000000000000000000000000000000000a6fa4040718000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "gasLimit": 300000, "value": "0", "blockNumber": 17713701 }]' http://localhost:9081/api/v1/simulate-stateful/33b11f54-451d-4b54-8485-64a022a7f020

The first transaction is successful but the second one isn't, although it was successful on the simulated block .

This happens both when using simulate-stateful and simulate-bundle

Current Simulation halts on multiple EVM errors

I have been playing around with simulation bundles and noticed everytime there is an EVM error in one of the transactions the entire simulation stops and there isn't a response at all .

Response data: { code: 500, message: 'EVM_ERROR' }

On the backend :

INFO ts::api > 127.0.0.1:40026 "POST /api/v1/simulate-bundle HTTP/1.1" 500 "-" "axios/0.27.2" 1.702706046s [src/evm.rs:177] &err = "backend: failed while inspecting: Transaction(LackOfFundForGasLimit { gas_limit: 0x00000000000000000000000000000000000000000000000027d449cb495f0000_U256, balance: 0x00000000000000000000000000000000000000000000000000174e50d6e133ec_U256 })"

Errors like these and other present on the error handling file are apparently pretty common, so it would be nice if the current simulation would just skip the particular transaction causing any of these errors instead of exiting with an error and failing to simulate everything else .

[QUESTION] Persistent simulation: How to end a session?

Hey there! First of all, thank you for such a blazing fast implementation of a transaction simulator. I am still stunned about how performant it is.

As a disclaimer, my knowledge about Rust memory allocation is far from the best.

I am using a multi-step simulation getting a session ID and I wasn't able to find an endpoint to close such a session, so in my understanding, this session will be kept in memory during the entire runtime unless the server is restarted, right? As I am hammering the service with thousands of different concurrent sessions that won't be reused, I got a bit worried about them lingering for eternity.

Am I correct in this assumption?

Cheers!

FatalExternalError on valid transactions

I get this error quite often for no apparent reason

Json body:

[
  {
    "chainId": 1,
    "from": "0xF5D2d4f61675568AAF2fd9d7F4a8C3fc478bB2c0",
    "to": "0xEf1c6E67703c7BD7107eed8303Fbe6EC2554BF6B",
    "data": "0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000646fcd3f00000000000000000000000000000000000000000000000000000000000000030b090c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000001e60176d18aaae6000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000378f609379acd0acbd20000000000000000000000000000000000000000000000000001e60176d18aaae600000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000a3a122766d611a96c929c99d60a2b7e622705b6b000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000",
    "gasLimit": 250000,
    "value": "136798448514673382",
    "blockNumber": 17338560,
    "formatTrace": true
  },
  {
    "chainId": 1,
    "from": "0x22a6894B11da57000c35159395246e3402DB5665",
    "to": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
    "data": "0xfb3bdb4100000000000000000000000000000000000000050c783eb9b5c85f2a80000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000022a6894b11da57000c35159395246e3402db56650000000000000000000000000000000000000000000000000000018859fb352c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000009f493f51ed6da4573578a6843c7e041e9bec012a",
    "gasLimit": 521000,
    "value": "500000000000000000",
    "blockNumber": 17338560,
    "formatTrace": true
  }
]

And here is my curl request :

curl -H "Content-Type: application/json" --data @tests/body.json http://localhost:9080/api/v1/simulate-bundle

The response :

[{"simulationId":1,"gasUsed":0,"blockNumber":17338560,"success":false,"trace":[{"callType":"CALL","from":"0x0000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000","value":"0x0"}],"formattedTrace":" [0] \u001b[31m0x0000000000000000000000000000000000000000\u001b[0m::\u001b[31mfallback\u001b[0m() \u001b[33m\u001b[0m\n โ””โ”€ \u001b[31mโ† \u001b[0m()\n","logs":[],"exitReason":"FatalExternalError","returnData":"0x"},{"simulationId":1,"gasUsed":0,"blockNumber":17338560,"success":false,"trace":[{"callType":"CALL","from":"0x0000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000","value":"0x0"}],"formattedTrace":" [0] \u001b[31m0x0000000000000000000000000000000000000000\u001b[0m::\u001b[31mfallback\u001b[0m() \u001b[33m\u001b[0m\n โ””โ”€ \u001b[31mโ† \u001b[0m()\n","logs":[],"exitReason":"FatalExternalError","returnData":"0x"}]

Add support for gzip

Test with:

curl -v -d "@data.json" -H 'Accept-encoding: gzip' -H "Content-Type: application/json" -X POST http://localhost:8080/api/v1/simulate

You will notice that the server doesn't support compression.

Update dependencies to support dencun

Since the dencun hardfork temper reports reverts when simply simulating with ethereum nodes does not.
Currently our assumption is that this is caused by outdated dependencies that are not yet aware of the new behavior introduced by the dencun hardfork.
Would it be possible to update the dependencies to reasonably current versions to resolve this? ๐Ÿ™

Simulating with a custom gas price

Currently, it seems all transactions are simulated with a gas_price of 0 gwei (base_fee_per_gas and priority_fee_per_gas are both set to 0). This means the LackOfFundForGasLimit EVM error is only caused by a transaction being sent with a value that is higher than the amount of ETH held by the from address.
It would be very useful if Temper also supported simulating with a custom gas_price so that a simulation fails if the from address does not have enough ETH to pay for gas * price + value.
In this case, there would be two options.

  • The easiest option to implement would probably be to just set the gas_price and let Foundry handle the failure, but in this case Foundry will likely use the provided gasLimit to calculate the total gas cost, instead of the actual amount of gas used by the tx.
  • A nicer (but likely more difficult to implement) option would be to fail a TX when the from address does not have enough ETH for the amount of gas that was actually used (+ the value of the tx).
    One (inefficient) way to implement this second option is by simulating the transaction twice, once with a gas_price of 0, gasLimit set to the maximum of the block and calling call_raw without committing the result. The second simulation could then set the gas_price to the one provided by the user, and set the gasLimit to the amount of gas used in the first simulation.

If the second option is implemented, some use cases may still benefit from the option to check for the LackOfFundForGasLimit error using a user-provided gasLimit instead of the simulated amount, which could be implemented by only running the first simulation if the user does not provide their own gasLimit parameter. This would make the gasLimit parameter optional.

A slight ease-of-use addition would be to automatically use the base_fee_per_gas from the block if the user provides a priority_fee_per_gas without explicitly providing a base_fee_per_gas. If the user provides a gas_price (pre- eip-1559), the base- and priority fee could be set automatically

Transparent EVM errors

Currently, when an EVM error occurs that is not being parsed yet, the response received is {"code":500,"message":"EVM_ERROR"} (see https://github.com/EnsoFinance/temper/blob/main/src/errors.rs#L81).
In this case, the only way to check which error occurred is to check the Temper CLI logs. It would be nice to have the option to receive the raw EVM error instead of, or in addition to, the parsed error.
A possible way to do this without making it the default behaviour would be to add an optional parameter like "transparent_error": true to the /api/v1/simulate, /api/v1/simulate-bundle and /api/v1/simulate-stateful endpoints.

In addition to getting specific errors for types that are not parsed yet, this would also help users find errors in their transactions more easily, since the raw EVM errors may contain more details.

single threaded not available

so I wanted to use this lib in a single threaded project setup that I have, but I get this error when trying to run things:
thread 'main' panicked at /ethers-rs-c3a7c0a0ae0fe6be/df165b8/ethers-solc/src/utils.rs:437:48: can call blocking only when running on the multi-threaded runtime

any idea how this can be fixed or any known workarounds?
thank you

Assets state Change

This is a feature request .

Currently, temper only supports state changes for native balance but it does not process other assets tracing such as wrapped ethereum .

Being able to identify assets state changes is crucial for multiple applications .

Implementation suggestion :

Add 2 endpoints for assets state change , for eg :

/simulateAssetsChange
/simulateBundleAssetsChange

State override in simulate-tx

Hello, i've discoverd the temper project recently, and 'im trying to simulate a transaction overriding my balance.
I want to send a tx to a contract that will perform operations, so i need to override it's balance, here is the body of the request :

body = {
"chainId": 5,
"from": account.address,
"to": phantom.address,
"data": tx['input'],
"gasLimit": 500000,
"blockNumber": w3.eth.get_block_number(),
'stateOverrides': {
phantom.address: {
'balance': "100000000000000000000"
}
}
}

The transaction is correctly simulated, but the phantom contract balance is not overriden (still 0), do you know what's the problem here ? :/
I'm testing my contract on goerli, maybe this can cause issues
In the function i call in my contract, i have this require at the beginning :

require(address(this).balance > 0, "eth balance of phantom is empty :')");

Which always fails :/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.