Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.remlo.xyz/llms.txt

Use this file to discover all available pages before exploring further.

EmployeeRegistry records the relationship between employee wallets and their employers, plus the TIP-403 compliance policy each employer has in force. It’s the identity layer the rest of the protocol reads.

What it stores

struct Employee {
    address wallet;
    bytes32 employerId;
    uint256 policyId;
    bytes32 employeeIdHash;
    bool active;
}

mapping(address => Employee) public employees;
mapping(bytes32 => address[]) public employerWallets;
mapping(bytes32 => address) public walletByEmployeeKey;  // C-6 fix: O(1) reverse lookup
Each registered employee has a wallet, an employer they belong to, an optional policy ID for compliance bindings, and an active flag. Two way lookups are O(1): given a wallet you find the employer, given an (employerId, employeeIdHash) pair you find the wallet (audit fix C-6). employeeIdHash is a keccak256 commitment to the off-chain employee record (Supabase row ID + a per employer salt). It binds the on-chain wallet to a specific HR entity without leaking the underlying record.

Key functions

configureEmployer(employerId, policyId, admin). Owner only. Sets up an employer config with an admin wallet (the only address allowed to register employees for this employer) and an optional TIP-403 policy ID. registerEmployee(wallet, employerId, employeeIdHash). Only callable by the employer’s configured admin. Checks the wallet against the bound TIP-403 policy if set. Reverts with WalletAlreadyRegistered if the wallet is already active for any employer. deactivateEmployee(wallet). The employer admin or contract owner can soft delete. Clears the reverse mapping so a fresh registration of the same (employerId, employeeIdHash) to a new wallet resolves cleanly (e.g., when an employee rotates wallets). isEmployedBy(wallet, employerId). View. Returns true iff the wallet is active and bound to that employer. Used by PayrollBatcher for the optional H-4 batch validation path. getWallet(employerId, employeeIdHash). View. Returns the wallet for that pair, or address(0) if unregistered.

TIP-403 policy binding

If EmployerConfig.policyId > 0, every registerEmployee call queries tip403Registry.isAuthorized(policyId, wallet) and reverts with ComplianceCheckFailed if the wallet is not authorized under that policy. The TIP-403 registry address is set immutably at deployment (audit fix M-2). A malicious owner can’t swap in a permissive registry post-deployment. For employers that don’t use TIP-403 (most demo flows), policyId defaults to 0 and the check is skipped.

Why on-chain identity

An off-chain employer to employee mapping is opaque to other contracts. With on-chain identity:
  • PayrollBatcher can verify recipients before paying them.
  • Third party agents can confirm a wallet really belongs to a particular employer before extending credit.
  • Reputation writes target the right counterparty without trusting Remlo’s database.
The registry is also the substrate for compliance reporting. A regulator querying “show me every employee paid by employer X in March” gets a deterministic answer by combining the registry with PayrollBatcher event logs. No off-chain database snapshot required.

Live deployment

Tempo Moderato (chainId 42431):
0x2B8fC6eACBd89a7B01bB400cDd492ff0CE931a7e
View on explorer.