Skip to main content

EVM Compatibility

RP1 provides full Ethereum Virtual Machine compatibility through Ethermint integration.

Overview

FeatureSupport
Solidity0.8.x
EVM VersionShanghai
JSON-RPCFull
Web3.js
Ethers.js
MetaMask

Network Configuration

Mainnet

ParameterValue
Network NameRP1 Mainnet
RPC URLhttps://evm.rp.one
Chain ID1111
Currency SymbolRP1
Block Explorerhttps://explorer.rp.one

Testnet

ParameterValue
Network NameRP1 Testnet
RPC URLhttps://evm.testnet.rp.one
Chain ID1112
Currency SymbolRP1
Block Explorerhttps://testnet.explorer.rp.one

MetaMask Setup

  1. Open MetaMask
  2. Click "Add Network"
  3. Enter network details above
  4. Import your account

Or use:

await window.ethereum.request({
method: 'wallet_addEthereumChain',
params: [{
chainId: '0x457', // 1111 in hex
chainName: 'RP1 Mainnet',
rpcUrls: ['https://evm.rp.one'],
nativeCurrency: {
name: 'RP1',
symbol: 'RP1',
decimals: 18,
},
blockExplorerUrls: ['https://explorer.rp.one'],
}],
});

JSON-RPC Methods

Standard Ethereum Methods

import { ethers } from 'ethers';

const provider = new ethers.JsonRpcProvider('https://evm.rp.one');

// Get balance
const balance = await provider.getBalance('0x...');

// Get block
const block = await provider.getBlock('latest');

// Send transaction
const tx = await wallet.sendTransaction({
to: '0x...',
value: ethers.parseEther('1.0'),
});

// Call contract
const result = await contract.someMethod();

Supported Methods

MethodStatus
eth_chainId
eth_blockNumber
eth_getBalance
eth_getCode
eth_call
eth_sendTransaction
eth_sendRawTransaction
eth_getTransactionReceipt
eth_getLogs
eth_subscribe
eth_getBlockByNumber
eth_getBlockByHash
eth_estimateGas
eth_gasPrice
debug_traceTransaction

RP1-Specific Methods

// Get RP1 privacy status
const privacy = await provider.send('rp1_getPrivacyStatus', [address]);

// Get oracle price
const price = await provider.send('rp1_getOraclePrice', ['BTC']);

Contract Development

Hardhat Configuration

// hardhat.config.js
require('@nomiclabs/hardhat-ethers');
require('@nomiclabs/hardhat-waffle');

module.exports = {
solidity: {
version: '0.8.19',
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
networks: {
rp1: {
url: 'https://evm.rp.one',
chainId: 1111,
accounts: [process.env.PRIVATE_KEY],
gasPrice: 'auto',
},
rp1Testnet: {
url: 'https://evm.testnet.rp.one',
chainId: 1112,
accounts: [process.env.PRIVATE_KEY],
},
},
};

Foundry Configuration

# foundry.toml
[profile.default]
src = 'src'
out = 'out'
libs = ['lib']
solc_version = '0.8.19'

[rpc_endpoints]
rp1 = "https://evm.rp.one"
rp1_testnet = "https://evm.testnet.rp.one"

[etherscan]
rp1 = { key = "${RP1_EXPLORER_KEY}", url = "https://explorer.rp.one/api" }

Precompiled Contracts

RP1 includes special precompiled contracts:

AddressContractPurpose
0x0...100OracleGet price feeds
0x0...101PrivacyShield/unshield
0x0...102LendingBorrow/supply
0x0...103StakingDelegate/undelegate

Using Precompiles

interface IRP1Oracle {
function getPrice(string memory symbol) external view returns (uint256);
function getTWAP(string memory symbol, uint256 period) external view returns (uint256);
}

contract MyDeFi {
IRP1Oracle constant oracle = IRP1Oracle(0x0000000000000000000000000000000000000100);

function getCollateralValue(uint256 amount) public view returns (uint256) {
uint256 price = oracle.getPrice("RP1");
return amount * price / 1e18;
}
}

Address Conversion

RP1 supports both Cosmos (bech32) and EVM (hex) addresses:

import { ethers } from 'ethers';
import { bech32 } from 'bech32';

// EVM to Cosmos
function evmToCosmos(evmAddress) {
const bytes = ethers.getBytes(evmAddress);
const words = bech32.toWords(bytes);
return bech32.encode('rp1', words);
}

// Cosmos to EVM
function cosmosToEvm(cosmosAddress) {
const { words } = bech32.decode(cosmosAddress);
const bytes = bech32.fromWords(words);
return ethers.hexlify(bytes);
}

// Example
const evmAddr = '0x1234567890123456789012345678901234567890';
const cosmosAddr = evmToCosmos(evmAddr);
// rp1qzgxqxzsv9s2zwx...

Gas Mechanics

OperationGas Cost
Simple transfer21,000
Contract deployVariable
Storage write20,000
Storage read2,100
Oracle call5,000

Gas Price Oracle

const gasPrice = await provider.getGasPrice();
// Returns gas price in wei

// For EIP-1559
const feeData = await provider.getFeeData();
console.log('Max Fee:', feeData.maxFeePerGas);
console.log('Priority Fee:', feeData.maxPriorityFeePerGas);

Events and Logs

// Subscribe to events
const filter = contract.filters.Transfer();
contract.on(filter, (from, to, amount) => {
console.log(`Transfer: ${from} -> ${to}: ${amount}`);
});

// Query historical logs
const logs = await provider.getLogs({
address: contractAddress,
fromBlock: 0,
toBlock: 'latest',
topics: [ethers.id('Transfer(address,address,uint256)')],
});

Differences from Ethereum

FeatureEthereumRP1
Block Time12s200ms
Finality~15 minInstant
Gas TokenETHRP1
Chain ID11111
ConsensusPoSCometBFT

Next Steps