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?
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 usingstring.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.
Update:
As of Solidity v0.8.12
the string.concat(a,b)
function is the preferred method, as mentioned here.
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.
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/…
Commented
Nov 26, 2019 at 0:07
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, "", "", "");
}
string s = string(abi.encodePacked("a", " ", "concatenated", " ", "string"));
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.
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.
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));
}