Правильная обработка ошибок запроса/подтверждения отказа из приложения Node.JS?

У меня есть функция получения в моем смарт-контракте, которая возвращает одно из строковых значений в статически определенном массиве строк. При входе в функцию она выполняет проверку границ входящего индекса, используя require(). Если проверка границ не удалась, что произойдет в моем приложении Node.JS, которое использовало Web3.js для выполнения вызова? Будет ли выброшена ошибка Javascript? Получу ли я NULL обратно?

Если у кого-то есть хорошая статья или веб-ресурс, который показывает правильный способ обработки ошибок из вызова Web3.JS, которые привели к запуску операции assert или require на стороне смарт-контракта, поделитесь ею.

Вот мой код смарт-контракта:

pragma solidity ^0.4.23;

import "github.com/OpenZeppelin/zeppelin-solidity/contracts/ownership/Ownable.sol";

contract VideoDummyData is Ownable{

    // Constructor, MUST be public.
    constructor() public {
        // Unused.
    }

    // Array of sample video IDs.
    string[3] m_aryVideoIds = 
        ["ZUSPD9zOyJs", "4nqJiBRNQuw", "PLcxE4UkJt0"];


    // Return one of the sample video IDs.
    function getVideoIdAt (uint ndx) public view returns(string)
    {
        // Bounds check on the desired index.
        require(ndx < m_aryVideoIds.length);

        return m_aryVideoIds[ndx];
    }
}
Вы просто получите сообщение об ошибке от web3, но не сможете узнать, в чем именно заключается ошибка.
@Andromelus - не раньше следующей версии Solidity, верно, когда они позволят вам вернуть сообщение об ошибке с помощью assert/revert? Если я прав на этот счет, знаете ли вы, будет ли изменение немедленным, или нам нужно будет подождать, пока все узлы в сети Ethereum обновят или примут изменение (например, софт-форк)?
Вам нужно только, чтобы транзакция была добыта. Таким образом, узел, к которому вы подключены, должен знать блок, в котором находится tx.
Речь идет callо viewфункции, поэтому транзакция для майнинга не требуется.

Ответы (2)

Поскольку вы вызываете viewфункцию, первый обратный вызов вызовет ошибку более или менее немедленно.

В настоящее время возможно вернуть ошибки с помощью

require(expression, "error msg");

Проблема заключается в доступе к этому сообщению выше по стеку в Web3 и Node.

Тем временем вы можете использовать tryи .catch()в обещанном коде, таком как абстракция трюфельного контракта.

Вы не будете знать точную причину, но сможете сделать вывод, учитывая требования контракта.

Надеюсь, поможет.

После того, как вы вызываете/отправляете методы, возвращаются по какой-либо причине, вы получаете приведенный ниже ответ в своем коде express/nodejs.

   {
    "data": {
        "0x926192b712005c4eab709b7f7e1718435b6f2117580360b73e7601a439feffcd": {
            "error": "revert",
            "program_counter": 383,
            "return": "0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000165468697320496420616c72656164792065786973747300000000000000000000",
            "reason": "This Id already exists"
        },
        "stack": "RuntimeError: VM Exception while processing transaction: revert This Id already exists\n    at Function.RuntimeError.fromResults (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\utils\\runtimeerror.js:94:13)\n    at BlockchainDouble.processBlock (C:\\Program Files\\WindowsApps\\GanacheUI_2.5.4.0_x64__5dg5pnz03psnj\\app\\resources\\static\\node\\node_modules\\ganache-core\\lib\\blockchain_double.js:627:24)\n    at processTicksAndRejections (internal/process/task_queues.js:93:5)",
        "name": "RuntimeError"
    }
}

Теперь нам нужно показать пользователю соответствующее сообщение, чтобы пользователь мог понять, для чего мы можем использовать приведенный ниже код. Чтобы получить причину из возвращенного ответа. используйте приведенный ниже код в коде nodeJS/expressjs....

try {
    await myContract.methods.foo().send();
} catch (e) {
    const data = e.data;
    const txHash = Object.keys(data)[0]; 
    const reason = data[txHash].reason;

    console.log(reason); 
}