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/에 원래 게시됨

좋은 웹페이지 즐겨찾기