EIP-712
개념
기존에는 왼쪽처럼 유저가 서명할 때 byte 문자열만 볼 수 있었다.
오른쪽은 EIP-712 서명으로 구조화된 데이터를 통해 사용자가 무엇을 서명하는지 알아 볼 수 있다.


EIP-712의 데이터는 domain 정보 영역와 서명 정보 영역 2가지로 나뉜다.
domain 정보를 담는 구조체는 Eip721Domain으로
name, version, chainId, verifyingContract, salt와 같은 필드로 구성된다.
해당 구조체는 hashStruct 함수를 통해 domainSeperator라는 해시값으로 사용된다.
domainSeparator = hashStruct(eip712Domain)
서명 정보는 사용자가 구조체를 정의해서 사용할 수 있고
마찬가지로 hashStruct 함수를 통해 해시값을 구할 수 있다.
2가지의 해시값을 통해 최종 해시값을 구할 수 있고
사용자는 이를 개인키로 서명해서 전송하게 된다.
keccak256("\x19\x01" ‖ domainSeparator ‖ hashStruct(message))
OpenZeppelin Contract
EIP-712
아래는 domainSeperator를 구하는 로직이다.
생성자에서 Eip721Domain의 필드로 사용되는 값들을 초기화해주고
_buildDomainSeperator 함수에서 구조체 정보를 사용해서 domainSeperator를 구하고 있다.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
ECDSA
최종 해시값을 구하는 부분이다.
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}'분석 > 블록체인' 카테고리의 다른 글
| [Ethereum] Multisig에 대해 알아보자 (0) | 2025.10.08 |
|---|---|
| [Ethereum] ERC-721A에 대해 알아보자 (0) | 2025.10.06 |
| [Ethereum] ERC-1155에 대해 알아보자 (0) | 2025.10.01 |
| [Ethereum] ERC-721에 대해 알아보자 (0) | 2025.10.01 |
| [XRPL] XRPL에 대해 알아보자 (0) | 2025.09.24 |