Как продолжить выполнение функций, когда `require` оценивает false

У меня вопрос о модификаторах, требованиях и потоке функций.

Вот простой пример моей мысли.

      contract Numbers {
    uint256[] private _numbers;

    modifier bigNumber(uint256 someNumber) {
        require(someNumber > 10, "Numbers: Number must be greater than 10");
        _;
    }

    function _addNumber(uint256 someNumber) private bigNumber(someNumber) {
        _numbers.push(someNumber);
    }

    function addNumbers(uint256[] memory _newNumbers) external {
        for (uint256 i = 0; i < _newNumbers.length; i++) {
            _addNumber(_newNumbers[i]);
        }
    }
}

Скажем, я вызываю эту функцию с помощью addNumbers([11, 12, 13, 8, 20, 21, 5, 22, 23]);

Я бы получил сообщение об ошибке, когда он достигнет 8.

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

Я подумал добавить if чтобы «поймать» ошибку раньше, но, возможно, есть способ лучше.

Заранее спасибо!

1 ответ

Неудачный require() условие вызывает исключение.


В вашем случае самый простой способ - продублировать условие в вашем addNumbers() функция.

      function addNumbers(uint256[] memory _newNumbers) external {
    for (uint256 i = 0; i < _newNumbers.length; i++) {

        // duplicated condition from the modifier
        if (_newNumbers[i] <= 10) {
            _addNumber(_newNumbers[i]);
        }
    }
}

Если бы функция была external (т.е. исполняемый вне контракта), вы можете использовать выражение try / catch.

      // mind the changed visibility from `private` to `external`
function _addNumber(uint256 someNumber) external bigNumber(someNumber) {
    _numbers.push(someNumber);
}

function addNumbers(uint256[] memory _newNumbers) external {
    for (uint256 i = 0; i < _newNumbers.length; i++) {
        try this._addNumber(_newNumbers[i]) {
            // do nothing if didn't throw an exception
        } catch (bytes memory) {
            // do nothing if threw an exception
        }
    }
}

Try / catch в настоящее время (v0.8) поддерживается только для внешних вызовов и создания контрактов. Вот почему вам нужно сделать _addNumber() внешняя функция, чтобы заставить ее работать.

Документы: https://docs.soliditylang.org/en/v0.8.6/control-structures.html#try-catch

Другие вопросы по тегам