LogoLogo
  • Overview
    • Introduction
    • Table of Contents
  • Token Information
    • Symmio Foundation
  • Protocol Architecture
    • Protocol Introduction
    • Technical Documentation
      • Building an Application with SYMM
        • Introduction and Diamond Explainer
        • Querying Info from the SYMM Diamond
        • MultiAccount
        • Creating an Account and Depositing Funds
        • Sending a Quote
        • Closing a Quote
        • Instant Trading
          • Instant Login (EOA)
          • Instant Login (Account Abstraction)
          • Sending a Quote (Instant Open)
          • Sending a Quote (Instant Close)
        • Frequently Used Queries
      • Solver Docs
        • Solver Docs (github)
        • Solver Implementation Guide (High Level Overview)
        • Building a Solver on SYMMIO
          • 1. Intent Creation
          • 2. Seeing the Intent
          • 3. Hedging Off-Chain
          • 4. Opening/Closing a Position On-Chain
          • Creating the APIs
            • GET Contract Symbols
            • GET Open Interest
            • GET Notional Cap
            • GET Price Range
            • GET Error Codes
            • GET Get Locked Params
            • GET Get Funding Info
            • POST Position State
          • Solver Flow Summary Example
          • Recommended Architecture for Solvers
          • Glossary
        • Conditional Orders Handler
        • Rasa Solver TP/SL Implementation
        • Instant Trading
          • Instant Trading (Solvers)
          • Rasa Instant Trading Implementation
          • Instant Trading Condition Checks
        • Fetching Gas Prices Script
        • How to Add a Market as a Solver
        • Verifying Account Abstracted Instant Actions (ERC-4337)
      • Frontend Docs
        • Setting up a Frontend with SYMMIO
        • Frontend SDK Setup Guide
        • MultiAccount Deployment Guide
        • Instant Trading (Frontends)
          • Account Abstracted Instant Actions (Frontends)
        • Implement a Trading Bot on Symmio (OLD)
          • Setup
          • Creating a Sub-Account
          • Minting Collateral Tokens (Optional)
          • Depositing and Allocating Tokens
          • Obtaining Muon Signatures
          • Sending a Quote
          • Monitoring Price for Execution
      • Contract Docs
        • SYMMIO CORE v0.82
        • Contracts Documentation 0.8.2
          • Main Flow
          • The SYMM Diamond
          • Facets
            • Account Facet
            • Control Facet
            • Funding Rate Facet
            • PartyA Facet
            • PartyB Facet
            • Liquidation Facet
            • View Facet
          • MultiAccount
            • PartyA
            • PartyB
          • SYMM App (Muon)
            • LibMuon
            • MuonStorage
        • Contracts Documentation 0.8.3
          • Facets
            • Control Facet
            • Account Facet
            • PartyA Facet
            • PartyB Facet
            • View Facet
            • Bridge Facet
            • Liquidation Facet (Implementation)
          • Modified Events
          • New Events
          • MuonStorage
        • Contracts Documentation 0.8.4
          • Main Flow (0.8.4)
          • The SYMM Diamond (0.8.4)
          • Facets
            • Account Facet (0.8.4)
            • Bridge Facet (0.8.4)
            • Control Facet (0.8.4)
            • Force Actions Facet (0.8.4)
            • Funding Rate Facet (0.8.4)
            • Liquidations Facet (0.8.4)
            • PartyA Facet (0.8.4)
            • PartyB Group Actions Facet (0.8.4)
            • PartyB Quote Actions Facet (0.8.4)
            • PartyB Position Actions Facet (0.8.4)
            • Settlement Facet (0.8.4)
            • View Facet (0.8.4)
          • MultiAccount (0.8.4)
            • SymmioPartyA
            • SymmioPartyB
          • SYMM App (Muon)
            • LibMuon (0.8.4)
            • MuonStorage (0.8.4)
      • Contract Addresses / Solver Endpoints
        • Mantle
        • Mode
        • IOTA
        • Base
        • BSC
        • Arbitrum
        • Polygon
        • Berachain
        • Solver Endpoints and Addresses
          • Perps Hub
          • Rasa Capital
          • Rasa Capital (Zero Spread)
          • Zenith
      • How to Query our Contracts
      • Muon API Queries
      • Solver Error Codes
      • Interacting with SYMMIO Contracts
    • Protocol higher level architecture
      • 12-Hour Fraud Proof Window
      • PartyB
      • Solver Settings
      • Max Leverage
      • Maintenance Margin (CVA) Calculations
    • Symmio Whitepaper
  • Building on Symmio
    • Builders introduction
    • Solving for Symmio
      • Solver documentation
      • Solver - Example Flow
    • Trading Fees
      • Perps - Settlement Costs
      • Pair Trading - Settlement costs
    • Exchanges (Frontends)
      • Frontend Introduction
      • SDK - SYMM client
      • Trade on Symmio
  • Legal & Brand & Security
    • Security (Audits / Bugbounty)
      • Bug bounty / Coverage
        • How to contact ?
      • Audits
        • SYMM - V0.8 - 0.81
          • Sherlock Audit - Jun 15, 2023
          • Smart State - Jul 2, 2023
        • SYMM - 0.82
          • Sherlock Audit -Aug 30, 2023
        • SYMM - 0.83
          • Sherlock Audit - Jun 17, 2024
        • SYMM - 0.84
          • Sherlock Audit - Oct 3, 2024
        • Vaults
          • Sherlock Audit - Jan 2, 2024
    • Terms of Service & Licensing
      • TRADEMARK & COPYRIGHT NOTICE
      • CONTACT US
      • TERMS OF SERVICE
      • FRONTEND LICENSE
        • Frontend Modifications
        • Frontend Use Grants
      • CONTRACT LICENSE
        • Contract Use Grants
        • Contract Modifications
    • Brand - Assets Logos
