Skip to content

algorandfoundation/x-accounts

Repository files navigation

Liquid Accounts

EVM Account Abstraction on Algorand via ECDSA signature verification

Algo x EVM enables Ethereum wallets (MetaMask, etc.) to control Algorand accounts using an ECDSA signature verification LogicSig. Sign once with your Ethereum wallet to authorize transactions on Algorand—no seed phrases, no new wallets.

Important

DO NOT PERFORM PUBLIC BETA TESTING YET

The logic sig standard may still evolve, which would impact the ALGO x EVM derived addresses. If you onboard public beta testers, future changes would require you to support them in recovering funds from outdated derivations or migrate to the latest version.

Tools aiding migrations/recovery will not be in scope for this project while it is in alpha/unstable state.

Private testing is fine, so long as you are aware that future versions may derive different Algorand addresses, and you would need to recover your own funds with the corresponding version of this repo.

Overview

This monorepo contains:

  • Logic Sig - LogicSig that verifies ECDSA (secp256k1) signatures from EVM addresses
  • SDK - TypeScript SDK for integrating EVM wallet signing with Algorand
  • use-wallet - @txnlab/use-wallet with Algo x EVM / MetaMask support
  • use-wallet-ui - @txnlab/use-wallet-ui with Algo x EVM / MetaMask support
  • frontend - React demo application with MetaMask integration
  • rpc-server - Mock Ethereum JSON-RPC server (Cloudflare Worker) that lets MetaMask Mobile connect to Algorand as a custom network. Responds to standard RPC methods (eth_chainId, eth_blockNumber, net_version, eth_gasPrice, eth_getBlockByNumber) and serves real ALGO balances via eth_getBalance by deriving the Algo x EVM address and querying Algorand mainnet, converting from 6-decimal microAlgos to 18-decimal wei.

How It Works

  1. Derive Algorand Address: Each EVM address (20 bytes) maps deterministically to a unique Algorand LogicSig address
  2. Sign with EVM Wallet: MetaMask signs the transaction/group ID using EIP-712 typed structured data (eth_signTypedData_v4)
  3. Verify on Algorand: The LogicSig recovers the public key from the signature and verifies it matches the template owner
  4. Execute Transaction: If verification succeeds, the transaction is approved

Technical Details

The LogicSig contract:

  • Uses ecdsaPkRecover (secp256k1) to recover the signer's public key
  • Derives the Ethereum address from the recovered public key (last 20 bytes of keccak256)
  • Compares the recovered address against the template owner
  • Computes an EIP-712 digest over the transaction ID (single txn) or group ID (atomic groups), providing domain separation

Why EIP-712 Structured Signing

The LogicSig uses EIP-712 typed structured data rather than raw personal_sign for two reasons:

  • Domain separation: The EIP-712 domain (name, version) is embedded in the signed digest, preventing signatures from being replayed across different applications or protocols. Network-level replay protection is provided by the Algorand transaction's genesis hash, which is already part of the signed transaction ID/group ID.
  • Human-readable signing prompts: EVM wallets (MetaMask, etc.) display the structured fields to the user instead of an opaque hex blob, making it clear what is being authorized.

Quick Start

Prerequisites

The recommended way to install pnpm is via Corepack, which ships with Node.js:

corepack enable
corepack prepare pnpm@10.29.3 --activate

Alternative: standalone install

npm install -g pnpm@10.29.3

Installation

# Clone the repository
git clone https://github.com/algorandfoundation/x-accounts.git
cd x-accounts

# fetch the submodules
git submodule init
git submodule update

# Install dependencies
# Read the output carefully, you may need to approve build scripts.
pnpm i

# Start LocalNet
algokit localnet start

# Build all projects
algokit project run build

Running the Demo

# Start the frontend (from root directory)
cd projects/frontend
pnpm dev

Open http://localhost:5173 and connect MetaMask to see EVM-controlled Algorand accounts in action.

