Каковы распространенные ошибки или ограничения при кодировании в Solidity?

Что было бы в вашем списке, чтобы предупредить других разработчиков?

Что работает на большинстве других языков, которые не работают или ведут себя так, как ожидалось, в Solidity?

Например, только: какие параметры могут быть переданы в функции, что можно вернуть из функций?

21 голос | спросил eth 22 Jam1000000amFri, 22 Jan 2016 01:22:04 +030016 2016, 01:22:04

6 ответов


14

Объявление локального массива (или другого типа ссылки ) и предположим, что он будет создан в памяти, но фактически перезапишет хранилище :

/// THIS CONTRACT CONTAINS AN ERROR
contract C {
    uint someVariable;
    uint[] data;

    function f() {
        uint[] x;
        x.push(2);
        data = x;
    }
}
  

Тип локальной переменной x является хранилищем uint [], но поскольку хранилище   не динамически распределяется, он должен быть назначен из состояния   перед тем, как он может быть использован. Таким образом, пространство в хранилище не будет   выделяется для x, но вместо этого он функционирует только как псевдоним для   существующая переменная в хранилище.

     

Что произойдет, так это то, что компилятор интерпретирует x как хранилище   указатель и будет указывать на слот памяти 0 по умолчанию. Эта   имеет значение, что someVariable (который находится в слоте 0 памяти)   изменен с помощью x.push (2).

     

Правильный способ сделать это:

contract C {
    uint someVariable;
    uint[] data;

    function f() {
        uint[] x = data;
        x.push(2);
    }
}

OR

contract C {
    uint someVariable;
    uint[] data;

    function f() {
        uint[] memory x = new uint[](1);
        x[0] = 2;
        data = x;
    }
}
ответил eth 22 Jam1000000amFri, 22 Jan 2016 01:22:04 +030016 2016, 01:22:04
12

В документах

  

In for (var i = 0; i <arrayName.length; i ++) {...}, тип i будет uint8, потому что это наименьший тип, который требуется для хранения значения 0. Если массив имеет более 255 элементов, цикл не будет завершен.

и

  

Пока невозможно использовать массивы массивов во внешних функциях. ... Вы можете использовать только один уровень динамических массивов [где угодно].

и

  

Из-за ограничений EVM невозможно вернуть динамический контент из внешних вызовов функций. Функция f в контракте C {функция f () возвращает (uint []) {...}} вернет что-то, если вызвана из web3.js, но не вызвана из Solidity.   Единственным обходным решением на данный момент является использование больших массивов статического размера.

ответил Tjaden Hess 22 Jam1000000amFri, 22 Jan 2016 01:41:30 +030016 2016, 01:41:30
6
  • Всегда предоставляйте достаточно газа для транзакции (90% ошибок новобранец из-за нехватки газа)
  • Исключения будут потреблять весь транзакционный газ (используйте с осторожностью)
  • Это не может быть легко проверено, если ваш контракт выдает исключение
  • Нелегко проверить, не закончился ли у вашей транзакции газ.
  • Вещи могут работать с testnet, но могут терпеть неудачу в частной тестовой сети (проверьте, чтобы она работала в обоих)
  • Ограниченная поддержка строки без внешних библиотек
  • Некоторые функции могут выйти из строя (например, отправить), проверить возвращаемое значение
  • Следите за повторными проблемами (особенно при отправке денег или другого токена)
ответил Tjaden Hess 22 Jam1000000amFri, 22 Jan 2016 01:41:30 +030016 2016, 01:41:30
3

string [] не разрешены в параметрах функции или возвратах.

обратитесь к обсуждению здесь:
Невозможно ли использовать массив строк в качестве аргумента функции сплошности?

ответил Shawn Guo 12 Jpm1000000pmThu, 12 Jan 2017 17:12:33 +030017 2017, 17:12:33
1

returns с именованными параметрами вывода вводит новую локальную переменную.

например. из этого вопроса :

contract Test {
    address owner;

    function Test(){
        owner = msg.sender;
    }

    function getOwner() returns (address owner) {
        return owner;
    }
}

Здесь в getOwner вводится новая переменная owner и инициализируется до нуля. По совпадению это переопределяет переменную состояния owner, которая приводит к неожиданному результату.


Отображения допускаются только для переменных состояния (или в качестве ссылочных типов хранения во внутренних функциях).

например. из этого вопроса :

function getBalance(address addr) returns (uint, uint) {
    mapping(address => uint)  balancers;
    balancers[msg.sender] = 500;

    return (balancesA[addr], balancesB[addr]);
}

Здесь mapping(address => uint) balances не выделяет новое сопоставление, а вводит неинициализированную переменную. Следовательно, доступ к балансирам balancers[msg.sender] недействителен.

ответил max taldykin 3 MarpmFri, 03 Mar 2017 21:29:38 +03002017-03-03T21:29:38+03:0009 2017, 21:29:38
0
  • Использование delete в массиве оставляет пробел, поэтому вам нужно переместить элементы вручную и обновить свойство length.

  • string совпадает с bytes, но не разрешает доступ к длине или индексу.

  • bytes - это тот же byte[], но упакован плотно (дороже).

  • Суффикс даты не может быть применен к переменным.

  • Надежность наследует правила определения области видимости от JavaScript; нет области обзора.

Для получения большей прочности, проверьте https://github.com/miguelmota/solidity-idiosyncrasies

ответил Miguel Mota 17 +03002017-10-17T19:52:44+03:00312017bEurope/MoscowTue, 17 Oct 2017 19:52:44 +0300 2017, 19:52:44

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

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

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