Как я могу вернуть несколько строк из функции контракта?

В солидности очевидно, как получить одну строку, возвращаемую функцией. Но я бы хотел, чтобы смарт-контракт возвращал несколько строковых значений. Есть ли способ сделать это?

Ответы (2)

Есть несколько типов строковых значений, на которые вы можете ссылаться.

  • bytes1- bytes32: фиксированный размер.
  • bytesили string: динамический размер.

Solidity поддерживает функции с несколькими возвращаемыми значениями.

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);
    }
}

Вы можете сделать то же самое с bytesили string, но с тем ограничением, что Solidity не поддерживает возврат значений динамического размера в другие функции. Это означает, что вы сможете использовать getDataфункцию из другого контракта и получить возвращаемые значения, но не сможете получить возвращаемые значения getDynamicDataиз контракта.

contract UsesMultiReturner {
    function doIt() {
        mr = MultiReturner(0x1234);

        // this will work
        var (a, b) = mr.getData();

        // this won't work
        var (a, b) = mr.getDynamicData();
    }
}

Однако вы можете получить возвращаемые значения как из, так и getDataиз -за пределов блокчейна.getDynamicDatacall

поскольку возвращаемый тип равен bytes32, должны ли мы привести тип varк bytes32?@Piper Merriam.
In Solidity varможет использоваться для делегирования выбора соответствующего типа компилятору. aи bбудет установлено как bytes32компилятор, так как компилятор знает, что mr.getData()вернет тип(bytes32, bytes32)
varтеперь устарело. Есть ли обновление о том, как вернуть несколько значений с помощью 0.4.21?
Solidity 0.4.23 , но я не уверен, что он действительно делает то же самое.

Вы можете использовать библиотеку Seriality . Seriality — это библиотека для очень эффективной сериализации и десериализации всех типов Solidity, которая в основном написана на Solidity-Assembly.

1- С помощью Seriality вы можете легко сериализовать и десериализовать свои переменные, структуры, массивы, кортежи... и передавать их через контракты и библиотеки.

2- Вы можете отделить свой контракт от библиотек, сериализовав параметры в массив байтов.

3- Его также можно использовать в качестве альтернативы протоколу RLP в Solidity.

Вот пример:

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;
  }    
}

Это вывод 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"

А вот буфер:

    42696120696e6a6120646168616e207365727669636500000000000000000000
    0000000000000000000000000000000000000000000000000000000000000016
    496e616d206a61766162206c6173686921000000000000000000000000000000
    0000000000000000000000000000000000000000000000000000000000000011
    4920616d20616e206974696e6572616e742070726f6772616d6d657200000000
    000000000000000000000000000000000000000000000000000000000000001c
    4d617920492062757920796f752061206472696e6b3f00000000000000000000
    0000000000000000000000000000000000000000000000000000000000000016
    436f6d65206f6e2062616279206c6574732064616e6365210000000000000000
    0000000000000000000000000000000000000000000000000000000000000018