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
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.
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
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
string
Domain name (e.g., "Consent")
version
string
Domain version (e.g., "1")
createConsentRecord
Creates a new consent record with supplier signature verification.
Parameters:
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:
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
createdAtto the current block timestamp
Emits: ConsentRecordCreated
batchCreateConsentRecords
Creates multiple consent records in a single transaction.
Parameters:
inputs
ConsentRecordInput[]
Array of consent record inputs
Returns:
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:
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
revocationRefto the provided valueIncrements
nonceby 1
extendValidity
Extends the validity period of a consent record.
Parameters:
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
validityEndto new valueIncrements
nonceby 1
getConsentRecord
Retrieves a consent record by ID.
Parameters:
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
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
Creating a Consent Record (TypeScript/Viem)
Batch Creating Consent Records
Revoking a Consent Record
Extending Validity
Checking Consent Status
Checking if Revocation is Allowed
Consent Lifecycle
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:
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
Compact Signatures: Uses EIP-2098 compact signatures (r, vs) for gas efficiency
Nonce Protection: Each modification increments the nonce, preventing replay attacks
Supplier Authorization: Only the original supplier can modify their consent
Agreement Validation: Consent can only be created for existing agreements (verified by calling
getAgreementData)Revocation Control: Revocation eligibility is enforced by the parent Agreement contract
Digest Tracking: Prevents duplicate consent records with identical parameters
Flexible Agreement Reference: Each consent stores a reference to its Agreement contract, allowing consents to reference agreements from different Agreement contract deployments
Timestamp Recording:
createdAtis recorded for grace period calculations
Related Contracts
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

