In solidity it's obvious how to get a single string returned from a function. But, I'd like to have the smart contract return multiple string values. Is there a way to do this?
There are a few types of string values that you may be referring to.
bytes1
-bytes32
: fixed size.bytes
orstring
: dynamically sized.
Solidity supports functions with multiple return values.
contract MultiReturner {
function getData() constant returns (bytes32, bytes32) {
bytes32 a = "abcd";
bytes32 b = "wxyz";
return (a, b);
}
function getDynamicData() constant returns (bytes, bytes) {
bytes a;
a.push('a');
a.push('b');
a.push('c');
bytes b;
b.push('x');
b.push('y');
b.push('z');
return (a, b);
}
}
You can do the same with bytes
or string
but with the limitation that solidity does not support returning dynamically sized values to other functions. This means that you would be able to use the getData
function from within another contract and retrieve the return values but you would not be able to retrieve the return values from getDynamicData
from within a contract.
contract UsesMultiReturner {
function doIt() {
mr = MultiReturner(0x1234);
// this will work
var (a, b) = mr.getData();
// this won't work
var (a, b) = mr.getDynamicData();
}
}
You can however retrieve the return values from both getData
and getDynamicData
when call
from outside of the blockchain.
-
since returned type is
bytes32
, should we typecastvar
intobytes32
?@Piper Merriam. – alper Jan 11 '17 at 15:29 -
2In solidity
var
can be used to delegate selecting the appropriate type to the compiler.a
andb
will be set asbytes32
by the compiler since the compiler knows thatmr.getData()
will return type(bytes32, bytes32)
– Piper Merriam Jan 11 '17 at 15:35 -
var
is now deprecated. Is there an update on how to return multiple values using0.4.21
? – JohnAllen Mar 23 '18 at 17:14 -
Solidity 0.4.23, but I'm not sure if it actually does the same thing. – digitaldonkey May 23 '18 at 23:59
You can use Seriality library. Seriality is a library for serializing and de-serializing all the Solidity types in a very efficient way which mostly written in solidity-assembly
1- By means of Seriality you can easily serialize and deserialize your variables, structs, arrays, tuples, ... and pass them through the contracts and libraries.
2- You can decouple your contract from libraries by serializing parameters into a byte array.
3- It also can be used as an alternative for RLP protocol in Solidity.
Here is a sample :
pragma solidity ^0.4.16;
import "./Seriality.sol";
contract StringsReturn is Seriality {
function stringCaller() public returns( string memory out1,
string memory out2,
string memory out3,
string memory out4,
string memory out5)
{
bytes memory buffer = new bytes(320);
uint offset = stringCallee(buffer);
//deserializing
out1 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out1));
offset -= sizeOfString(out1);
out2 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out2));
offset -= sizeOfString(out2);
out3 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out3));
offset -= sizeOfString(out3);
out4 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out4));
offset -= sizeOfString(out4);
out5 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out5));
}
function stringCallee(bytes memory buffer) public returns (uint buffer_size) {
string memory out1 = new string(32);
string memory out2 = new string(32);
string memory out3 = new string(32);
string memory out4 = new string(32);
string memory out5 = new string(32);
out1 = "Come on baby lets dance!";
out2 = "May I buy you a drink?";
out3 = "I am an itinerant programmer";
out4 = "Inam javab lashi!";
out5 = "Bia inja dahan service";
// Serializing
buffer_size = sizeOfString(out5) +
sizeOfString(out4) +
sizeOfString(out3) +
sizeOfString(out2) +
sizeOfString(out1);
uint offset = buffer_size;
stringToBytes(offset, bytes(out1), buffer);
offset -= sizeOfString(out1);
stringToBytes(offset, bytes(out2), buffer);
offset -= sizeOfString(out2);
stringToBytes(offset, bytes(out3), buffer);
offset -= sizeOfString(out3);
stringToBytes(offset, bytes(out4), buffer);
offset -= sizeOfString(out4);
stringToBytes(offset, bytes(out5), buffer);
return buffer_size;
}
}
This is the output of stringCaller()
"0": "string: out1 Come on baby lets dance!",
"1": "string: out2 May I buy you a drink?",
"2": "string: out3 I am an itinerant programmer",
"3": "string: out4 Inam javab lashi!",
"4": "string: out5 Bia inja dahan service"
And here is the buffer :
42696120696e6a6120646168616e207365727669636500000000000000000000
0000000000000000000000000000000000000000000000000000000000000016
496e616d206a61766162206c6173686921000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000011
4920616d20616e206974696e6572616e742070726f6772616d6d657200000000
000000000000000000000000000000000000000000000000000000000000001c
4d617920492062757920796f752061206472696e6b3f00000000000000000000
0000000000000000000000000000000000000000000000000000000000000016
436f6d65206f6e2062616279206c6574732064616e6365210000000000000000
0000000000000000000000000000000000000000000000000000000000000018