Powered by GitBook
LogoLogo

All rights to the people (c) 2023 Symmetry Labs A.G.

On this page
  • Example Code Snippet
  • Constructing the SIWE Message
  • Encoding the Message for EIP-1271 Verification
  • On-Chain Signature Verification
  • Account Abstracted Flow– Verifying Instant Actions:
  1. Protocol Architecture
  2. Technical Documentation
  3. Solver Docs

Verifying Account Abstracted Instant Actions (ERC-4337)

When using Account Abstraction with ERC-4337, you may need to verify a user’s signature on-chain (EIP-1271). This process allows smart contract wallets to sign off-chain data (via the user’s wallet logic) and then be validated on-chain by calling a contract’s isValidSignature() function.

The example below uses:

  • SIWE (Sign-In with Ethereum) to structure the message (nonce, domain, expiration, etc.).

  • ERC-4337 style message hashing to produce the correct pre-hashed data.

EIP-1271 on-chain validation via a contract call to isValidSignature().

Example Code Snippet

import json

from eth_typing import HexStr
from eth_utils import keccak, to_bytes, to_hex
from siwe import SiweMessage
from siwe import siwe
from web3 import Web3

RPC = ''
web3 = Web3(Web3.HTTPProvider(RPC))


def _encode_erc4337(message: SiweMessage) -> HexStr:
    data_str = message.prepare_message()
    print(data_str)
    hex_message = data_str.encode('utf-8').hex()
    presign_message_prefix = f'\x19Ethereum Signed Message:\n{len(data_str)}'
    prefix = presign_message_prefix.encode('utf-8').hex()
    combined_message = f'0x{prefix}{hex_message}'
    return to_hex(keccak(to_bytes(hexstr=combined_message)))


message_dict = {
    "account_address": "0x94b1e92397bC7Bc0964e1d6C736277AF27E5a76a",
    "expiration_time": "2024-12-19T08:09:21.231Z",
    "issued_at": "2024-12-16T08:09:21.231Z",
    "signature": "0xf8582d00465b648c7d3f0f06d1ca41553af52bf70e1f21b115c7a18a0f548dd032000319a7947d17575ffba4a358a9e5be4f9302216a41e22ba1f4aa7f5108ac20",
    "nonce": "1ESHS1N2VcQ"
}

domain = "vibe-ui-git-hedger-whitelist-link-vibe-tradings-projects.vercel.app"
uri = "https://base-hedger82.rasa.capital/login"
signature = message_dict['signature']
owner = "0x3Da94BF626065EF31dab46529ea0A69761a01a1e"

