Learning Objectives – after this chapter you will be able to:
  • Declare strings and choose memory or calldata for them.
  • Find a string’s byte length, compare two strings and join strings.
  • Convert between string and bytes, and use escape sequences.
String
  • Solidity data types are classified as value types and reference types. A string is a reference type: the variable refers to where the text is stored.
  • A string is a dynamically sized sequence of characters – letters, digits, spaces and symbols.
  • Strings are stored as UTF-8 encoded bytes. Internally string is the same as bytes, but it does not allow index access or a .length member.
  • Both double quotes "Hello" and single quotes 'Hello' can be used for string literals. Normal literals may contain only printable ASCII; for other characters use a Unicode literal: unicode"नमस्ते ₹".
String and Memory
  • Because a string has no fixed size, you must tell the compiler where it is kept when it is used in a function: memory, calldata or storage.
  • memory is a temporary area (much like RAM). A function can use memory while it runs; after execution the memory is wiped. storage keeps data between calls.
  • Return values of type string are always declared string memory.
  • Parameters of external functions can use string calldata, which is read-only and cheaper.
Common String Operations
TaskHow
Length (in bytes)bytes(s).length – counts bytes, not characters; a non-ASCII character such as “₹” takes 3 bytes in UTF-8.
Compare two stringskeccak256(bytes(a)) == keccak256(bytes(b)) – the == operator does not work on strings.
Join (concatenate)string.concat(a, " ", b) (Solidity 0.8.12+)
Read one bytebytes(s)[0] returns a bytes1
Bytes to stringstring(b) where b is bytes memory
Empty checkbytes(s).length == 0

Bytes to String Conversion – bytes can be converted to a string with the string() conversion:
bytes memory bstr = new bytes(10);
string memory message = string(bstr);

Escape Characters
SequenceDescription
\"Double quote
\'Single quote
\nNew line
\\Backslash
\tTab
\rCarriage return
\xNNHex escape (one byte)
\uNNNNUnicode escape (inserted as UTF-8)
\ + new lineContinues the literal on the next line
Example : Working with Strings
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract StringDemo {
    string public greeting = "Hello";        // stored permanently in storage

    function setGreeting(string calldata text) external {
        greeting = text;                      // calldata -> storage copy
    }

    function byteLength(string calldata text) external pure returns (uint) {
        return bytes(text).length;            // number of UTF-8 bytes
    }

    function isEqual(string memory a, string memory b) public pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }

    function fullName(string memory first, string memory last) public pure returns (string memory) {
        return string.concat(first, " ", last);
    }

    function firstLetter(string memory text) public pure returns (bytes1) {
        require(bytes(text).length > 0, "Empty string");
        return bytes(text)[0];
    }

    function rupee() public pure returns (string memory, uint) {
        string memory symbol = unicode"₹";
        return (symbol, bytes(symbol).length);   // ("₹", 3)
    }
}
Key Takeaways
  • string is a dynamic UTF-8 reference type – always give it a data location in functions.
  • Convert to bytes for length and indexing; compare strings with keccak256.
  • Use string.concat to join and unicode"..." for non-ASCII text.
Download | Print      E-Notes

The PDF E-Notes are the earlier printable version of this chapter. The notes on this page are the latest, revised version.

Video : Strings in Solidity
Resource File
Question / Answer (15 questions)

Answer : A reference type. It is dynamically sized, so the variable refers to the location of the data and needs a data location (memory, calldata or storage) inside functions.

Answer : UTF-8. Internally a string is a byte array of its UTF-8 encoding.

Answer : Convert it to bytes and read the length: bytes(s).length. This returns the number of bytes, which can be larger than the number of characters for non-ASCII text.

Answer : The rupee sign is encoded in UTF-8 using three bytes, and the length counts bytes, not characters.

Answer : By comparing their hashes: keccak256(bytes(a)) == keccak256(bytes(b)). The == operator is not defined for strings.

Answer : With string.concat(a, b, ...), available from Solidity 0.8.12. Older code used string(abi.encodePacked(a, b)).

Answer : bytes memory bstr = new bytes(10); string memory message = string(bstr);

Answer : A returned string is a dynamic reference type that must be placed in a temporary location for the caller; memory is used for return values.

Answer : For parameters of external (or public) functions that only read the input. calldata is read-only and avoids copying the data into memory, which saves gas.

Answer : memory is temporary and exists only during the function call; storage is permanent and keeps the data on the blockchain between calls.

Answer : No. Index access is not allowed on string. Convert first: bytes(s)[0] returns the first byte as bytes1.

Answer : Use a Unicode literal, e.g. unicode"नमस्ते ₹". Regular string literals may contain only printable ASCII characters (plus escape sequences).

Answer : \" (double quote), ' (single quote), \n (new line), \ (backslash), \t (tab), \r (carriage return), \xNN (hex) and \uNNNN (Unicode).

Answer : bytes(s).length == 0.

Answer : Every byte stored in contract storage costs gas and is kept by every node, so long text increases deployment and transaction costs. Large data is usually stored off-chain with only a hash on-chain.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. Which expression correctly compares two strings a and b?

Show Answer

Correct Answer : C. keccak256(bytes(a)) == keccak256(bytes(b))
Strings are compared by hashing.

Q2. bytes("Hello").length returns:

Show Answer

Correct Answer : C. 5
Five ASCII characters = five bytes.

Q3. Which function joins strings in Solidity 0.8.12 and later?

Show Answer

Correct Answer : B. string.concat
string.concat was added in 0.8.12.

Q4. Which data location is read-only and suited to external string parameters?

Show Answer

Correct Answer : D. calldata
calldata is read-only and cheap.

Q5. Solidity strings are encoded as:

Show Answer

Correct Answer : A. UTF-8
Strings are UTF-8 byte arrays.

Bibliography/References

The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.

  1. Solidity Team. (n.d.). Types (value types, reference types, mappings, operators, conversions). Solidity Documentation. https://docs.soliditylang.org/en/latest/types.html
  2. Solidity Team. (n.d.). Cheatsheet. Solidity Documentation. https://docs.soliditylang.org/en/latest/cheatsheet.html
  3. GeeksforGeeks. (n.d.). Solidity – Strings. https://www.geeksforgeeks.org/solidity-strings/
  4. Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.