Передать массив в качестве первого параметра в web3.js

Когда я развиваюсь в солидности в сочетании с web3.js, недавно я столкнулся с некоторой проблемой. Я создаю код контракта ниже

//setContractDetail(index,bool isConsentItem,uint8[] detailItems)
function setContractDetail(uint8 index,bool isConsentItem,uint8[] detailItems) public checkOwner{
    consentForm.items[index].isConsent= isConsentItem;
    consentForm.items[index].itemDetail = detailItems;
    /* emit SetContractDetailEvent(msg.sender,index,isConsentItem,detailItems,now); */
}
function setContractDetail2(uint8 index,bool isConsentItem) public checkOwner{
    consentForm.items[index].isConsent = isConsentItem;
}
function setContractDetail3(uint8[] index,bool isConsentItem,uint8[] detailItems) public checkOwner{
    for(uint i=0;i<index.length;i++){
        uint pointer = index[i];
        consentForm.items[pointer].isConsent= isConsentItem;
        consentForm.items[pointer].itemDetail = detailItems;
    }
    /* emit SetContractDetailEvent(msg.sender,index,isConsentItem,detailItems,now); */
}
function setContractDetail4(bool isTest,uint8[] index,bool isConsentItem,uint8[] detailItems) public checkOwner{
    for(uint i=0;i<index.length;i++){
        uint pointer = index[i];
        consentForm.items[pointer].isConsent= isConsentItem;
        consentForm.items[pointer].itemDetail = detailItems;
    }
    /* emit SetContractDetailEvent(msg.sender,index,isConsentItem,detailItems,now); */
}

Когда я передаю первый параметр в виде массива (setContractDetail3), я всегда получаю сообщение об ошибке - ERROR Error: Error: требуется газ, превышающий норму или всегда терпящая неудачу транзакция . Однако, когда я устанавливаю значение, отличное от массива, в качестве первого параметра, вызов функции будет выполняться хорошо. Кто-нибудь знает, в чем причина этой проблемы?

ps Я мог успешно скомпилировать ремикс, но после того, как я установил контракт в консоли geth, а также подключился к web3.js, он в конечном итоге потерпел неудачу.

Вы установили Gas и GasPrice при вызове метода смарт-контракта?
Я использую «Mycontract.methods.mymethod(parms).estimateGas({from:account}).then()» для настройки значения газа. С другой стороны, я установил для своего gasPrice значение 0 (я использую geth для установки -gasPrice 0 при активации консоли)
Я до сих пор не знаю, в чем причина ошибки; но вашего оценочного звонка по газу, подобного этому estimateGas({from:account}), недостаточно, потому что в нем не хватает информации для оценки газа. Вы должны предоставить достаточно информации, как показано ниже
``` // CallMsg содержит параметры для вызовов контракта. type CallMsg struct { From common.Address // отправитель «транзакции» To *common.Address // контракт назначения (ноль для создания контракта) Gas uint64 // если 0, вызов выполняется с почти бесконечным gasPrice * big.Int // wei <-> коэффициент газообмена Value *big.Int // количество wei, отправленное вместе с вызовом Data []byte // входные данные, обычно вызов метода контракта в кодировке ABI } ```

Ответы (2)

Можно использовать динамические массивы в качестве аргумента функции, используя ABIEncoderV2 для функции твердости.

Обратитесь к следующему выпуску Github и блогу для получения более подробной информации:

https://github.com/ethereum/solidity/issues/2708

https://blog.ricmoo.com/solidity-abiv2-a-foray-into-the-experimental-a6afd3d47185

Однако использование нескольких динамических массивов в качестве аргумента может быть еще одной проблемой, поскольку в Java аргумент переменной длины должен быть последним аргументом функции, а использование нескольких аргументов переменной длины в одной и той же функции не допускается.

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

Здесь применяется ошибка, всегда приводящая к сбою транзакции - если вы передаете массив в качестве значения, если только структура consentForm.itemsне полностью идентична передаваемому массиву, транзакция будет искать, например, "randomStringThatIUsedToNameTheFirstItemInMyArray" и сравнивать его с любым items[0] обозначается как. Вероятно, это приведет к ошибке, и ваша функция застрянет в цикле, т . е. транзакция всегда будет завершаться ошибкой .

Помимо этой причины, я бы реструктурировал контракт, так как такие циклы всегда

а) опасный б) газовый тяжелый

... и, возможно, использовать блок try/catch в цикле в случае такой ошибки.