Solidity Programming: Strings, Bytes, and Address Types

In this article, we'll discuss a few more fundamental datatypes in Solidity programming, namely: strings, bytes, and address types.

This article is based on notes from this Blockchain Developer course and is organized as follows:

  • Strings with Solidity
  • Bytes with Solidity
  • Address Types
  • Understanding the Msg. Object

Stay up to date with AI

We're an independent group of machine learning engineers, quantitative analysts, and quantum computing enthusiasts. Subscribe to our newsletter and never miss our articles, latest news, etc.

Great! Check your inbox and click the link.
Sorry, something went wrong. Please try again.

Strings with Solidity

Strings are actually arrays in Solidity and very similar to byte arrays.

Let's break down what that means in more detail.

Strings are quite unique in Solidity compared to other programming languages in that there are no string manipulation functions, except you can concatenate strings.

Other than concatenation, there are no string manipulation functions. The reason for this is that strings are very expensive to store on a blockchain.

Let's get started with an example with a new file in Remix called ExampleStrings.sol.

We'll then add our pragma line and start a new contract ExampleStrings and define a public "Hello World" string as follows:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract ExampleStrings {

    string public myString = "Hello World";

}

Next, we'll add a setter function for it, and place the _myString parameter within a memory location.

Memories are an ephemeral data location to work within functions, or during the transaction, meaning the memory location will be gone after the transaction is completed.

In order to make this permanent, we simply need to bring it to a storage location as follows:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract ExampleStrings {

    string public myString = "Hello World";

    function setMyString(string memory _myString) public {
        myString = _myString;

    }

}

Now if we deploy this contract we can now update our string with the setter function:

Comparing two strings

If we want to compare two strings we can create a function that will tell us if the string is the same as the string that was previously stored.

In this case, we will make this a public view function, which means it's a reading function that can return something, in this case we will return a boolean.

If we try and use return myString == _myString; we will get an error because their is no native comparison for strings in Solidity.

To resolve this we need to use the keccak256 hash of both strings, and we also have to use abi.encodePacked since this hash function requires a single bytes argument:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract ExampleStrings {

    string public myString = "Hello World";

    function setMyString(string memory _myString) public {
        myString = _myString;
    }

    function compareTwoStrings(string memory _myString) public view returns(bool) {
        return keccak256(abi.encodePacked(myString)) == keccak256(abi.encodePacked(_myString));
    }

}

If we redeploy this our initial string is "Hello World" and compare it to a different string we see the boolean returns false:

In this case, we're not actually comparing the strings but comparing the hashes of the strings.

Bytes with Solidity

There is a difference between bytes and strings, although we can add a line of bytes public myBytes = "Hello World"; and it will return a byte representation of the string:

Aside from that, the main differences between bytes and strings are:

  • Bytes have a length and can be converted into strings
  • You cannot convert every string into bytes and get the length because strings are represented in UTF8 while bytes are not

This means that sometimes a character is represented by two bytes and other times by one byte.

This is why, in general, it is not very advisable to use strings in smart contracts, although we will still continue working with them for demonstration purposes.

Address Types

One datatype that is very specific to Solidity is the address type.

Address types store 20 bytes worth of an Ethereum address or an Ethereum account.

Let's see how address types work by creating new file in remix called ExampleAddress.sol and a contract with the same name.

We'll then create an address type, make it public, and call it someAdress:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract ExampleAddress {

    address public someAddress;

}

If we deploy this, we see that by default the address is 0x... followed by 40 0's, or 20 bytes worth of 0's.

If we want to set this to a different address we can create a function setSomeAddress as follows:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract ExampleAddress {

    address public someAddress;

    function setSomeAddress(address _someAddress) public {
        someAddress = _someAddress;
    }

}

Now if we try and set the address to 0x01, we see we get an "incorrect address" error as we need the exact characters for an address.

Instead, we can get a correct address from Remix above, copy it to our clipboard, and then change the address without any errors:

Getting the balance of an address

Addresses also have a member property for the balance.

We can get the balance of an address by:

  • Creating function called getAddressBalance()
  • We will make it a public view function because we will read something and will return an unsigned integer
  • We will then return someAddress.balance
//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract ExampleAddress {

    address public someAddress;

    function setSomeAddress(address _someAddress) public {
        someAddress = _someAddress;
    }

    function getAddressBalance() public view returns(uint) {
        return someAddress.balance;
    }

}

Now if we deploy this contract and set the address to one of the test addresses provided by Remix we can then return the balance:

Understanding the Msg. Object

One more variable to discuss in this article is the messenger object, in particular, the property msg.sender.

The messenger object is a key part of Ethereum blockchain programming as it highlights the difference between a classical, centralized database and a blockchain-based one where we have public and private keys.

To start, we'll create a new contract called ExampleMsgSender.sol and start it off similar to our ExampleAddress contract above with a public address.

We'll then add a function called updateSomeAddress() without passing in any parameters and we'll set someAddress to msg.sender:

//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract ExampleAddress {

    address public someAddress;

    function updateSomeAddress() public {
        someAddress = msg.sender;
    }

}

The msg object is a public object that is available through all your contracts and contracts and contains several properties:

  • The sender property contains the address of the person who is interacting with the smart contract
  • If an account is calling the contract, it will contain the address of the account
  • This also means if one contract is interacting with another contract, the msg.sender will contain the address of the last point of contact

If we deploy this contract we see that someAdress is 0x0...initially, and if we hit updateSomeAddress it will automatically change to the last address that interacted with the contract:

Summary: Strings, Bytes, and Address Types with Solidity

In this article, we discussed key data types in Solidty: strings, bytes, and address types. A few key points to remember are:

  • Strings are actually arrays in Solidity and are very similar to byte arrays
  • Memories are an ephemeral data location to work within functions, or during the transaction, meaning the memory location will be gone after the transaction is completed.
  • The main difference between bytes and strings is that bytes have a length and can be converted into strings. You cannot convert every string into bytes and get the length because strings are represented in UTF8 while bytes are not.
  • Address types store 20 bytes worth of an Ethereum address or an Ethereum account.
  • The msg object is a public object that is available through all your contracts and contracts and contains the address of the person who is interacting with the smart contract

Resources