evmts / tevm-monorepo

An ecosystem of ethereum tools to build robust TypeScript applications
https://tevm.dev
MIT License
199 stars 16 forks source link
evm forge solidity typescript

An ecosystem of tools to build robust Ethereum applications in TypeScript for Viem

CI NPM Version Tevm Downloads Tevm Bundler Downloads Minzipped Size

tevm-monorepo

Tevm tools include an Ethereum devnet that can run in the Browser and Node.js along with a solidity bundler that allows you to import solidity directly into TypeScript files. All built on top of the viem API.

// import solidity directly into typescript
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'
import { createMemoryClient, http } from 'tevm'
import { optimism } from 'tevm/common'

// create a anvil-like devnet directly in TypeScript
const client = createMemoryClient({
  common: optimism,
  fork: {transport: http('https://mainnet.optimism.io')()}
})

// execute the EVM locally in the browser, node.js, deno and Bun
const balance = await client.readContract(
  ERC20
    .withAddress('0x4200000000000000000000000000000000000042')
    .read
    .balanceOf('0xd8da6bf26964af9d7eed9e03e53415d37aa96045')
)

Table of Contents

Overview

Tevm is modular, easy to pick up, and built on top of viem.

Tevm consists of the following modular tools:

These tools are modular and can be used by themselves but they also compose very well together with each other and with viem/wagmi.

Examples

ethereum simulator preview

MemoryClient

MemoryClient is an anvil-like Ethereum devnet specially crafted for TypeScript applications and tests.

✅  Built on top of viem and supports all Viem APIs
✅  Runs in the browser, Node.js, and Bun
✅  Supports forking akin to anvil --fork-url
✅  Can generate EVM traces and access lists
✅  HTTP handlers for running as a server in tests or backends
✅  Full support for the Ethereum JSON-RPC API and anvil_ API

With MemoryClient, you can easily solve a lot of previously tough-to-solve problems:

MemoryClient Example

import { createMemoryClient, http } from 'tevm'
import { optimism } from 'tevm/common'

// To start the MemoryClient, simply call `createMemoryClient`
const client = createMemoryClient({
  // MemoryClient supports anvil-like forking
  fork: { transport: http('https://mainnet.optimism.io') },
  common: optimism,
})

// MemoryClient supports the entire viem API
const blockNumber = await client.getBlockNumber()

// MemoryClient can arbitrarily modify accounts
client.tevmSetAccount({
  address: `0x${'69'.repeat(20)}`,
  nonce: 9,
  balance: 420n,
  deployedBytecode: '0x...',
  // ...
})

// MemoryClient can impersonate any account
const { data, errors, events, executionGasUsed, logs } = client.tevmContract({
  createTransaction: true,
  address: `0x${'69'.repeat(20)}`,
  abi: [...],
  functionName: 'transferFrom',
  args: [...],
})

const { blockHash } = await client.tevmMine()

Tevm Bundler + LSP

Tevm Bundler

The Tevm Bundler is the next-generation build-time tool version of tools like Typechain. The Tevm Bundler removes the need to copy-paste ABIs or set up complicated build pipelines. With the Bundler, you can directly import Solidity contracts into your TypeScript files. This brings a TRPC-like experience to Contract-TypeScript code.

Tevm also supports code-generation of TypeScript from Solidity contracts, similar to TypeChain.

The Tevm Bundler builds Contracts and Scripts that modularly work with Viem, Wagmi, and Tevm.

// Import Solidity directly into TypeScript. The Tevm Bundler will compile the contracts to TevmContracts and TevmScripts
import { ERC20 } from '@openzeppelin/contracts/token/ERC20/ERC20.sol'

console.log(ERC20.abi)
console.log(ERC20.humanReadableAbi)

// Use the contracts with Wagmi, Viem, or Tevm. In this example, Wagmi
const { data } = useReadContract(
  ERC20.read.balanceOf(`0x${'01'.repeat(20)}`)
)

image image image

Tevm LSP

The Tevm LSP is a ts-plugin that allows your code editor to pick up types from your Solidity imports if using the Tevm Bundler.

image

Tevm Contracts

Tevm contracts are an extremely lightweight modular abstraction for interacting with viem, wagmi, and tevm. They are created automatically if using the Tevm Bundler via importing Solidity but can also be created manually.

They can also be used with ethers to create type-safe contracts.

import { createContract } from 'tevm/contract'

const script = createContract({
  name: 'MyScript',
  humanReadableAbi: ['function exampleRead() returns (uint256)', ...],
  bytecode: '0x123...',
  deployedBytecode: '0x123...',
  address: '0x123...'
})

// Use with Wagmi
useReadContract(script.read.exampleRead())

// Use with Viem/Tevm
client.readContract(script.read.exampleRead())

// Even use with ethers to create a type-safe contract
import { Contract } from '@tevm/ethers'
const contract = new Contract(script.address, script.abi, provider)
// This will be type-safe
const res = await contract.read()

Tevm Scripting

Tevm scripting allows arbitrary Solidity execution similar to Forge scripts. Instead of cheat codes, Tevm allows you to very easily bring your own cheat codes via executing arbitrary JavaScript. See the Tevm scripting guide for information on how to build scripts.

Because Tevm also allows scripts to execute arbitrary JavaScript, scripts can be extremely powerful. For example, one could build a library for writing servers in Solidity.

Join Telegram

Visit Docs (under construction) for docs, guides, API, and more! 📄

Contributing 💻

Contributions are encouraged, but please open an issue before making any major changes to ensure your changes will be accepted.

See CONTRIBUTING.md for contributing information.

License 📄

Most files are licensed under the MIT license. Some files copied from ethereumjs inherit the MPL-2.0 license. These files are individually marked at the top and are all in the @tevm/state, @tevm/blockchain, and other packages that wrap ethereumjs libraries.