О чем вы хотели бы предупредить других разработчиков?
Что работает на большинстве других языков, но не работает или ведет себя так, как ожидалось, в Solidity?
Только для примера: какие параметры можно передавать функциям, что можно возвращать из функций?
Объявление локального массива (или другого ссылочного типа ) и предположение, что он будет создан в памяти, но фактически перезапишет хранилище :
/// THIS CONTRACT CONTAINS AN ERROR
contract C {
uint someVariable;
uint[] data;
function f() {
uint[] x;
x.push(2);
data = x;
}
}
Тип локальной переменной x — uint[] storage, но поскольку хранилище не выделяется динамически, перед использованием его необходимо назначить из переменной состояния. Таким образом, для 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;
}
}
Из документов
В for (var i = 0; i < arrayName.length; i++) { ... } тип i будет uint8, потому что это наименьший тип, необходимый для хранения значения 0. Если в массиве больше чем 255 элементов, цикл не завершится.
также
Пока нельзя использовать массивы массивов во внешних функциях. ... Вы можете использовать только один уровень динамических массивов [где угодно].
а также
Из-за ограничений EVM невозможно вернуть динамическое содержимое из вызовов внешних функций. Функция f в контракте C { function f() return (uint[]) { ... } } вернет что-то, если она вызывается из web3.js, но не из Solidity. Единственным обходным решением на данный момент является использование больших массивов статического размера.
string[] не разрешены в параметрах функции или возвращаемых значениях.
обратитесь к обсуждению здесь:
нельзя ли использовать массив строк в качестве аргумента функции прочности?
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]
недействителен.
Использование delete
в массиве оставляет зазор, поэтому вам нужно сместить элементы вручную и обновить свойство длины.
string
то же самое, bytes
но не разрешает доступ к длине или индексу.
bytes
то же самое, byte[]
но упаковано плотно (дороже).
Суффиксы даты нельзя применять к переменным.
Solidity наследует правила области видимости от JavaScript; нет области видимости блока.
Чтобы узнать больше о солидности, посетите https://github.com/miguelmota/solidity-idiosyncrasies.
ryepdx