Skip to main content

Account Management

Patients and providers can register in the Registry Smart Contract by creating a Device and using that device to register. A single account can have more than one device.

DEVICE
Device 1
ETH Wallet + NaCl Keypair
0x1a2b...3c4d
SMART CONTRACT
EDHAccountRegistry
registerAccount()
Factory
WALLET CONTRACT
EDHAccount
Multi-owner Wallet — Address, PublicKey
onlyActiveDeviceEIP-1271ERC-2771
DEVICES
DeviceA
PublicKeyA
active
DeviceB
PublicKeyB
register
derive
SEED VAULT
SeedVault
Encrypted SEED per device
DeviceA seed: nacl.box(SEED, pubKeyA)
DeviceB seed: nacl.box(SEED, pubKeyB)
Account Registration Flow

Blockchain Network

EDH Smart Contracts can be deployed on any EVM-compatible blockchain, such as Polygon, Ethereum, Base, Arbitrum, or other networks that support Solidity.

ItemDetails
NetworkEVM-compatible (Polygon, Ethereum, Base, etc.)
Contract StandardSolidity ^0.8.0
Meta-TransactionERC-2771 via EverTrustedForwarder

EDHAccountRegistry

The Registry Contract is a Smart Contract for managing public key data on the blockchain. Its primary function is Account Registration, which registers the public keys of the account and its first device. Upon registration, an EDHAccount Smart Contract is created on the blockchain.

Interface: Account Registration

contract EDHAccountRegistry {
event EDHAccountRegistered(address indexed _account, address indexed _device);

function precomputeAccountAddress(
bytes32 salt,
address device,
bytes32 accountEncryptionPubKey
) public view returns (address);

function registerAccount(
bytes32 salt,
bytes32 accountEncryptionPubKey,
bytes32 deviceEncryptionPubKey,
bytes calldata boxedDeviceName
) public returns (address _address);

}

Event EDHAccountRegistered : An event emitted when an account is successfully registered.

precomputeAccountAddress : A view function that pre-computes the account address. Because transaction functions on the blockchain cannot return result values, this function exists to calculate the account address in advance. The computed address depends on a randomly generated salt, the device address, and the public key of the account being registered.

registerAccount : A transaction function that creates an EDHAccount as a smart contract and grants the device that created the account permission to manage it. If account creation succeeds, an EDHAccountRegistered event is emitted.

EDHAccount

EDHAccount is a smart contract that represents a user account in the EDH system. It functions similarly to a Multi-Owner Wallet Contract, allowing the Ethereum accounts of devices that own the account to manage the EDHAccount.

Being a Wallet Contract enables the EDHAccount to integrate well with the broader blockchain ecosystem in the future. For example:

  • It can serve as a destination account for receiving various assets such as NFTs and tokens.
  • It can verify signatures through the "EIP-1271: Standard Signature Validation Method for Contracts" standard.

The main responsibilities of EDHAccount are:

  • Device management
  • Storing the history of the account's encryption public keys
  • Verifying signatures signed by current devices
  • Storing shared constants accessible to all devices
  • Providing functions for the account to interact with other smart contracts

Interface: Account Operations

contract EDHAccount {
event EDHAccountCreated(bytes32 accountPublicKey);
event EDHDeviceRegistered(address indexed device, bytes32 devicePublicKey, address approverDevice);
event EDHDeviceRevoked(address indexed device, bytes32 devicePublicKey, address approverDevice);
event EDHAccountKeyUpdated(address indexed device, bytes32 newPublicKey, bytes32 prevPublicKey);

function encryptionPublicKey() public view returns (bytes32 key);
function encryptionPublicKeys() public view returns (bytes32[] memory keys);

function isValidSignature(
bytes32 _hash, bytes memory _signature
) public view returns (bytes4 magicValue);

function isRevokedSignature(
bytes32 _hash, bytes memory _signature
) public view returns (bool);

function updateEncryptionPublicKey(bytes32 key) public onlyActiveDevice;

function registerDevice(
bytes32 accountEncryptionPubKey,
address deviceAddress,
bytes32 deviceEncryptionPubKey,
bytes memory deviceName
) public onlyActiveDevice;

function revokeDevice(address deviceAddress) public onlyActiveDevice;

function isActiveDevice(address _address) public view returns (bool);
function isRevokedDevice(address _address) public view returns (bool);

uint constant public DEVICE_STATUS_UNLINKED = 0;
uint constant public DEVICE_STATUS_ACTIVE = 1;
uint constant public DEVICE_STATUS_REVOKED = 2;
function getDeviceStatus(address _address) public view returns (uint);
function getActiveDevice(address _address) public view returns (DeviceItemView memory device);
function getActiveDevices() public view returns (DeviceItemView[] memory devices);
function getRevokedDevice(address _address) public view returns (DeviceItemView memory device);

function execute(address target, bytes memory callData) public onlyActiveDevice returns (bytes memory);
function multicall(bytes[] memory data) public returns (bytes[] memory results);

}

