# How 3DPass Achieves EVM Compatibility: Technical Architecture Explained

> Discover how 3DPass achieves EVM compatibility using pallet-evm, SputnikVM, deterministic address translation, and the Frontier framework. Learn about its technical architecture.

- Repository: [3Dpass/3dp](https://github.com/3dpass/3dp)
- Tags: architecture
- Published: 2026-02-23

---

**3DPass achieves full EVM compatibility by embedding the `pallet‑evm` runtime module powered by SputnikVM, implementing deterministic address translation between Substrate `H256` and Ethereum `H160` formats, and exposing standard Ethereum JSON‑RPC endpoints through the Frontier framework.**

The 3DPass blockchain is built on Substrate yet offers native support for unmodified Ethereum smart contracts. By bridging the gap between Substrate's native runtime and the Ethereum Virtual Machine, 3DPass allows Solidity developers to deploy existing dApps while maintaining access to Substrate-native features like on-chain identity and asset management.

## Core Architecture Components

The EVM integration relies on several interconnected pallets and mapping layers that translate between Ethereum and Substrate paradigms.

### pallet-evm Runtime Integration

At the heart of 3DPass EVM compatibility lies the **`pallet‑evm`** configured in [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs). This pallet embeds the SputnikVM engine to execute Ethereum bytecode directly within the Substrate runtime. The configuration defines critical parameters including the `Runner` trait implementation, gas-to-weight conversion ratios, and the EVM `ChainId`.

The runtime implements `pallet_evm::Config for Runtime` at line 1534 of [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs), specifying how contract calls and creations are dispatched through the `Runner::call` and `Runner::create` methods.

### Deterministic Address Mapping

3DPass uses **`HashedAddressMapping<BlakeTwo256>`** to establish a bi-directional mapping between Substrate native accounts (`AccountId` as `H256`) and Ethereum addresses (`H160`). This deterministic hashing ensures every Substrate account automatically possesses a corresponding EVM address, enabling seamless cross-platform token transfers and asset interactions.

The mapping type is declared in [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs) at line 41:

```rust
type AddressMapping = HashedAddressMapping<BlakeTwo256>;

```

## Chain Configuration and Identity

Beyond the execution engine, 3DPass configures Ethereum-compatible network parameters to ensure compatibility with standard tooling.

### Chain ID and Network Parameters

The **`pallet_evm_chain_id`** pallet configures the network identifier that MetaMask, ethers.js, and other Ethereum tools use to identify the 3DPass chain. This configuration appears in [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs) at line 1511 as `impl pallet_evm_chain_id::Config for Runtime {}`.

### Block Hash and Fee Handling

For full Ethereum RPC compatibility, 3DPass implements **`pallet_ethereum::EthereumBlockHashMapping`** to handle `blockHash` queries, and integrates the `BaseFee` pallet for EIP-1559-compliant dynamic fee calculations. These components ensure that Ethereum clients receive expected responses when querying historical blocks or estimating gas costs.

The `BlockHashMapping` type is defined in [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs) at line 38.

## Precompiles: Bridging Solidity and Substrate

Precompiles expose native Substrate functionality as Ethereum-compatible contract addresses, allowing Solidity code to interact with native pallets.

### FrontierPrecompiles Implementation

The **`FrontierPrecompiles<R>`** type aggregates standard Ethereum precompiles (SHA-256, RIPEMD-160, etc.) alongside custom 3DPass-specific precompiles. This collection bridges Substrate pallets—such as identity, assets, and proxy modules—to Solidity contracts via deterministic address calls.

Custom precompiles are registered in [`runtime/src/precompiles.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/precompiles.rs), with individual implementations located in `precompiles/*/src/lib.rs` directories (e.g., [`precompiles/identity/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/precompiles/identity/src/lib.rs)).

### Accessing Substrate Features from Solidity

Developers can call Substrate-native functions directly from Solidity by targeting specific precompile addresses. For example, the Identity precompile at `0x00000000000000000000000000000000000405` exposes `pallet_identity` functionality:

```solidity
interface IIdentity {
    function setIdentity(address who, bytes calldata info) external;
}

contract Registry {
    IIdentity constant ID = IIdentity(address(0x00000000000000000000000000000000000405));
    
    function register(bytes calldata info) external {
        ID.setIdentity(msg.sender, info);
    }
}

```

When this contract executes, the EVM routes the call through the Identity precompile implementation back to the Substrate runtime.

## RPC Layer and Transaction Lifecycle

The **`frontier/rpc-core`** crate provides the translation layer between Ethereum JSON-RPC calls and Substrate extrinsics.

### Transaction Processing Pipeline

When a user submits an Ethereum transaction via `eth_sendRawTransaction`, the RPC handler defined in [`frontier/rpc-core/src/eth.rs`](https://github.com/3dpass/3dp/blob/main/frontier/rpc-core/src/eth.rs) decodes the raw bytes, validates nonces and gas limits using logic from [`primitives/evm/src/validation.rs`](https://github.com/3dpass/3dp/blob/main/primitives/evm/src/validation.rs), and dispatches the call through the configured `pallet_evm` runner.

The transaction lifecycle functions `call_evm` and `create_evm` in [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs) (around line 2078) handle the final execution, applying gas metering and state transitions according to Ethereum rules while recording changes to Substrate storage.

## Practical Implementation Examples

### Sending Transactions via Ethereum Tooling

You can interact with 3DPass using standard Ethereum libraries like ethers.js:

```javascript
const { ethers } = require('ethers');

const provider = new ethers.JsonRpcProvider('http://localhost:9944');
const wallet = new ethers.Wallet('<PRIVATE_KEY>', provider);

async function send() {
  const tx = {
    to: '0x1234...abcd',
    value: ethers.parseEther('0.01')
  };
  const receipt = await wallet.sendTransaction(tx);
  console.log('Tx hash:', receipt.hash);
}

send();

```

The RPC endpoint processes this through `frontier/rpc-core` before reaching the EVM pallet at [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs).

### Converting Between Address Formats

For runtime developers working in Rust, converting between Substrate accounts and EVM addresses uses the configured mapping:

```rust
use pallet_evm::AddressMapping;

let substrate_account: <Runtime as frame_system::Config>::AccountId = ...;
let evm_address: sp_core::H160 = 
    <Runtime as pallet_evm::Config>::AddressMapping::into_account_id(substrate_account);

```

This conversion utilizes the same `HashedAddressMapping<BlakeTwo256>` logic applied to all cross-vm interactions.

## Summary

- **3DPass integrates `pallet‑evm`** with SputnikVM to execute unmodified Ethereum bytecode within the Substrate runtime via [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs).
- **Deterministic address mapping** through `HashedAddressMapping<BlakeTwo256>` ensures every Substrate `H256` account maps to a unique Ethereum `H160` address.
- **Frontier precompiles** bridge Solidity contracts to native Substrate pallets like identity and assets through specialized contract addresses.
- **EIP‑1559 compatibility** is achieved through the `BaseFee` pallet and `EthereumBlockHashMapping` for complete Ethereum RPC parity.
- **Standard Ethereum tooling** works out-of-the-box via the `frontier/rpc-core` translation layer that converts JSON-RPC calls to Substrate extrinsics.

## Frequently Asked Questions

### How does 3DPass convert Substrate addresses to Ethereum addresses?

3DPass uses the `HashedAddressMapping<BlakeTwo256>` type defined in [`runtime/src/lib.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/lib.rs) to deterministically hash Substrate `AccountId` (32-byte `H256`) values into Ethereum-compatible `H160` addresses. This ensures every native account automatically has a corresponding EVM address without manual registration.

### Can I use MetaMask to interact with 3DPass?

Yes. 3DPass exposes standard Ethereum JSON-RPC endpoints through the `frontier/rpc-core` implementation, allowing MetaMask to connect using the network's Chain ID configured in the `pallet_evm_chain_id` pallet. Transactions signed in MetaMask are processed by the same validation logic found in [`primitives/evm/src/validation.rs`](https://github.com/3dpass/3dp/blob/main/primitives/evm/src/validation.rs).

### What precompiles are available on 3DPass?

3DPass includes standard Ethereum precompiles plus custom extensions for Substrate pallets. The `FrontierPrecompiles` type in [`runtime/src/precompiles.rs`](https://github.com/3dpass/3dp/blob/main/runtime/src/precompiles.rs) aggregates these, including implementations for identity management, batch calls, and asset transfers located in the `precompiles/` directory.

### How are gas fees calculated in 3DPass EVM transactions?

The network implements EIP-1559 fee mechanics using the `BaseFee` pallet alongside gas-to-weight mappings defined in the `pallet_evm` configuration. This allows Ethereum-compatible fee estimation while converting gas costs to Substrate weight units for block execution limits.