관련 자료 : https://eips.ethereum.org/EIPS/eip-712
Struct 구조체에 대해서 서명값을 구하기 위해서는 별도의 방법을 이용해서 구해야 합니다.
여기에 관련된 표준으로 EIP-712(721 아님!)가 있는데요.
간단히 알아봅니다.
Struct Hash 값 구하는 방법
- 아래와 같은 구조체가 있다고 가정해봅니다.(Mail)
struct Mail {
address from;
address to;
string contents;
}
- 이 구조체에 대한 TypeHash 를 먼저 구해야 합니다.(아래와 같이 하면 구할 수 있음)
- 단, enum으로 선언된 변수의 경우 uint8을 사용해야 함
// 아래 함수 실행하면 결과값은:536e54c54e6699204b424f41f6dea846ee38ac369afec3e7c141d2c92c65e67f
bytes32 constant MAIL_TYPEHASH = keccak256(
"Mail(address from,address to,string contents)");
- 위와 같이 TypeHash를 구한 다음에 실제 구조체를 Hashing 하는 방법은 아래와 같습니다.
- abi.encode를 이용하여 인코딩을 하고 첫번째 변수에 위에서 구한 TypeHash 값을 입력합니다.
- address처럼 byte 수가 고정된 경우는 그냥 변수를 넘겨줘도 되지만, string이나 bytes 같은 경우에는 길이가 동적이기 때문에 keccak256으로 묶어서 변수에 입력해야 합니다.
function hashStruct(Mail memory mail) pure returns (bytes32 hash) {
return keccak256(abi.encode(
MAIL_TYPEHASH,
mail.from,
mail.to,
keccak256(mail.contents)
));
}
- 위 값을 이용해서 특정 address가 서명을 했다는 것을 증명해보자..!!
function validateSig(
Mail memory mail,
Sig memory sig
) internal pure {
bytes32 mailHash = hashStruct(mail);
// Hash 값과 rsv 값을 이용하여 서명한 Address와 동일한지 확인해서 검증을 할 수 있음
// ecrecover 내부에 sig 값은 v>s>r 순서대로 입력을 해야함.
require(ecrecover(mailHash, sig.v, sig.r, sig.s) == mail.from);
}