event EDHAccountCreated : An event log emitted when this account is created.

event EDHDeviceRegistered/EDHDeviceRevoked : Events emitted when a new device is registered to this account or when an existing device is revoked.

event EDHAccountKeyUpdated : An event log emitted when the account's encryption public key is updated.

registerDevice : A transaction function that adds a device with permission to manage the account, making it an active device.

revokeDevice : A transaction function that revokes a device's permission to manage the account, making it a revoked device.

note

Adding or removing devices only affects the Ethereum wallet's permission to operate the EDHAccount. It does not affect the sharing of the account secret, which must be separately added to the SeedVault.

encryptionPublicKey/encryptionPublicKeys : View functions that return the current public key and the full history of all past public keys for the account.

updateEncryptionPublicKey : A function to update the account's latest public key.

isActiveDevice/isRevokedDevice : View functions to check the status of a device linked to the EDHAccount.

getActiveDevices/getRevokedDevice : View functions that return device information for devices linked to the account, such as their Ethereum address and encryption public key used for inter-device communication.

isValidSignature/isRevokedSignature : View functions used to verify whether a digital signature belongs to a device associated with the account.

execute/multicall : Transaction functions that allow a device to instruct the account to execute other transactions. This enables the smart contract account to call functions on other smart contracts in the system, with the account acting as a representative of the device.

Additionally, there are functions for storing and reading account constants, which are covered in the File Storage section.

BioAnchorRegistry

BioAnchorRegistry is a smart contract for registering Biological Identity Attestation (BIA) commitments on the blockchain. It uses Poseidon hashing to bind a did:bio Decentralized Identifier to the user's genomic identity.

Key features:

  • One anchor per address: Each Ethereum address can register only one genomic commitment.
  • Sybil resistance: Prevents a single person from creating multiple identities.
  • Assurance levels 0--3: Ranging from self-attested to multi-source lab verification.
  • Revocation: Can be revoked if data is compromised.

For details on the Solidity interface and gas costs, see BioAnchorRegistry.

Meta-Transaction (ERC-2771)

EDH Smart Contracts support ERC-2771 Meta-Transactions via EverTrustedForwarder, allowing users to interact without paying gas fees themselves.

How It Works

  1. The user signs a message digest according to the EIP-712 Typed Data standard using the device's private key.
  2. The application sends the signed message to Ever's Gas Payer Service.
  3. The Gas Payer Service submits the transaction through the EverTrustedForwarder contract.
  4. The Forwarder verifies the signature and forwards the call to the EDH contract, appending the real user's address.
  5. The EDH contract uses msg.sender from the forwarder context to verify permissions.

ByAdmin Functions

Functions called via meta-transaction include an additional signature parameter, which is an EIP-712 signed message digest containing:

  • The function call data to be executed
  • The account owner's address
  • A nonce to prevent replay attacks

For details about the Gas Payer Wallet, see Ever Services.

Account Recovery

If a user loses all their devices, the account can be recovered using a backup SEED.

Recovery Steps

  1. Create a new device: Generate a new Ethereum keypair and NaCl keypair on the new device.
  2. Import the backup SEED: Use the backed-up SEED (32 bytes) to derive the account's central keys.
  3. Register the new device: Call registerDevice on the EDHAccount contract (at least one active device is required).
  4. Update the SeedVault: Add the encrypted SEED for the new device to the SeedVault.
danger

If all active devices are lost and there is no backup SEED, account recovery is impossible. Users should always store their SEED in a safe place, such as written on paper and kept in a secure safe.

Emergency Guardian

Users can designate an Emergency Guardian, which is another EDH account authorized to help recover data access. If the account owner cannot access their data, the Emergency Guardian can approve the registration of a new device through a social recovery mechanism.

Estimated Gas Costs

Actual costs depend on the chosen network. Below are approximate gas estimates:

OperationGas (approx.)
registerAccount~200,000
registerDevice~100,000
revokeDevice~50,000
updateEncryptionPublicKey~45,000
execute~60,000+
setDataBytes~60,000

See Also