95

I'm trying to concatenate two strings in solidity.

I tried with + or . but neither option works. There is not much documentation on string concatenation yet. Is it even possible?

If not, can I insert variables into strings?

7 Answers 7

41

As of Feb 2022, in Solidity v0.8.12 you can now concatenate strings in a simpler fashion!

string.concat(s1, s2)

Taken directly from the solidity docs on strings and bytes:

Solidity does not have string manipulation functions, but there are third-party string libraries. You can also compare two strings by their keccak256-hash using keccak256(abi.encodePacked(s1)) == keccak256(abi.encodePacked(s2)) and concatenate two strings using string.concat(s1, s2).

contract Poem {
    string public text;

    function addLine(string memory added_text) public {
           text = string.concat(text,added_text);
    }
}

The above code snippet is provided by Hannu-Daniel Goiss on his article about string concatenation.

88

Update:

As of Solidity v0.8.12 the string.concat(a,b) function is the preferred method, as mentioned here.


Optimized for low gas-consumption

The ethereum community has implemented some ABI encoding functions which can be accessed natively without having to call another contract. This is how you could append a string to another with ABI encoding:

function append(string a, string b, string c, string d, string e) internal pure returns (string) {

    return string(abi.encodePacked(a, b, c, d, e));

}

For demonstration, I called both functions, this one and the one used in the oraclizeAPI contract as proposed earlier, in remix with 5x the argument "string" and compared the gas consumption which turned out to be for ABI encoding less than 2/3 of what the other solution burns and the execution cost only about 1/7th:

Initial Solution:
Transaction cost: 45380
Execution cost: 19436

ABI encoding:
Transaction cost: 28650
Execution cost: 2706


To be fair, ABI encoding has not been around for too long and the earlier proposed solutions get the job done as well. I have been using the strConcat function from oraclizeAPI for some time myself. However, especially if you need this function to be called by another smart contract or internally by a function changing the state of the contract, for the sake of cost-efficiency, you should definitely use ABI encoding.

4
  • 2
    This is the correct answer in 2019
    – Miguel
    Commented Jul 30, 2019 at 3:21
  • What version of Solidity does this require? I got error: TypeError: Data location must be "storage" or "memory" for parameter in function, but none was given. function append(string a, string b, string c, string d, string e, string f) internal pure returns (string) { Commented Oct 23, 2019 at 23:12
  • I think, back when I wrote the answer, I was still using Solidity ^0.4.24. In Solidity 0.5.0 and higher, you are required to specify for strings whether they will be stored in memory or storage. If you add the memory keyword after string for every parameter and the return value, everything should work as expected. Commented Oct 23, 2019 at 23:22
  • As of Solidity 0.5.0, abi.encodePacked is the recommended way. I can confirm that it works when the more complicated old way hits the block gas limit with the same two strings being concatenated. solidity.readthedocs.io/en/v0.5.3/…
    – Cliff Hall
    Commented Nov 26, 2019 at 0:07
31

You can do that in Solidity by copying each byte of the input strings to the output one.

You can find an implementation of this in oraclizeAPI for example (function strConcat).

The code is pretty much the following:

function strConcat(string _a, string _b, string _c, string _d, string _e) internal returns (string){
    bytes memory _ba = bytes(_a);
    bytes memory _bb = bytes(_b);
    bytes memory _bc = bytes(_c);
    bytes memory _bd = bytes(_d);
    bytes memory _be = bytes(_e);
    string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length);
    bytes memory babcde = bytes(abcde);
    uint k = 0;
    for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i];
    for (i = 0; i < _bb.length; i++) babcde[k++] = _bb[i];
    for (i = 0; i < _bc.length; i++) babcde[k++] = _bc[i];
    for (i = 0; i < _bd.length; i++) babcde[k++] = _bd[i];
    for (i = 0; i < _be.length; i++) babcde[k++] = _be[i];
    return string(babcde);
}

function strConcat(string _a, string _b, string _c, string _d) internal returns (string) {
    return strConcat(_a, _b, _c, _d, "");
}

function strConcat(string _a, string _b, string _c) internal returns (string) {
    return strConcat(_a, _b, _c, "", "");
}

function strConcat(string _a, string _b) internal returns (string) {
    return strConcat(_a, _b, "", "", "");
}
2
  • 1
    Nice. Looks like you provide other helpers too in your link. Didn't see any examples yet in the repo, but I assume there would be some examples where it's essential for someone to use strConcat on-chain?
    – eth
    Commented Feb 10, 2016 at 5:37
  • 1
    What is this just to concat string that is why most programers are poor Commented Jun 23, 2021 at 8:56
19
string s = string(abi.encodePacked("a", " ", "concatenated", " ", "string"));

ethfiddle

2
  • 3
    Any pros and cons for this approach would be much appreciated by newbie like me. Thanks for the solution anyway.
    – LiweiZ
    Commented Jul 20, 2018 at 4:14
  • Was using this in a require error message, and it return unreadable data: Error: Returned error: VM Exception while processing transaction: revert transferFrom: From address must have enough tokens, fromAddress=ͼ=;9h�}>8�bw�N�A balance= transferAmount= +�'� Was trying to debug why my require was firing. Commented Oct 23, 2019 at 23:19
13

To be honest, I don't think you should do string manipulation in the contract (which is on the blockchain). A well-developed blockchain app should be kicked off from a user account, not a contract. Contract initiated transactions should do simple things like transferring stuff. If you are concatenating between two strings, then treat them like the underlying array data that they are and simply push the new value on the old one.

Otherwise, for serious manipulating of strings, do it on the client side before posting it in the body of the transaction back to the blockchain. Basically, with Ethereum, we're sort of like in the early stages of databases with SQL still on the horizon. Do the work outside the datapile.

1
  • 3
    I'm using it for developing unit tests in solidity. FWIW.
    – n13
    Commented Jun 13, 2018 at 5:47
12

A library can be used, for example:

import "github.com/Arachnid/solidity-stringutils/strings.sol";

contract C {
  using strings for *;
  string public s;

  function foo(string s1, string s2) {
    s = s1.toSlice().concat(s2.toSlice());
  }
}

Use the above for a quick test that you can modify for your needs.


Since concatenating strings needs to be done manually for now, and doing so in a contract may consume unnecessary gas (new string has to be allocated and then each character written), it is worth considering what's the use case that needs string concatenation?

If the DApp can be written in a way so that the frontend concatenates the strings, and then passes it to the contract for processing, this could be a better design.

Or, if a contract wants to hash a single long string, note that all the built-in hashing functions in Solidity (sha256, ripemd160, sha3) take a variable number of arguments and will perform the concatenation before computing the hash.

1

Is just a litle update on the selected answer

using Solidity ^0.8.4

function appendString(string memory _a, string memory _b, string memory _c) internal pure returns (string memory)  {
    return string(abi.encodePacked(_a, _b, _c));
}

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.