Consent

Overview

The Consent contract manages individual user consents linked to agreements in the Permission Protocol. It enables users (data suppliers) to create, revoke, and extend consent records through cryptographically signed actions.

Contract Details

Property
Value

Solidity Version

^0.8.28

License

MIT

Inheritance

EIP712 (OpenZeppelin)

Dependencies

IAgreement interface


Purpose

The Consent contract provides a complete lifecycle management system for user consents:

  • Create Consent: Users grant consent to an existing agreement

  • Revoke Consent: Users can revoke their consent (based on agreement's revocation rules)

  • Extend Validity: Users can extend the expiration of their consent

  • Batch Operations: Create multiple consent records in a single transaction

All operations require EIP-712 signatures from the data supplier, enabling gasless (meta-transaction) patterns.


Data Structures

ConsentRecord

The primary structure for storing consent details.

Field
Type
Description

agreementId

uint256

ID of the associated Agreement

agreement

IAgreement

Reference to the Agreement contract

createdAt

uint64

Timestamp when consent was created (for revoke checks)

supplier

address

Address of the data supplier

validityEnd

uint64

Expiration timestamp (0 = never expires)

nonce

uint16

Counter for replay protection on updates

disclosed

bool

If true, data is publicly accessible

dataRef

string

IPFS hash or URL pointing to the data

revocationRef

string

Revocation reason (empty if not revoked)

ConsentRecordInput

Input structure for batch consent record creation.


State Variables

Variable
Type
Visibility
Description

consentRecordCounter

uint256

public

Counter for unique consent IDs (starts at 1)

usedDigests

mapping(bytes32 => uint256)

public

Tracks used EIP-712 digests

consentRecords

mapping(uint256 => ConsentRecord)

public

Storage of consent records


Functions

Constructor

Initializes the contract with EIP-712 domain parameters.

Parameters:

Name
Type
Description

name

string

Domain name (e.g., "Consent")

version

string

Domain version (e.g., "1")


createConsentRecord

Creates a new consent record with supplier signature verification.

Parameters:

Name
Type
Description

agreementId

uint256

ID of the parent agreement

agreement

IAgreement

The Agreement contract reference

supplier

address

Address of the data supplier (signer)

validityEnd

uint64

Expiration timestamp (0 = never expires)

disclosed

bool

Public disclosure flag

dataRef

string

Reference to the data

r

bytes32

ECDSA signature component r

vs

bytes32

ECDSA compact signature component (v + s)

Returns:

Name
Type
Description

consentRecordId

uint256

The unique ID of the created consent

Requirements:

  • Referenced agreement must exist

  • Signature must be from the supplier

  • Consent with same parameters cannot already exist

Effects:

  • Sets createdAt to the current block timestamp

Emits: ConsentRecordCreated


batchCreateConsentRecords

Creates multiple consent records in a single transaction.

Parameters:

Name
Type
Description

inputs

ConsentRecordInput[]

Array of consent record inputs

Returns:

Name
Type
Description

consentRecordIds

uint256[]

Array of created consent record IDs

Requirements:

  • Input array must not be empty

Emits: ConsentRecordCreated for each consent record


revokeConsentRecord

Revokes an existing consent record.

Parameters:

Name
Type
Description

consentRecordId

uint256

ID of the consent to revoke

revocationRef

string

Reason or reference for revocation

nonce

uint16

Current nonce of the consent record

r

bytes32

ECDSA signature component r

vs

bytes32

ECDSA compact signature component

Requirements:

  • Agreement must allow revocation (agreement.isRevokable() returns true)

  • Nonce must match current consent record nonce

  • Signature must be from the original supplier

  • Revocation reference cannot be empty

  • Consent must not already be revoked

Emits: ConsentRecordRevoked

Effects:

  • Sets revocationRef to the provided value

  • Increments nonce by 1


extendValidity

Extends the validity period of a consent record.

Parameters:

Name
Type
Description

consentRecordId

uint256

ID of the consent to extend

newValidityEnd

uint64

New expiration timestamp

nonce

uint16

Current nonce of the consent record

r

bytes32

ECDSA signature component r

vs

bytes32

ECDSA compact signature component

Requirements:

  • Nonce must match current consent record nonce

  • New validity must be greater than current validity

  • Current validity cannot be 0 (consents with no expiry cannot be extended)

  • Consent must not be revoked

  • Signature must be from the original supplier

Emits: ConsentRecordValidityExtended

Effects:

  • Updates validityEnd to new value

  • Increments nonce by 1


getConsentRecord

Retrieves a consent record by ID.

Parameters:

Name
Type
Description

consentRecordId

uint256

The consent record identifier

Returns: ConsentRecord struct

Reverts: ConsentRecordNotFound if record doesn't exist


Hash Functions

hashConsentRecord

Computes the EIP-712 struct hash for consent record creation.

getTypedDataHash

Returns the complete EIP-712 typed data hash for signing.


Events

ConsentRecordCreated

Emitted when a new consent record is created. Includes the agreement contract reference and signature components for verification.

ConsentRecordRevoked

Emitted when a consent record is revoked.

ConsentRecordValidityExtended

Emitted when consent validity is extended.


Errors

Error
Description

ConsentRecordAlreadyExists(uint256)

A consent with the same parameters already exists

InvalidSignature()

The provided signature is invalid

InvalidRevocationRef()

The revocation reference is empty

InvalidNonce()

The provided nonce doesn't match

InvalidNewValidityEnd()

New validity is not greater than current

ConsentRecordNotFound()

The requested consent ID does not exist

EmptyBatchInput()

The batch input array is empty

ConsentRecordAlreadyRevoked()

The consent record has already been revoked

RevokeFailed()

Revocation not allowed by agreement's rules


EIP-712 Type Definitions

The contract uses multiple EIP-712 types for different operations:

ConsentRecord (for creation)

RevokeRecord (for revocation)

ExtendValidityRecord (for extension)


Usage Examples

Extending Validity

Checking if Revocation is Allowed


Note: Unlike previous versions, revocation is now permanent. Once a consent is revoked, it cannot be restored (undoRevocation has been removed).


Revocation Rules

The ability to revoke a consent record depends on the parent agreement's revokeEligibility setting:

RevokeEligibility
Can Revoke?

UnRevokable (0)

Never - revokeConsentRecord will always fail

InstantlyRevokable (1)

Always - can revoke immediately after creation

RevokableAfterGracePeriod (2)

Only after createdAt + revokeGracePeriodSeconds

The Consent contract calls agreement.isRevokable(agreementId, createdAt) to verify revocation eligibility before allowing the revoke operation.


Security Considerations

  1. Compact Signatures: Uses EIP-2098 compact signatures (r, vs) for gas efficiency

  2. Nonce Protection: Each modification increments the nonce, preventing replay attacks

  3. Supplier Authorization: Only the original supplier can modify their consent

  4. Agreement Validation: Consent can only be created for existing agreements (verified by calling getAgreementData)

  5. Revocation Control: Revocation eligibility is enforced by the parent Agreement contract

  6. Digest Tracking: Prevents duplicate consent records with identical parameters

  7. Flexible Agreement Reference: Each consent stores a reference to its Agreement contract, allowing consents to reference agreements from different Agreement contract deployments

  8. Timestamp Recording: createdAt is recorded for grace period calculations


  • Agreement: Parent contract that defines consent terms and revocation rules

  • IAgreement: Interface for Agreement contract

  • DIDRegistry: Identity management for suppliers


Deployment

The contract is deployed using Hardhat Ignition:

Last updated