fields = {
    "domain": domain,
    "address": owner,
    "uri": uri,
    "version": siwe.VersionEnum.one,
    "chain_id": "8453",
    "nonce": message_dict["nonce"],
    "issued_at": message_dict["issued_at"],
    "statement": f'msg: {message_dict["account_address"]}',
    "expiration_time": message_dict["expiration_time"]
}

siwe_message = SiweMessage(**fields)
hash_message = _encode_erc4337(siwe_message)

with open('SignerValidatorAbi.json') as f:
    abi = json.load(f)

contract = web3.eth.contract(address=owner, abi=abi)

try:
    magic_value = contract.functions.isValidSignature(hash_message, signature).call()
    print("Magic Value Returned:", magic_value.hex())
    print(magic_value == Web3.to_bytes(hexstr=HexStr('0x1626ba7e')))
except Exception as e:
    print("Error calling isValidSignature:", e)

Below is a breakdown of how this code example verifies Instant Trades in an AA context.

Constructing the SIWE Message

fields = {
    "domain": domain,
    "address": owner,
    "uri": uri,
    "version": siwe.VersionEnum.one,
    "chain_id": "8453",
    "nonce": message_dict["nonce"],
    "issued_at": message_dict["issued_at"],
    "statement": f'msg: {message_dict["account_address"]}',
    "expiration_time": message_dict["expiration_time"]
}
siwe_message = SiweMessage(**fields)
  • SIWE (Sign-In with Ethereum) is used to define an off-chain message containing:

    • domain: The site or application domain.

    • address: The user’s (or smart wallets) address—this is an EIP-1271 contract in this example.

    • nonce & issued_at: Used to prevent replay attacks.

    • expiration_time: Defines how long this signed authorization is valid.

    • statement: here account_address is the ERC-4337 compliant wallet

    • chain_id: The chain on which the address is deployed.

Encoding the Message for EIP-1271 Verification

def _encode_erc4337(message: SiweMessage) -> HexStr:
    data_str = message.prepare_message()
    print(data_str)
    hex_message = data_str.encode('utf-8').hex()
    presign_message_prefix = f'\x19Ethereum Signed Message:\n{len(data_str)}'
    prefix = presign_message_prefix.encode('utf-8').hex()
    combined_message = f'0x{prefix}{hex_message}'
    return to_hex(keccak(to_bytes(hexstr=combined_message)))
  1. message.prepare_message() gives you the SIWE message as a string.

  2. The code applies EIP-191 style prefix: \x19Ethereum Signed Message:\n<length>. This is the same prefix typically used in MetaMask or other wallets for “personal_sign.”

  3. The prefixed message is then hashed with keccak-256.

The resulting hash_message becomes the “message hash” that the smart contract will verify.

On-Chain Signature Verification

contract = web3.eth.contract(address=owner, abi=abi)
magic_value = contract.functions.isValidSignature(hash_message, signature).call()
print("Magic Value Returned:", magic_value.hex())
print(magic_value == Web3.to_bytes(hexstr=HexStr('0x1626ba7e')))
  1. owner is not an EOA– it’s an EIP-1271-compatible contract (smart wallet).

  2. isValidSignature(bytes32 _hash, bytes _signature) is part of EIP-1271. The contract checks internally if the provided signature is valid for _hash.

  3. A valid signature must return 0x1626ba7e (the EIP-1271 magic value).

  4. If the returned value is not 0x1626ba7e, the signature is invalid.

Account Abstracted Flow– Verifying Instant Actions:

  1. The frontend generates a SIWE message for "instant actions"

    • E.g., “I authorize solver XYZ to execute opens/closes until expiration_time.”

    • The user (or user’s wallet) signs it off-chain, producing a signature.

  2. The solver/backend calls _encode_erc4337(siwe_message) to construct the same SIWE string and get the hash_message.

  3. The solver then invokes isValidSignature(hash_message, signature) on the user’s smart wallet contract:

  • Success (0x1626ba7e) means the user’s contract acknowledges the signature, so the solver can proceed with “instant actions.”

  • Failure (any other value or revert) means the signature is invalid or expired.

This ensures no new signature is required for every single open/close, provided the user already authorized a “session.”

PreviousHow to Add a Market as a SolverNextFrontend Docs

Last updated 7 days ago