ens의 스마트 계약에서 Solidity의 문자열 길이를 찾는 방법
Why bytes(str).length; is not enough for getting length of string in Solidity, and let’s understand the strlen method from contracts of ens
Javascript의 세계에서 문자열의 길이를 찾는 것은 쉬운 일입니다.
그냥 해
str.length
그게 다야 🤌그러나 문자열은 Solidity 내에서 작업하기에 그리 친숙하지 않습니다. ❗
Solidity에서 문자열은 배열 내부에 저장된 문자 그룹이며 데이터를 바이트로 저장합니다.
문자열 유형에는 길이 방법이 없습니다.
Buildspace의 build-polygon-ens 프로젝트를 살펴보다가 StringUtils.sol에 대한 링크를 찾았습니다.
Solidity에서 문자열의 길이를 찾는 방법을 알았습니다. 문자열을 바이트로 변환하고 길이를 찾을 수 있습니다.
따라서
bytes(str).length;
🤌만큼 쉬울 것입니다. 하지만 이 util 파일의 방법은 조금 달랐습니다.// SPDX-License-Identifier: MIT
// Source:
// https://github.com/ensdomains/ens-contracts/blob/master/contracts/ethregistrar/StringUtils.sol
pragma solidity >=0.8.4;
library StringUtils {
/**
* @dev Returns the length of a given string
*
* @param s The string to measure the length of
* @return The length of the input string
*/
function strlen(string memory s) internal pure returns (uint256) {
uint256 len;
uint256 i = 0;
uint256 bytelength = bytes(s).length;
for (len = 0; i < bytelength; len++) {
bytes1 b = bytes(s)[i];
if (b < 0x80) {
i += 1;
} else if (b < 0xE0) {
i += 2;
} else if (b < 0xF0) {
i += 3;
} else if (b < 0xF8) {
i += 4;
} else if (b < 0xFC) {
i += 5;
} else {
i += 6;
}
}
return len;
}
}
내가 이해할 수 없는 코드에 이상한 for 루프가 있었습니다.
그래서 제 안에 있는 개발자가 🕵️♀️를 검색했지만 제가 찾은 모든 기사는 문자열의 길이를 찾기 위해 이 작업을 수행했습니다
bytes(str).length;
. Stackoverflow에서 비슷한 코드를 찾았지만 실제로 내부에서 일어나는 일을 아무도 설명하지 않았습니다.for(len = 0; i < bytelength; len++) {
bytes1 b = bytes(s)[i];
if(b < 0x80) {
i += 1;
} else if (b < 0xE0) {
i += 2;
} else if (b < 0xF0) {
i += 3;
} else if (b < 0xF8) {
i += 4;
} else if (b < 0xFC) {
i += 5;
} else {
i += 6;
}
}
3시간의 🐌자기 탐구 끝에 스스로 알아낼 수 있었고(조금 느리지만 해냈습니다🍾),
그래서 저와 같은 모든 사람들에게 도움이 될 수 있도록 적어보자고 생각했습니다(비트, 바이트 0️⃣1️⃣).
이제 이것을 차단 해제/디코딩해 보겠습니다.
bytes(str).length 작동 방식
문자열을 바이트로 변환할 때 이것이 Solidity가 하는 일입니다.
// if we do bytes("xyz"), solidity converts it as
xyz -> 78 79 7a // 78=x, 79=y, 7a=z
ABC -> 41 42 43 // 41=A, 42=B, 43=C
문자열을 바이트로 변환하려면 이것을 사용하십시오website.
각 문자가 1바이트를 생성하는 것을 보면
이것이 우리가 bytes("").length를 수행할 때 문자열의 길이를 얻는 이유입니다.
But there are some characters for which generated bytes are more than one
For example
€ -> e2 82 ac
유로 기호의 경우 생성된 바이트는 3입니다.
따라서 Euro(€) 🤑 기호가 포함된 문자열의 길이를 찾으려고 하면 반환되는 길이입니다.
bytes(str).length
€ 3바이트가 생성되므로 이 문자에 대한 올바른 문자열 길이를 반환하지 않습니다.그때 우리가 위에서 본 for 루프가 구출됩니다 ⛑️
이
e2 82 ac
바이트 배열을 반복하고 해당 루프 내에서 무슨 일이 일어나고 있는지 확인합니다.for(len = 0; i < bytelength; len++) {
bytes1 b = bytes(s)[i];
// b = e2 for first iteration
if(b < 0x80) {
i += 1;
} else if (b < 0xE0) {
i += 2;
} else if (b < 0xF0) {
i += 3;
} else if (b < 0xF8) {
i += 4;
} else if (b < 0xFC) {
i += 5;
} else {
i += 6;
}
}
첫 번째 반복
b=e2
다음 줄에 조건이 있습니다.
if(b < 0x80) {
i += 1;
}
이 조건은 기본적으로 이러한 16진수 문자의 10진수 값을 비교합니다.
에 대한 십진수 값
0x80 -> 128
// our b is e2 at the moment, decimal value for e2 = 226
0xe2 -> 226
일반 문자의 경우 16진수 문자의 10진수 변환은
< 128
이고 a의 경우 97입니다.그래서 이렇게 모든 조건을 확인해보면
for(len = 0; i < bytelength; len++) {
bytes1 b = bytes(s)[i];
if(b < 0x80) { //0x80 = 128 => 226 < 128 ❌
i += 1;
} else if (b < 0xE0) { //0xE0 = 224 => 226 < 224 ❌
i += 2;
} else if (b < 0xF0) { //0xF0 = 240 => 226 < 240 ✅
i += 3;
}
...
}
이제 우리의
i is 3
,따라서 for 루프의 조건은
3<3
이며 이는 거짓이고 루프가 중단되며 값은len will be 1
현재And that’s it, it is the correct value for the length of string “€”
"€"와 같은 문자열을 더 시도하고 싶다면 1바이트 이상을 차지하는 작은 문자 목록이 있습니다.
€ -> e2 82 ac
à -> c3 83
¢ -> c2 a2
예를 들어
abc¢Ã
와 같은 임의의 문자열을 만들고 사용해 보십시오.짜잔 🎉 이제 작동합니다
나와 연결:
DM은 모든 종류의 개선 제안에 열려 있습니다.
https://pateldeep.xyz/에 원래 게시됨
Reference
이 문제에 관하여(ens의 스마트 계약에서 Solidity의 문자열 길이를 찾는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/deep1144/how-to-find-length-of-string-in-solidity-from-the-smart-contract-of-ens-415a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)