ERC-5289 Ethereum notarization interface (Ethereum Notary Interface)
Review · Signatures & auth · created 2022-07-16
A standard that lets a smart contract provide a link pointing to a legal document and record a user's signature history on-chain, adding legal binding force to the use of the contract.
Why it is needed
A smart contract executes as code, but that alone does not make it a legally binding contract. The original text uses NFTs as an example. NFTs are often known as a means of holding and proving copyright, but in reality this is rarely the case. Most NFTs have no legal meaning whatsoever, and even in the rare cases where they do, they only grant limited usage permission to the initial holder, without passing any permission on to subsequent holders. This standard aims to create direct contractual privity between a contract's users and a legal document, by having the contract provide an immutable link to the legal document and verify and record whether and when a user has signed that document. However, the original authors state that they are not lawyers and that this proposal is not legal advice.
What to implement
event DocumentSigned(address indexed signer, uint16 indexed documentId);: An event emitted when signDocument is called and a signature is made.function legalDocument(uint16 documentId) external view returns (string memory);: Returns an immutable link pointing to the legal document. IPFS hosting is recommended, and it must be a common file format such as PDF or HTML.function documentSigned(address user, uint16 documentId) external view returns (bool signed);: Returns whether the given user has signed that document.function documentSignedAt(address user, uint16 documentId) external view returns (uint64 timestamp);: Returns the time at which the given user signed that document. If they have not signed, the value may be anything.function signDocument(address signer, uint16 documentId) external;: Signs the document. The contract must verify the call and must either emit a DocumentSigned event or fail.
In depth
Legal document library interface
IERC5289Library inherits from ERC-165. legalDocument(uint16 documentId) returns an immutable link to the legal document; IPFS hosting is RECOMMENDED, and a common file format such as PDF, HTML, TeX, or Markdown MUST be used. documentSigned(address user, uint16 documentId) returns whether a signature exists, and documentSignedAt returns the signing time as a uint64. If the user has not signed, the timestamp returned by documentSignedAt may be any value, so documentSigned must be checked first to confirm whether a signature exists. signDocument(address signer, uint16 documentId) must be verified by the contract and must either emit a DocumentSigned event or fail (throw).
Requesting a signature via an ERC-5568 signal
To require a signature on a specific document, the contract reverts with an ERC-5568 signal. The signal's instruction_data is an ABI-encoded (address, uint16) pair, where address is the library address and uint16 is the document's documentId. The original text shows an example of the form throw WalletSignal24(0, 5289, abi.encode(library address, 12345)). In other words, the transaction is deliberately made to fail, and the failure data carries information to the wallet about which document needs to be signed.
Behavior required of the wallet
A wallet that receives a signature request MUST call legalDocument to fetch the document, display that document to the user, and then present a screen asking the user to sign or cancel. If the user agrees, the wallet MUST call signDocument. An implementation that processes the signature without displaying the document does not conform to the standard.
Rationale behind the types and design choices
uint64 was chosen as the return type for the signing time because a 64-bit time register is standard. uint16 was chosen for the document ID because 65,536 documents are likely sufficient for any use case; if not enough, the contract can simply be redeployed. The reason signDocument does not take an ECDSA signature as an argument is for future compatibility with account abstraction, and if needed, this functionality can be added by a later extension. IPFS was made mandatory because it can prove the authenticity of the signed document.
A proposal in Review stage, and not legal advice
The status of this proposal is Review, meaning it has not yet been finalized and its content may change. Also, the original authors explicitly state that they are not lawyers and that this proposal is not legal advice. It should be read with the understanding that actual legal effect may vary depending on the laws of each jurisdiction.
Things to watch out for
- The document must be permissive: A user could claim that their private key was stolen and that someone signed on their behalf without authorization. For this reason, the document being signed must be permissive in nature, granting rights, and must not be restrictive in nature, imposing obligations. For example, a document granting usage permission for an image attached to an NFT is fine, since the signer would have no reason to deny having signed it.