EVVM Signature Structures Overview
All EVVM operations require EIP-191 cryptographic signatures for security. The platform uses centralized signature verification where Core.sol validates all operations using a unified signature format.
Universal Signature Format
{evvmId},{serviceAddress},{hashPayload},{executor},{nonce},{isAsyncExec}
Components:
{evvmId}: Network identifier (uint256, typically1){serviceAddress}: Address of the service contract being called{hashPayload}: Service-specific hash of operation parameters (bytes32){executor}: Authorized executor address (address,0x0...0for unrestricted){nonce}: User's centralized nonce from Core.sol (uint256){isAsyncExec}: Execution mode -truefor async,falsefor sync (boolean)
Two-Layer Signature Architecture
EVVM uses a two-layer hashing system for deterministic and gas-efficient signatures:
Layer 1: Hash Payload Generation
Each service uses a dedicated HashUtils library to generate hashPayload:
// Example: CoreHashUtils for payment operations
bytes32 hashPayload = CoreHashUtils.hashDataForPay(
receiver,
token,
amount,
priorityFee
);
Available HashUtils Libraries:
- CoreHashUtils: Payment operations (pay, batchPay, dispersePay)
- NameServiceHashUtils: Username operations (register, transfer, metadata)
- StakingHashUtils: Staking operations (stake, unstake, claim)
- P2PSwapHashUtils: Swap operations (makeOrder, dispatch, cancel)
- TreasuryCrossChainHashUtils: Cross-chain bridge operations
Layer 2: Signature Construction
The hashPayload is combined with execution context to create the final message:
// Signature message construction (simplified)
string memory message = string.concat(
uintToString(evvmId), // Network ID
",",
addressToString(serviceAddress), // Service contract
",",
bytes32ToString(hashPayload), // Service-specific hash
",",
addressToString(executor), // Authorized executor
",",
uintToString(nonce), // User's nonce
",",
isAsyncExec ? "true" : "false" // Execution mode
);
Layer 3: EIP-191 Wrapping
The message is signed using the EIP-191 standard (same as MetaMask):
bytes32 messageHash = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n",
uintToString(bytes(message).length),
message
)
);
Centralized Verification Process
All signatures are verified by Core.sol using validateAndConsumeNonce():
// Service calls Core.sol for verification
Core(coreAddress).validateAndConsumeNonce(
user, // Signer address
hashPayload, // Service-specific hash
executor, // Who can execute
nonce, // User's nonce
isAsyncExec, // Execution mode
signature // EIP-191 signature
);
What Core.sol Does:
- Verifies signature matches the signer (EIP-191 recovery)
- Validates nonce (checks status, consumes if valid)
- Checks executor authorization (if specified)
- Optionally delegates to UserValidator (if configured)
Example: Payment Signature
Scenario: Send 0.05 ETH to 0x742d...82d8c with sync execution
Step 1: Generate Hash Payload
bytes32 hashPayload = CoreHashUtils.hashDataForPay(
0x742d7b6b472c8f4bd58e6f9f6c82e8e6e7c82d8c, // receiver
0x0000000000000000000000000000000000000000, // token (ETH)
50000000000000000, // amount (0.05 ETH)
1000000000000000 // priorityFee (0.001 ETH)
);
// Result: 0xa7f3c2d8e9b4f1a6c5d8e7f9b2a3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1
Step 2: Construct Signature Message
1,0xCoreContractAddress,0xa7f3c2d8e9b4f1a6c5d8e7f9b2a3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1,0x0000000000000000000000000000000000000000,42,false
Components:
evvmId:1serviceAddress:0xCoreContractAddress(Core.sol)hashPayload:0xa7f3...(from Step 1)executor:0x0000...(unrestricted)nonce:42isAsyncExec:false(sync)
Step 3: Sign with Wallet User signs the message using MetaMask or another EIP-191 compatible wallet.
Parameter Formatting Rules
String Conversion
- Numbers:
"50000000000000000"(decimal string, no scientific notation) - Addresses:
"0x742c7b6b472c8f4bd58e6f9f6c82e8e6e7c82d8c"(lowercase hex with0x) - Bytes32:
"0xa7f3c2d8e9b4f1a6..."(64-character hex with0x) - Booleans:
"true"or"false"(lowercase) - Strings: As provided (e.g.,
"alice")
Formatting Utilities
Use AdvancedStrings library:
import {AdvancedStrings} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
AdvancedStrings.uintToString(42); // "42"
AdvancedStrings.addressToString(addr); // "0x742c..."
AdvancedStrings.bytes32ToString(hash); // "0xa7f3..."
EVVM Services Overview
Core.sol
Payment operations:
pay(): Single payment to addresses or usernamesbatchPay(): Multiple payments in one transactiondispersePay(): Split payment to multiple recipientscaPay(): Contract-only payments
NameService
Username management:
- Registration (pre-register → register flow)
- Marketplace (offers, transfers)
- Metadata (custom fields)
- Renewals and cleanup
Staking
Token staking:
- Presale and public staking
- Unstaking with time locks
- Reward distribution
Treasury
Cross-chain operations:
- Bridge transfers (Axelar, LayerZero)
- Multi-chain asset management
P2PSwap
Decentralized exchange:
- Order creation and cancellation
- Order dispatch (fills)
- Fee management
Best Practices
Security
- Never reuse nonces: Each signature must have a unique nonce
- Validate executor: Use
0x0...0for public operations, specific address for restricted - Async for time-sensitive: Use
isAsyncExec=truefor operations needing specific timing - Service address precision: Always use the correct deployed service address
Gas Optimization
- Batch operations: Use
batchPay()instead of multiplepay()calls - Sync when possible: Async execution costs more gas
- Reuse hash payloads: Cache
hashPayloadif making multiple signatures
Development
- Use HashUtils libraries: Don't manually construct hashes
- Test signature generation: Verify message format matches expected structure
- Handle nonce management: Track used nonces client-side
- Validate before signing: Check parameters before generating signature
Next Steps
Explore service-specific signature structures:
- Core Payment Signatures - Payment operation signatures
- NameService Signatures - Username and metadata operations
- Staking Signatures - Staking and reward operations
- Treasury Signatures - Cross-chain bridge operations
- P2PSwap Signatures - DEX order operations