Skip to content
Lattice

SingleSignerValidation

Git Source

Inherits: IERC6900ValidationModule

Title: SingleSignerValidation

Authors: David Dada <daveproxy80@gmail.com> (https://github.com/dadadave80), Modified from ERC-6900 reference implementation (https://github.com/erc6900/reference-implementation)

A reference ERC-6900 validation module: one signer per (account, entityId). Validates user operations (ECDSA over the EIP-191 user-op-hash), runtime calls (the caller must be the signer), and ERC-1271 signatures (against the digest the account hands it).

A standalone module — invoked by the account via CALL, so it runs in its OWN storage (msg.sender is the account; signerOf[account][entityId] is per-account). For ERC-1271, the Lattice account has ALREADY bound the digest to its domain via ERC-7739 before calling validateSignature, so this module does a plain signer check (no extra rehashing). Reference quality: minimal, no upgradeability, no enumeration.

Constants

_1271_MAGIC

ERC-1271 return values.

bytes4 internal constant _1271_MAGIC = 0x1626ba7e;

_1271_INVALID

bytes4 internal constant _1271_INVALID = 0xffffffff;

_SIG_OK

ERC-4337 authorizer field: success = 0, signature failure = 1.

uint256 internal constant _SIG_OK = 0;

_SIG_FAIL

uint256 internal constant _SIG_FAIL = 1;

State Variables

signerOf

The signer authorized for (account, entityId).

mapping(address account => mapping(uint32 entityId => address signer)) public signerOf;

Functions

onInstall

data = abi.encode(uint32 entityId, address signer).

function onInstall(bytes calldata data) external;

Parameters

NameTypeDescription
databytes

onUninstall

data = abi.encode(uint32 entityId).

function onUninstall(bytes calldata data) external;

Parameters

NameTypeDescription
databytes

validateUserOp

function validateUserOp(uint32 entityId, PackedUserOperation calldata userOp, bytes32 userOpHash)
        external
        view
        returns (uint256);

Parameters

NameTypeDescription
entityIduint32
userOpPackedUserOperation
userOpHashbytes32

Returns

NameTypeDescription
<none>uint256Packed validation data: validAfter (6 bytes) ‖ validUntil (6 bytes) ‖ authorizer (20 bytes).

validateRuntime

MUST revert to reject the call.

function validateRuntime(address account, uint32 entityId, address sender, uint256, bytes calldata, bytes calldata)
        external
        view;

Parameters

NameTypeDescription
accountaddress
entityIduint32
senderaddress
_uint256
_bytes
_bytes

validateSignature

function validateSignature(address account, uint32 entityId, address, bytes32 hash, bytes calldata signature)
        external
        view
        returns (bytes4);

Parameters

NameTypeDescription
accountaddress
entityIduint32
_address
hashbytes32
signaturebytes

Returns

NameTypeDescription
<none>bytes4ERC-1271 magic value 0x1626ba7e if valid, or 0xffffffff if invalid.

moduleId

Unique id in the format "vendor.module.semver"; vendor/module names MUST NOT contain a period.

function moduleId() external pure returns (string memory);

Returns

NameTypeDescription
<none>string

supportsInterface

function supportsInterface(bytes4 interfaceId) external pure returns (bool);

Parameters

NameTypeDescription
interfaceIdbytes4

Returns

NameTypeDescription
<none>bool

Events

SignerSet

event SignerSet(address indexed account, uint32 indexed entityId, address signer);

Parameters

NameTypeDescription
accountaddress
entityIduint32
signeraddress

Errors

NotAuthorized

The runtime caller is not the configured signer.

error NotAuthorized(address account, uint32 entityId, address sender);

Parameters

NameTypeDescription
accountaddress
entityIduint32
senderaddress