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

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

16 голосов | спросил Ethan Wilding 25 Jpm1000000pmMon, 25 Jan 2016 19:42:05 +030016 2016, 19:42:05

2 ответа


19

Существует несколько типов строковых значений, которые вы можете иметь в виду.

  • 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, но с ограничением, которое твердость не поддерживает возврат значений динамического размера к другим функциям. Это означает, что вы сможете использовать функцию 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 и getDynamicData, когда call из-за блочной цепочки.

ответил Piper Merriam 26 Jpm1000000pmTue, 26 Jan 2016 19:11:05 +030016 2016, 19:11:05
1

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

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
ответил Pouladzade 4 MaramSun, 04 Mar 2018 01:17:26 +03002018-03-04T01:17:26+03:0001 2018, 01:17:26

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132