19

I want to sent a string as an argument to a function. But some user may enter maybe 100 size string or even larger.

[Q] Inside the function is it possible to check the size of the string and return false if it exceeds the length limit that I have specified.

For example, a user is only allowed to send string which has length of 64 characters, and the contract's function returns throw if the string exceeds the limit of 64 character.

Test.transaction().setVariable("very_large_size_string_entered_65_chars");

For example:

Contract Test{
   String data;
   function setVariable(string str) {
       //check somehow does the string exceeds the character limit.
       data = str;
   }
}

Thank you for your valuable time and help.

4 Answers 4

26

Just check if bytes(str).length is too big.

Mind: This does not show the number of characters! See the answer below if you need to know an exact length of a utf-8 encoded string. This will cost significantly more gas, however. Note that the utf-8 length will be at most the byte length.

3
  • 5
    This way you can check th byte-length of string. If string encoding, for example UTF8, number of characters can differ from bytes(str).length Commented Apr 4, 2017 at 1:39
  • This answer should be edited to include Alexey's comment. bytes(str).length does NOT give the intended behavior in some cases, so it must be used with caution.
    – Symeof
    Commented Oct 2, 2018 at 20:19
  • I would argue that byte-length is the more important metric in most cases, since length in encodings like utf-8 is still upper-bounded by byte length. It seems rather arbitrary to assume that OP is using utf8 or any other particular encoding. Commented Oct 3, 2018 at 15:14
30

Code for calculating string length in characters

contract utf8StringLength {
    //---------------------BEGIN Code to copy-paste--------------

    function utfStringLength(string str) constant returns (uint length)
    {
        uint i=0;
        bytes memory string_rep = bytes(str);

        while (i<string_rep.length)
        {
            if (string_rep[i]>>7==0)
                i+=1;
            else if (string_rep[i]>>5==0x6)
                i+=2;
            else if (string_rep[i]>>4==0xE)
                i+=3;
            else if (string_rep[i]>>3==0x1E)
                i+=4;
            else
                //For safety
                i+=1;

            length++;
        }
    }

    ////////////////////END Code to copy-paste///////////////////


    //-----------------BEGIN testing stuff code-----------------

    string constant hello1= "Привет";
    string constant hello2= "Hello";
    string constant hello3= "你好";
    string constant hello4= "هيلو";
    string constant hello5= "مرحبا";


    function test() constant
    returns
        (uint,
        uint,
        uint,
        uint,
        uint)
    {
        return(
            utfStringLength(hello1),
            utfStringLength(hello2),
            utfStringLength(hello3),
            utfStringLength(hello4),
            utfStringLength(hello5)
        );
    }
    //////////////////END testing stuff code//////////////////////
}

Updated for solc v0.8

function utfStringLength(string memory str) pure internal returns (uint length) {
    uint i=0;
    bytes memory string_rep = bytes(str);

    while (i<string_rep.length)
    {
        if (string_rep[i]>>7==0)
            i+=1;
        else if (string_rep[i]>>5==bytes1(uint8(0x6)))
            i+=2;
        else if (string_rep[i]>>4==bytes1(uint8(0xE)))
            i+=3;
        else if (string_rep[i]>>3==bytes1(uint8(0x1E)))
            i+=4;
        else
            //For safety
            i+=1;

        length++;
    }
}
6
  • IMO this is the better answer. Commented Jul 15, 2017 at 7:37
  • This seems like, it will consume much more gas. @Alexey Barsuk
    – alper
    Commented Apr 14, 2018 at 15:22
  • 2
    @Alper Yes it will. If I measured right, about 10 times more for this function in comparison with bytes(str).length for the same string. Commented Apr 15, 2018 at 16:59
  • Thats pretty expensive as cost of ether @AlexeyBarsuk
    – alper
    Commented Apr 15, 2018 at 17:48
  • I know this is an old answer, but something seems to have changed in the Solidity compiler. If I try it now (0.8.4) I get an error TypeError: Operator == not compatible with types bytes1 and int_const 6 on the line else if (string_rep[i]>>5==0x6)
    – Chris_77
    Commented Jan 11, 2022 at 7:38
1

This method is from ens domains smart contract
A detailed explanation can be found here, https://dev.to/deep1144/how-to-find-length-of-string-in-solidity-from-the-smart-contract-of-ens-415a

// 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;
    }
}

2
  • This function has higher gas consumption than simply having bytes(str).length
    – alper
    Commented May 22, 2022 at 7:59
  • Depending on the use case, if bytes(str).length works for you and no special characters are going to be involved in the string, then definitely use it
    – Deep patel
    Commented May 23, 2022 at 14:05
-1

stirng is the special kind of array and compatible with bytes. Solidity does not provide much string operation and hence we can rely on bytes to carry out any string related operations like null check, length ...

pls find below the modified code to check for the string limit. If supplied styring lenght is more than required then this funcction would revert the function call.

In ther latest solidity release, 'throw' has deprecated, thats why I have used 'revert'.

pragma solidity ^0.4.4;

contract Test{
   string data;
   uint stringLimit;

   function setVariable(string str)  {
      bytes memory strBytes = bytes(str);
      if(strBytes.length >= stringLimit)
          revert;
      else 
         data = str;
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.