EIP: 6888
Title: Address Linkage with Single Nonce
Author: sunrize.eth, hiddenintheworld.eth
Status: Draft
Type: Standards Track
Category: ERC
Created: [2023-04-16]
Simple Summary
This EIP proposes a standard for linking Ethereum addresses using a simple smart contract that maps public addresses. The contract uses signed messages and a single nonce value to establish and revoke linkages between two addresses. This standard can be utilized for notification and wallet control modules, and it is fully on-chain.
Abstract
This standard proposes the use of a “Linkage” contract that allows an Ethereum address (owner) to link to another address (servant) using signed messages and a single nonce value. The linkage can be created or revoked using the owner’s or the servant’s signed message, which increases the nonce value for the servant’s address.
This standard can be utilized for fully on-chain notification and wallet control modules that require a secure and reliable solution. The use of signed messages and a single nonce value ensures that all transactions are recorded on the blockchain and cannot be manipulated or tampered with off-chain.
Specification
Definitions
ownerOf
: A mapping of address to address, representing the linkage between a servant address and its owner address.
nonces
: A mapping of address to uint256, representing the nonce value for each servant address.
Smart contract implementation
Here is the full code:
pragma solidity ^0.8.0;
contract Linkage {
mapping(address => address) public ownerOf;
mapping(address => uint256) public nonces;
function createLinkage(address servant, address owner, bytes memory signatureServant, bytes memory signatureOwner) public {
require(ownerOf[servant] == address(0), "Linkage already exists for servant");
bytes32 messageServant = keccak256(abi.encodePacked(owner, uint256(1), nonces[servant]));
bytes32 messageOwner = keccak256(abi.encodePacked(servant, uint256(0)));
require(recoverSigner(messageServant, signatureServant) == servant, "Invalid signatureServant");
require(recoverSigner(messageOwner, signatureOwner) == owner, "Invalid signatureOwner");
ownerOf[servant] = owner;
nonces[servant]++;
}
function revokeLinkage(address servant, address owner, bytes memory signature) public {
require(ownerOf[servant] == owner, "Linkage does not exist or is already revoked");
bytes32 messageServant = keccak256(abi.encodePacked(owner, uint256(3), nonces[servant]));
bytes32 messageOwner = keccak256(abi.encodePacked(servant, uint256(2)));
address signer = recoverSigner(messageServant, signature);
if (signer != servant) {
signer = recoverSigner(messageOwner, signature);
require(signer == owner, "Invalid signature");
}
ownerOf[servant] = address(0);
nonces[servant]++;
}
function recoverSigner(bytes32 _hash, bytes memory _signature) internal pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
if (_signature.length != 65) {
return (address(0));
}
assembly {
r := mload(add(_signature, 32))
s := mload(add(_signature, 64))
v := byte(0, mload(add(_signature, 96)))
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return (address(0));
} else {
return ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), v, r, s);
}
}
}
Methods
createLinkage(address servant, address owner, bytes memory signatureServant, bytes memory signatureOwner)
This function creates a linkage between the servant and owner addresses. The linkage is established only when the provided signatures of both parties are valid. The function increases the nonce value for the servant address.
revokeLinkage(address servant, address owner, bytes memory signature)
This function revokes the linkage between the servant and owner addresses. The function requires a valid signature from either the servant or the owner. The function increases the nonce value for the servant address.
recoverSigner(bytes32 _hash, bytes memory _signature) internal pure returns (address)
This internal function recovers the signer’s address from a given message hash and its corresponding signature.
Rationale
This standard was created to address the issue of open-source wallets like Metamask, which do not allow the use of private keys for encryption and decryption. By creating a simple smart contract that maps public addresses, users can link their addresses and utilize the contract for notification and wallet control modules. The use of signed messages and a single nonce value ensures security against replay attacks.
Backwards Compatibility
The proposed contract is not directly compatible with existing Ethereum token standards such as ERC20, ERC721, and ERC1155. However, it can be utilized alongside them or integrated into a new token standard with additional functionalities.
Security Considerations
The security of this standard relies on the uniqueness of the signed messages. Each signed message must include the source and target addresses to prevent replay attacks. The nonce for the servant address ensures that once a linkage is created or revoked, the same transaction cannot be used again.
Copyright
Copyright and related rights waived via CC0.
(NOTE: The EIP number and creation date will be provided when you submit the EIP to the Ethereum Improvement Proposals repository.)