EVVM Library Overview
The EVVM library ecosystem provides reusable components and utility contracts designed to simplify EVVM service development. These libraries handle common operations like signature verification, nonce management, string conversions, and service staking.
All libraries are imported from @evvm/testnet-contracts/library/ followed by the specific library path.
Library Architecture
Core Service Contract
- EvvmService: Base contract providing complete EVVM service functionality with built-in helpers for payments, signatures, nonces, and staking
Primitive Libraries
- Math: Standard mathematical operations with overflow protection (OpenZeppelin-based)
- SignatureRecover: EIP-191 signature recovery and verification primitives
Utility Libraries
- AdvancedStrings: Type conversion utilities (uint/address/bytes to string)
- SignatureUtil: High-level signature verification for EVVM messages
Service Utilities
- AsyncNonceService: Async nonce tracking and validation
- SyncNonceService: Sequential nonce management
- MakeServicePaymentOnEvvm: Payment processing helpers
- StakingServiceUtils: Service staking integration utilities
Quick Start
Using EvvmService (Recommended)
The EvvmService abstract contract is the recommended way to build EVVM services. It combines all essential utilities:
import {EvvmService} from "@evvm/testnet-contracts/library/EvvmService.sol";
contract MyService is EvvmService {
constructor(
address evvmAddress,
address stakingAddress
) EvvmService(evvmAddress, stakingAddress) {}
function myFunction(
address user,
string memory data,
uint256 nonce,
bytes memory signature,
uint256 priorityFee,
uint256 evvmNonce,
bool useAsync,
bytes memory paymentSig
) external {
// Validate signature
validateServiceSignature("myFunction", data, signature, user);
// Check nonce
verifyAsyncServiceNonce(user, nonce);
// Process payment
requestPay(user, getEtherAddress(), 1 ether, priorityFee, evvmNonce, useAsync, paymentSig);
// Mark nonce as used
markAsyncServiceNonceAsUsed(user, nonce);
}
}
Using Individual Utilities
For more granular control, use individual libraries:
import {SignatureUtil} from "@evvm/testnet-contracts/library/utils/SignatureUtil.sol";
import {AdvancedStrings} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
import {AsyncNonceService} from "@evvm/testnet-contracts/library/utils/service/AsyncNonceService.sol";
contract MyCustomService is AsyncNonceService {
function verifyUser(address user, bytes memory sig) internal view {
bool valid = SignatureUtil.verifySignature(
evvmId,
"myFunction",
AdvancedStrings.uintToString(someValue),
sig,
user
);
require(valid, "Invalid signature");
}
}
Library Categories
1. Service Development (EvvmService)
Complete all-in-one solution for building EVVM services with:
- Signature validation
- Payment processing
- Nonce management
- Service staking
- EVVM/Staking integration
Best for: New services, quick prototyping, standard use cases
2. Primitive Operations
Low-level utilities for fundamental operations:
- Signature recovery (EIP-191)
- Mathematical operations
- Type conversions
Best for: Building custom validation logic, advanced cryptographic operations
3. Service Utilities
Modular helpers for specific service functionalities:
- Nonce tracking (async/sync)
- Payment processing
- Staking integration
Best for: Custom service architectures, mixing and matching functionality
Design Patterns
Pattern 1: Full EvvmService Integration
contract Service is EvvmService {
// Inherit all functionality - fastest development
}
Pattern 2: Modular Composition
contract Service is AsyncNonceService, MakeServicePaymentOnEvvm {
// Mix utilities as needed - granular control
}
Pattern 3: Library-Only Usage
import {SignatureUtil} from "@evvm/testnet-contracts/library/utils/SignatureUtil.sol";
import {AdvancedStrings} from "@evvm/testnet-contracts/library/utils/AdvancedStrings.sol";
contract Service {
using SignatureUtil for bytes;
using AdvancedStrings for uint256;
// Pure library usage - maximum flexibility
}
Common Use Cases
Standard EVVM Service
Use EvvmService for complete service functionality:
contract CoffeeShop is EvvmService {
function orderCoffee(...) external {
validateServiceSignature(...);
verifyAsyncServiceNonce(...);
requestPay(...);
markAsyncServiceNonceAsUsed(...);
}
}
Read-Only Service
Use SignatureUtil for signature verification:
import {SignatureUtil} from "@evvm/testnet-contracts/library/utils/SignatureUtil.sol";
contract Validator {
function isValidSignature(bytes memory sig, address user) public pure returns (bool) {
return SignatureUtil.verifySignature(evvmId, "action", params, sig, user);
}
}
Custom Nonce Strategy
Inherit both nonce services:
import {AsyncNonceService} from "@evvm/testnet-contracts/library/utils/service/AsyncNonceService.sol";
import {SyncNonceService} from "@evvm/testnet-contracts/library/utils/service/SyncNonceService.sol";
contract HybridService is AsyncNonceService, SyncNonceService {
function actionWithSyncNonce(...) external {
uint256 expectedNonce = getNextSyncServiceNonce(user);
require(nonce == expectedNonce, "Invalid nonce");
_incrementSyncServiceNonce(user);
}
function actionWithAsyncNonce(...) external {
verifyAsyncServiceNonce(user, nonce);
markAsyncServiceNonceAsUsed(user, nonce);
}
}
Installation
# Clone repository
git clone https://github.com/EVVM-org/Testnet-Contracts.git
# Install via Forge
forge install EVVM-org/Testnet-Contracts
Foundry Configuration (foundry.toml):
remappings = [
"@evvm/testnet-contracts/=lib/Testnet-Contracts/src/"
]
Next Steps
Explore individual library documentation:
- EvvmService - Complete service development framework
- Primitives - Low-level mathematical and cryptographic operations
- Utils - String conversions and signature verification
- Service Utilities - Modular service components
Recommendation: Start with EvvmService for fastest development, then explore individual utilities as you need more customization.