- PVSM.RU - https://www.pvsm.ru -
Добрый день.
Разбираясь со смарт-контрактами Ethereum [1](Solidity [2]) столкнулся с одной интересной особенностью использования библиотек (library), о которой вроде как прямо нигде не написано (по крайне мере я не нашел).
Если коротко:
1. Пусть у нас будет библиотека, в которой объявим структуру и функцию работы с ней (обратите внимание, что функция объявлена как public)
library TestLib {
struct One { … }
function setVal( One storage _one, … ) public {…}
}
2. Пусть у нас будет контракт, который использует эту библиотеку
contract TestContract {
using TestLib for TestLib.One;
TestLib.One one;
function setVal( … ) public {
one.setVal( … );
}
}
При этом все будет нормально компилироваться и работать в remix [3], да и тесты в truffle [4]на ganache-cli [5] выполнятся без шибок. Так же без ошибок будет деплой. Далее для вызова контрактов мы используем web3j [6](через консоль geth [7]будет схожее поведение).
И вот тут, при попытке вызвать метод контракта setVal, возникает мало информационная ошибка:
java.lang.IndexOutOfBoundsException: Index: 0
Проблема именно в том, что функции библиотеки, в аргументах которых есть переменные типа структуры, объявлены как public.
Надо отметить, что в контракте функция такого вида:
function setVal( TestLib.One _one ) public {...}
просто не скомпилируются.
Не совсем для меня понятно, почему компилятор не считает за ошибку наличие такой функции в библиотеке. Ну и ошибка выполнения, конечно, не раскрывает суть проблемы.
Особенно запутывает случай, если вдруг функция установки значения была internal, а функция получения – public. В этом случае может сложиться ложно представление, что функция установки работает не верно, т.к. при попытке получения данных видя сообщения исключения начинаешь думать, что в переменную структуры ничего не положили. Что и получилось с нашим проектом. Это привело к усиленному гуглению, проверки версий и прочее. А все, как часто бывает, оказалось намного проще: надо заменить public на internal.
Надеюсь, заметка сэкономит пару часов Вашего драгоценного времени, если вдруг столкнетесь с таким вот странным, поведением казалось бы, простых контракта и библиотеки.
Полезные ссылки:
Зачем использовать библиотеки в solidity [8]
Library Driven Development of Solidity [9]
Как вызвать контракт в консоли geth [10]
Автор: крепыш
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/solidity/286483
Ссылки в тексте:
[1] Ethereum : https://www.ethereum.org/
[2] Solidity: http://solidity.readthedocs.io/en/v0.4.24/)
[3] remix: https://remix.ethereum.org
[4] truffle : https://truffleframework.com/
[5] ganache-cli: https://github.com/trufflesuite/ganache-cli
[6] web3j : https://github.com/web3j/web3j
[7] geth : https://github.com/ethereum/go-ethereum/wiki/geth
[8] Зачем использовать библиотеки в solidity: http://www.zohaib.me/reusable-code-in-solidity-using-library/
[9] Library Driven Development of Solidity: https://medium.com/@kidinamoto/library-driven-development-of-solidity-ec7b0b41f38
[10] Как вызвать контракт в консоли geth: https://ethereum.stackexchange.com/questions/3514/how-to-call-a-contract-method-using-the-eth-call-json-rpc-api/3520
[11] Источник: http://habrahabr.ru/sandbox/122617/
Нажмите здесь для печати.