일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- SBT표준
- rust 기초
- ethers v6
- 컨트렉트 동일한 함수이름 호출
- erc4337 contract
- 스마트컨트렉트 예약어 함수이름 중복
- erc4337
- 스마트컨트렉트 함수이름 중복 호출
- 스마트컨트렉트테스트
- 머신러닝기초
- git rebase
- ethers websocket
- chainlink 설명
- ethers type
- vue기초
- 러스트 기초 학습
- 스마트 컨트렉트 함수이름 중복
- 체인의정석
- ambiguous function description
- 오블완
- 계정추상화
- 컨트렉트 배포 자동화
- multicall
- 러스트 기초
- Vue.js
- 러스트기초
- ethers
- ethers typescript
- 티스토리챌린지
- Vue
- Today
- Total
체인의정석
Solidity 0.8.0 버전에서 HashStruct안에 UUID 넣는 법 본문
일단 해당 게시글은 hashStruct안에 UUID를 넣고 싶은 상황에서 오류가 나서 해결하기 위해 고민한 결과를 담고 있다.
먼저 테스트를 위해서 UUID를 만들어야 했다.
그 부분은
https://it-timehacker.tistory.com/317?category=1006911
여기를 보면 알 수 있다.
그 다음 차례는 string 자료형을 추가하는 것이였는데 에러가 났다.
원인을 찾을 수 가 없어 UUID가 아닌 자료 형을 넣어보기도 하고 uint256형을 추가하기도 했는데 string 형태가 나오면 오류가 나는 것을 확인할 수 있었다.
결국 다시 원문으로 돌아와서 고민을 하였다.
https://issuecloser.com/blog/ethersjs-signing-eip712-typed-structs
이런식으로 구조체를 만들고 안에다가 문자열이 있으면 잘 되었는데 자세히 보면 해당 구조체는 해시스트럭트를 만들때 구조체 자체를 해시한것을 볼 수 있었다.
그리고 결정적인 단서는 EIP712 문서를 보고 알았다.
https://eips.ethereum.org/EIPS/eip-712
보면 분명 string 형으로 된 name같은 자료형이 지원되는것을 볼 수 있었는데
여기에 나온 해시스트럭트 예시가 힌트가 되었다.
function hashStruct(Mail memory mail) pure returns (bytes32 hash) {
return keccak256(abi.encode(
MAIL_TYPEHASH,
mail.from,
mail.to,
keccak256(mail.contents)
));
}
여기서 mail 의 contents는 string 자료형이다. 결국 hashStruct를 만드는 규칙에서 uint256이나 address는 그냥 넣으면 되지만 string의 경우 keccack256을 한번 해주어서 bytes32로 바꾸어 주어야 한다는 것을 알 수 있었다.
struct도 마찬가지로 keccack을 해주어야 한다.
하지만 또 이대로 하면 에러가 발생한다.
TypeError: Invalid type for argument in function call. Invalid implicit conversion from string memory to bytes memory requested. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding.
이러한 에러가 발생하는 이유는 EIP712 공식문서가 오래되었고 문법이 바뀌었기 때문인데 경고문에 뜬것과 같이 abi.encodePacked를 먼저 한 후에 keccack256을 하면 문자형을 해시스트럭트에 넣을 수 있다.
function hashStruct(StructA memory structA)
public
view
returns (bytes32)
{
return
keccak256(
abi.encode(
TYPEHASH,
.
.
.
,
keccak256(abi.encodePacked(UUID))
)
);
}
그리고 테스트를 돌려본 결과 잘 통과하였다.
UUID를 넣어서 해시 스트렉트에서 관리하니 데이터베이스와 연결하기는 좋아진거 같다.
다만, 내가 사용하는 체인은 이더리움이 아닌 evm 계열 체인이기 때문에 이런식으로 가스비 절감보다는 오프체인과의 편한 연동을 위주로 코딩을 하느라 오프체인을 사용하는 고객사 입장에서 최대한 편리하게 맞추고 있지만
이게 이더리움의 경우라면 UUID같은걸 넣고 다시 해시하는 과정이 연산량이 들어가기 때문에 bytes32로 넣지 않았을까 싶다. 오픈씨도 보면 구조체 자체가 엄청 거대하고 이를 최적화 하고 너무 거대한 로딩을 피하기 위하여 바이트코드 레벨까지 들어가서 구조체의 부분부분을 끊어서 검증하는 로직으로 사용하고 있는데, 최적화를 더 하다보면 이런식으로 UUID를 직접 넣지 않을지 모르지만 일단 넣는 방법은 구현할 수 있었다.
교훈 : 정말 막힐때는 공식문서로 되돌아가자. 공식문서의 예시나 애초에 내가 하려는 시도가 지원이 되는 케이스라면 무엇이 잘못된건지 차근차근히 짚어야 한다. 특히 EIP가 적용된 부분은 EIP문서를 계속해서 들여다보면 답이 나오는 경우가 있는거 같다.
'블록체인 > Solidity' 카테고리의 다른 글
스마트컨트렉트 테스트에 Infinite Approve 적용하기 (0) | 2022.07.25 |
---|---|
스마트컨트렉트에서 소수점 처리하는법과 엑셀에서 검산하는 방법 및 유의점 (0) | 2022.07.25 |
Solidity에서 자주 만나는 에러 "CompilerError: Stack too deep, try removing local variables." 그리고 에러에 대한 해결 방안 정리 , 이벤트 로그와 함수 입력값 구조체로 개수 줄이기 (0) | 2022.07.13 |
이벤트 로그에 구조체 데이터 넣기, 이벤트 로그 작성하기 (0) | 2022.07.13 |
delegateCall에서의 상태변화 가능여부 및 사용하면 안되는 이유 (0) | 2022.07.08 |