Evoq.Ethereum.EAS
3.2.1
dotnet add package Evoq.Ethereum.EAS --version 3.2.1
NuGet\Install-Package Evoq.Ethereum.EAS -Version 3.2.1
<PackageReference Include="Evoq.Ethereum.EAS" Version="3.2.1" />
<PackageVersion Include="Evoq.Ethereum.EAS" Version="3.2.1" />
<PackageReference Include="Evoq.Ethereum.EAS" />
paket add Evoq.Ethereum.EAS --version 3.2.1
#r "nuget: Evoq.Ethereum.EAS, 3.2.1"
#addin nuget:?package=Evoq.Ethereum.EAS&version=3.2.1
#tool nuget:?package=Evoq.Ethereum.EAS&version=3.2.1
Evoq.Ethereum.EAS
A lightweight .NET library providing an easy-to-use implementation of the Ethereum Attestation Service (EAS). This package builds upon Evoq.Blockchain and Evoq.Ethereum to provide a simplified interface for working with EAS.
Installation
# Using the .NET CLI
dotnet add package Evoq.Ethereum.EAS
# Using the Package Manager Console
Install-Package Evoq.Ethereum.EAS
# Or add directly to your .csproj file
<PackageReference Include="Evoq.Ethereum.EAS" Version="2.0.0" />
Features
- Simple interface for creating and managing attestations
- Type-safe EAS primitives
- Easy integration with existing Ethereum applications
- Built on top of Evoq.Blockchain and Evoq.Ethereum
- Support for revocable attestations
- Comprehensive attestation querying and validation
- Built-in timestamping support
- Schema registry integration
Target Frameworks
This package targets .NET Standard 2.1 for maximum compatibility across:
- .NET 6.0+
- .NET Framework 4.7.2+ (Note: .NET Framework 4.6.1 and earlier are not supported)
- .NET Core 2.1+ (Note: .NET Core 2.0 is not supported)
- Xamarin
- Unity
Dependencies
- Evoq.Blockchain (1.0.8)
- Evoq.Ethereum (2.1.0)
- System.Text.Json (8.0.5)
- SimpleBase (4.0.2)
Usage
Basic Setup
// Initialize EAS with the contract address
var eas = new EAS(easContractAddress);
// Create an interaction context (example using Hardhat testnet)
InteractionContext context = EthereumTestContext.CreateHardhatContext(out var logger);
// For production use, you'll need to set up your own context with proper configuration
var endpoint = new Endpoint(
networkName: ChainNames.Mainnet,
displayName: ChainNames.Mainnet,
url: "https://mainnet.infura.io/v3/YOUR-PROJECT-ID",
loggerFactory: loggerFactory
);
var chain = endpoint.CreateChain();
var getTransactionCount = () => chain.GetTransactionCountAsync(yourAddress, "latest");
var nonces = new InMemoryNonceStore(loggerFactory, getTransactionCount);
var account = new SenderAccount(privateKey, yourAddress);
var sender = new Sender(account, nonces);
var context = new InteractionContext(endpoint, sender, UseSuggestedGasOptions);
Understanding InteractionContext
The InteractionContext
is the core configuration object that manages your connection to the Ethereum network. It's composed of several key components:
- Endpoint: Manages the network connection and chain configuration
- Sender: Handles transaction signing and nonce management
- Gas Options: Configures how gas fees are calculated
Creating an InteractionContext
There are two main approaches:
- Using Test Context (for development)
// Creates a context connected to a local Hardhat node
// This handles all the setup internally using environment variables
InteractionContext context = EthereumTestContext.CreateHardhatContext(out var logger);
- Manual Configuration (for production)
// 1. Set up logging
var loggerFactory = LoggerFactory.Create(builder =>
builder.AddConsole().SetMinimumLevel(LogLevel.Information)
);
// 2. Create the endpoint
var endpoint = new Endpoint(
networkName: ChainNames.Mainnet,
displayName: ChainNames.Mainnet,
url: "your-rpc-url",
loggerFactory: loggerFactory
);
// 3. Create the chain
var chain = endpoint.CreateChain();
// 4. Set up nonce management
var getTransactionCount = () => chain.GetTransactionCountAsync(yourAddress, "latest");
var nonces = new InMemoryNonceStore(loggerFactory, getTransactionCount);
// 5. Configure the sender account
var account = new SenderAccount(privateKey, yourAddress);
var sender = new Sender(account, nonces);
// 6. Create the context with gas options
var context = new InteractionContext(endpoint, sender, UseSuggestedGasOptions);
// Helper function for gas options
static GasOptions UseSuggestedGasOptions(ITransactionFeeEstimate estimate)
{
return estimate.ToSuggestedGasOptions();
}
Available Chain Names
The library includes predefined chain names for common networks:
ChainNames.Mainnet // Ethereum Mainnet
ChainNames.Goerli // Goerli Testnet
ChainNames.Sepolia // Sepolia Testnet
ChainNames.Hardhat // Local Hardhat Network
Environment Variables for Testing
When using the test context, the following environment variables are required:
Blockchain__Ethereum__Addresses__Hardhat1PrivateKey=your-private-key
Blockchain__Ethereum__Addresses__Hardhat1Address=your-address
Creating Attestations
try
{
// Create a schema UID (example for a boolean schema)
var schemaUID = SchemaUID.FormatSchemaUID("bool isAHuman", EthereumAddress.Zero, true);
// Prepare attestation data
var data = new AttestationRequestData(
Recipient: recipientAddress,
ExpirationTime: DateTimeOffset.UtcNow.AddDays(1),
Revocable: true,
RefUID: Hex.Empty,
Data: Hex.Empty,
Value: EtherAmount.Zero
);
// Create the attestation request
var request = new AttestationRequest(schemaUID, data);
// Submit the attestation
var result = await eas.AttestAsync(context, request);
if (result.Success)
{
var attestationUID = result.Result;
Console.WriteLine($"Created attestation with UID: {attestationUID}");
// Retrieve the attestation
var attestation = await eas.GetAttestationAsync(context, attestationUID);
Console.WriteLine($"Retrieved attestation: {attestation}");
}
else
{
Console.WriteLine($"Failed to create attestation: {result.Error}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error creating attestation: {ex.Message}");
}
Advanced Features
Schema Registry Integration
// Initialize the schema registry
var schemaRegistry = new SchemaRegistry(schemaRegistryAddress);
// Register a new schema
var schema = "bool isAHuman";
var result = await schemaRegistry.Register(context, schema);
// Get an existing schema
var schemaRecord = await schemaRegistry.GetSchemaAsync(context, schema);
// Get schema version
var version = await schemaRegistry.GetVersionAsync(context);
Revocation
// On-chain revocation
var revocationRequest = new RevocationRequest(attestationUID);
await eas.RevokeAsync(context, revocationRequest);
// Record a timestamp for off-chain revocation data
// This is used to prove when a revocation was recorded
var revocationData = new Hex("your-revocation-data");
var timestamp = await eas.RevokeOffchainAsync(context, revocationData);
Timestamping
// Single timestamp
var timestamp = await eas.TimestampAsync(context, data);
// Get timestamp for data
var timestamp = await eas.GetTimestampAsync(context, data);
Attestation Validation
// Check if an attestation is valid
var isValid = await eas.IsAttestationValidAsync(context, attestationUID);
// Get attestation details
var attestation = await eas.GetAttestationAsync(context, attestationUID);
// Get schema registry address
var registryAddress = await eas.GetSchemaRegistryAsync(context);
Security Considerations
Private Key Management
- Never store private keys in source code or configuration files
- Use secure key management solutions
- Consider using hardware wallets for production environments
Network Security
- Use HTTPS for RPC endpoints
- Validate chain IDs before transactions
- Consider using multiple RPC providers for redundancy
API Keys
- Store API keys securely
- Use environment variables or secure secret management
- Rotate keys regularly
Testing
Prerequisites
- Install Hardhat for local Ethereum testing
- Clone the repository
- Run
npm install
in thecontracts
directory - Start Hardhat node:
npx hardhat node
Running Tests
# Run all tests
dotnet test
# Run specific test project
dotnet test tests/Evoq.Ethereum.EAS.Tests
# Run with logging
dotnet test --logger "console;verbosity=detailed"
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Luke Puplett
Project Links
Deploying EAS Contracts
For detailed instructions on deploying the Ethereum Attestation Service (EAS) contracts to a local Hardhat node, please refer to the Evoq.Ethereum README. The instructions include:
- Setting up the EAS contracts repository
- Installing dependencies with pnpm
- Creating and running the deployment script
- Verifying the deployment
The deployment process uses Hardhat Ignition for contract deployment and requires a local Hardhat node to be running.
Note: Many tests in this repository depend on having a local Hardhat node running and the EAS contracts deployed. Be sure to complete the deployment steps before running the test suite.
Address Change Warning: Each time you redeploy the EAS contracts to Hardhat, the contract addresses may change. This happens because Hardhat assigns new addresses if you reset the node, change the deployment order, or use a different mnemonic. If the addresses change, you must update the test code (or configuration) with the new deployed addresses, otherwise the tests will fail to find the contracts.
How Contract Addresses Are Determined:
Ethereum contract addresses are not based on the hash of the contract code. Instead, when a contract is deployed, its address is determined by the deployer's address and their transaction nonce at the time of deployment:
address = keccak256(rlp.encode([deployer_address, deployer_nonce]))[12:]
- If you redeploy, reset your node, or change the deployment order, the nonce changes, and so do the contract addresses.
- The contract code (bytecode) does not affect the address.
- This is why you may need to update the addresses in your test code after each deployment.
Hardhat Default Addresses:
When using the default Hardhat account (account #0) with a fresh node (all nonces = 0), the contract addresses are deterministic:
- SchemaRegistry (deployed first, nonce 0):
0x5FbDB2315678afecb367f032d93F642f64180aa3
- EAS (deployed second, nonce 1):
0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
These addresses are hardcoded in Contracts.cs
because they are predictable in this specific scenario. However, if you:
- Use a different deployer account
- Deploy in a different order
- Have any transactions before deployment
- Don't reset your node first
Then you'll get different addresses and will need to update your test code accordingly.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Evoq.Blockchain (>= 1.0.9 && < 2.0.0)
- Evoq.Ethereum (>= 3.1.0 && < 3.3.0)
- System.Text.Json (>= 8.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
3.2.1 | 196 | 6/17/2025 |
3.2.0 | 137 | 6/17/2025 |
3.1.0 | 221 | 5/15/2025 |
3.0.3 | 244 | 4/15/2025 |
3.0.2 | 187 | 4/10/2025 |
3.0.1 | 161 | 4/10/2025 |
3.0.0 | 158 | 4/9/2025 |
2.3.1 | 153 | 4/8/2025 |
2.3.0 | 153 | 4/8/2025 |
2.2.9 | 103 | 4/4/2025 |
2.2.8 | 124 | 4/4/2025 |
2.2.7 | 120 | 4/4/2025 |
2.2.6 | 131 | 4/4/2025 |
2.2.5 | 127 | 4/4/2025 |
2.2.4 | 159 | 4/3/2025 |
2.2.2 | 157 | 4/3/2025 |
2.2.1 | 158 | 4/3/2025 |
2.2.0 | 158 | 4/3/2025 |
2.1.8 | 159 | 4/2/2025 |
2.1.7 | 123 | 3/28/2025 |
2.1.6 | 119 | 3/28/2025 |
2.1.5 | 131 | 3/28/2025 |
2.1.4 | 128 | 3/28/2025 |
2.1.3 | 139 | 3/28/2025 |
2.1.2 | 133 | 3/27/2025 |
2.1.1 | 131 | 3/27/2025 |
2.1.0 | 139 | 3/27/2025 |
2.0.0 | 142 | 3/27/2025 |
2.0.0-alpha.3 | 111 | 3/26/2025 |
1.0.5-alpha.1 | 82 | 2/13/2025 |
1.0.4 | 119 | 2/13/2025 |
1.0.3 | 112 | 2/13/2025 |
1.0.2 | 105 | 2/12/2025 |
1.0.1 | 111 | 2/12/2025 |
1.0.0 | 109 | 2/12/2025 |