Note: The derived Algorand address must be funded before it can send transactions. New accounts need a minimum balance of 0.1 ALGO to exist on the network. You can fund the account from AlgoKit LocalNet dispenser or use the frontend to display the address and send funds to it.

Project Structure

x-accounts/
├── projects/
│   ├── evm-logicsig/    # Smart contract (Algorand TypeScript)
│   ├── evm-sdk/         # TypeScript SDK
│   ├── frontend/        # React demo application
│   ├── rpc-server/      # Mock Ethereum JSON-RPC (Cloudflare Worker)
│   ├── use-wallet/      # Enhanced @txnlab/use-wallet with Algo x EVM support
│   └── use-wallet-ui/   # Enhanced @txnlab/use-wallet-ui with Algo x EVM support

SDK Usage

Install the SDK:

npm install algo-x-evm-sdk
# or
pnpm add algo-x-evm-sdk

Basic usage:

import { AlgoXEvmSdk } from 'algo-x-evm-sdk'
import { AlgorandClient } from '@algorandfoundation/algokit-utils'

// Initialize
const algorand = AlgorandClient.fromEnvironment()
const sdk = new AlgoXEvmSdk({ algorand })

// Get Algorand address for an EVM address
const algoAddress = await sdk.getAddress({
  evmAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'
})

// Get a transaction signer (EIP-712 typed data signing)
const evmAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb2'
const { addr, signer } = await sdk.getSigner({
  evmAddress,
  signMessage: async ({ domain, types, primaryType, message }) => {
    const data = JSON.stringify({ domain, types, primaryType, message })
    return window.ethereum.request({
      method: 'eth_signTypedData_v4',
      params: [evmAddress, data]
    })
  }
})

// Use with algokit-utils
await algorand.send.payment({
  sender: addr,
  signer: signer,
  receiver: recipientAddress,
  amount: (1).algos()
})

use-wallet

The use-wallet fork introduces a base class for Algo x EVM accounts, as well as an implementation for Metamask. This should be a drop-in replacement for Algorand dApps.

use-wallet-ui & meta-wallet

Opinionated fork of use-wallet-ui adds "meta-wallet" functionality to dApps:

  • transaction transparency, see what you are signing before you sign
    • security context: runs in dApp; vulnerable in malicious or compromised dApps
  • Initiate transactions for managing assets, sending ALGO, etc
    • WIP
  • Onboarding guide for Algo x EVM connected accounts with 0 ALGO balance

Integration Effort:

  • Drop-in for transaction transparency
  • Minor integration needed for wallet management (integrate )

Possible future work:

  • Develop optional companion extension for dApp-independent txn verification
  • Integrated bridging to bootstrap account w/ USDC without leaving dApp

Development Workflow

Build

algokit project run build

This compiles:

  1. Logic sig to TEAL
  2. TypeScript SDK
  3. Use-wallet packages
  4. Use-wallet-ui package
  5. Frontend

Test

cd projects/evm-logicsig
algokit project run test

Contributing

Contributions are welcome! Please see individual project READMEs for specific development guidelines:

Security Considerations

  • The LogicSig verifies signatures using ECDSA secp256k1 curve
  • A template variable (owner address) ensures each EVM address has a unique Algorand address
  • Signatures are automatically normalized to lower-S form because the AVM only accepts lower-S signatures
  • EIP-712 domain separation prevents AVM<>EVM contamination
  • The contract binds signatures to specific transaction/group IDs, preventing replay across AVM networks (genesisHash) & time (first/lastRound)
  • Always verify the derived Algorand address matches expectations

CI/CD

This project uses GitHub Actions for continuous integration and deployment. Workflows are located in .github/workflows.

On main branch pushes:

  • Automated testing and linting
  • Smart contract deployment to TestNet via AlgoNode

Resources

License

MIT

About

EVM Account Abstraction on Algorand via ECDSA signature verification

Resources

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors