Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ RPC_URL="http://localhost:8545"
# Private key used to deploy contracts on the local chain
PRIVATE_KEY="0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133"

PRIVATE_KEYS="0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133","0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ codegen/*.json
codegen/abi/*
codegen/pvm/*
codegen/evm/*
codegen/libs/*
*.sha256.txt

# Benchmark artifacts
Expand Down
100 changes: 100 additions & 0 deletions benchmark/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Benchmark Development Guide

Compare smart contract performance across different languages (Solidity, ink!, Rust) and VMs (EVM, PolkaVM).

## Prerequisites

Install required toolchains:

```sh
# Deno runtime
curl -fsSL https://deno.land/install.sh | sh

# ink! contracts
rustup component add rust-src
cargo install --force --locked --version 6.0.0-beta.1 cargo-contract

# Rust PolkaVM contracts
cargo install --git https://github.com/paritytech/revive.git cargo-pvm --locked --force
```

**Note**: If ink! compilation fails with `panic_immediate_abort` errors, use toolchain 1.91.1.

## Running Benchmarks

Before running, start a development node:

```sh
# For Revive testing
revive_dev_stack

# For Geth testing (set RPC_URL=http://localhost:8545 in .env)
geth-dev
```

And build the necessary metadata:

```
deno task build
```

```sh
# 1. Build all contracts (ink!, Rust, Solidity)
./benchmark/contracts.ts --build

# 2. Deploy and execute benchmark operations (requires running node)
./benchmark/contracts.ts --execute

# 3. Generate reports in benchmark/reports/
./benchmark/contracts.ts --report

# Or run all steps together
./benchmark/contracts.ts --build --execute --report
```

## Adding New Contracts

Edit `benchmark/contracts.ts` and add a new artifact:

```typescript
{
id: 'MyContract',
srcs: [
ink('my_contract'), // ink/my_contract/
rust('my_contract'), // rust/contracts/my_contract.rs
...solidity('my_contract.sol', 'MyContract'), // contracts/my_contract.sol
],
deploy: (id, name, bytecode) => {
return deployContract({
name: { id, name },
bytecode,
args: [], // Constructor arguments
})
},
calls: [
{
name: 'my_operation',
exec: async (address) => {
return await env.wallet.writeContract({
address,
abi: abis.MyContract,
functionName: 'myFunction',
args: [arg1, arg2],
})
},
},
],
}
```

Create the contract source files and run the benchmark.

## Generated Reports

Reports are saved to `benchmark/reports/`:

- **opcode_analysis.md**: Opcode usage breakdown per transaction
- **contract_comparison.md**: Performance comparison across implementations
- **bytecode_size_comparison.md**: Compiled bytecode size comparison

Metrics are stored in `stats.db` (SQLite) for custom analysis.
107 changes: 13 additions & 94 deletions benchmark/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,102 +1,21 @@
#!/usr/bin/env -S deno run --env-file --allow-all
import { deploy as deployContract, env } from '../tools/lib/index.ts'
import { abis } from '../codegen/abis.ts'
import { env } from '../tools/lib/index.ts'
import { logger } from '../utils/logger.ts'
import {
Artifacts,
build,
deleteChainData,
deploy,
execute,
ink,
rust,
solidity,
} from './lib.ts'
import { build, deleteChainData, deploy, execute } from './lib.ts'
import { parseArgs } from '@std/cli'
import { parseEther } from 'viem'

export const contracts: Artifacts = [
{
id: 'Fibonacci',
srcs: [
ink('fibonacci'),
rust('fibonacci'),
rust('fibonacci_u128'),
rust('fibonacci_u256'),
...solidity('fibonacci.sol', 'Fibonacci'),
],
deploy: (id, name, bytecode) => {
return deployContract({
name: { id, name },
bytecode,
args: [],
})
},
calls: [
{
name: 'fib_10',
exec: async (address) => {
return await env.wallet.writeContract({
address,
abi: abis.Fibonacci,
functionName: 'fibonacci',
args: [10],
})
},
},
],
},
{
id: 'SimpleToken',
srcs: [
ink('simple_token'),
rust('simple_token_no_alloc'),
...solidity('simple_token.sol', 'SimpleToken'),
],
deploy: (id, name, bytecode) => {
return deployContract({
name: { id, name },
bytecode,
args: [],
})
},
calls: [
{
name: 'mint',
exec: (address) => {
return env.wallet.writeContract({
address,
abi: abis.SimpleToken,
functionName: 'mint',
args: [
env.wallet.account.address,
10_000_000_000_000_000_000_000_000n,
],
})
},
},
{
name: 'transfer',
exec: async (address) => {
// fund destination first
await env.wallet.sendTransaction({
to: '0x3d26c9637dFaB74141bA3C466224C0DBFDfF4A63',
value: parseEther('1'),
})
// Import contract definitions
import { testContracts } from './contracts/test-contracts.ts'
import { ethereumContracts } from './contracts/ethereum-contracts.ts'

return env.wallet.writeContract({
address,
abi: abis.SimpleToken,
functionName: 'transfer',
args: [
'0x3d26c9637dFaB74141bA3C466224C0DBFDfF4A63',
10_000_000_000_000_000_000_000_000n,
],
})
},
},
],
},
/**
* Combined contracts array for benchmarking
* - testContracts: Simple test contracts (Fibonacci, SimpleToken)
* - ethereumContracts: Real Ethereum contracts (USDT, WETH, USDC, XEN)
*/
export const contracts = [
...testContracts,
...ethereumContracts,
]

const cli = parseArgs(Deno.args, {
Expand Down
Loading