Как отправить байтовый массив python в функцию солидности с помощью web3.py?

У меня есть функция прочности, объявленная как:

function setUnitData(bytes32[10] my_input_array) public payable {...}

Когда я запускаю этот код:

contract = self.contract_instance['../contracts/test.sol:test']

test_byte = b'0x01234567890123456789012345678901' * 24
tx_hash = contract.functions.setUnitData(test_byte).transact({'from': self.w3.toChecksumAddress(unit['update_account']), 'gas': 3400000})

Я получаю это ValidationError:

web3.exceptions.ValidationError: Не удалось идентифицировать предполагаемую функцию с именем setUnitData, позиционным аргументом (аргументами) типа (<class 'bytes'>,)и аргументом (аргументами) ключевого слова типа {}. Найдено 1 функция (функции) с именем setUnitData: ['setUnitData(bytes32[10])'] Не удалось вызвать функцию из-за отсутствия соответствующих типов аргументов.

Любой возможный или лучший способ отправить массив байтов python или любой работоспособный тип этой функции?

Ответы (2)

Для функции setUnitData(bytes32[10])требуется массив из 10 элементов, каждый из которых представляет собой 32 байта данных. Поскольку мы не знаем назначение функции, давайте сгенерируем случайные данные такого типа:

>>> input_array = [bytes(range(idx, 32 + idx)) for idx in range(10)]
[b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f',
 b'\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ',
 b'\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !',
 b'\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"',
 b'\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#',
 b'\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$',
 b'\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%',
 b'\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&',
 b'\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'',
 b'\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'(']

Если просмотр собственных значений байтов в python вызывает у вас раздражение, вы можете преобразовать их в шестнадцатеричные строки. Web3.py тоже примет.

>>> from web3 import Web3
>>> hex_array = [Web3.toHex(bytes_data) for bytes_data in input_array] 
['0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
 '0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20',
 '0x02030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021',
 '0x030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122',
 '0x0405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223',
 '0x05060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324',
 '0x060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425',
 '0x0708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20212223242526',
 '0x08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627',
 '0x090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728']

Теперь вы можете отправить транзакцию с помощью:

contract = self.contract_instance['../contracts/test.sol:test']
tx_hash = contract.functions.setUnitData(input_array).transact({'from': self.w3.toChecksumAddress(unit['update_account']), 'gas': 3400000})

( hex_arrayтакже работает вместо input_array)

Он возвращает следующую ошибку: Could not decode contract function call getJobStorageTime return data b''@carver

Вам нужно передать массив байтов. cntract ожидает массив из 10 элементов, но вы передаете переменную bytes. Вы можете создать массив со всеми остальными элементами, установленными в нули.

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