Wie sende ich ein Python-Bytearray in die Solidity-Funktion von web3.py?

Ich habe eine Solidity-Funktion deklariert als:

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

Wenn ich diesen Code ausführe:

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})

Ich bekomme das ValidationError:

web3.exceptions.ValidationError: Die beabsichtigte Funktion mit name setUnitData, Positionsargument(en) vom Typ (<class 'bytes'>,)und Schlüsselwortargument(en) vom Typ konnte nicht identifiziert werden {}. 1 Funktion(en) mit dem Namen gefunden setUnitData: ['setUnitData(bytes32[10])'] Funktionsaufruf fehlgeschlagen, da keine übereinstimmenden Argumenttypen vorhanden sind.

Gibt es eine mögliche oder beste Möglichkeit, das Python-Byte-Array oder einen funktionsfähigen Typ an diese Funktion zu senden?

Antworten (2)

Die Funktion setUnitData(bytes32[10])erfordert ein Array aus 10 Elementen, von denen jedes 32 Byte Daten enthält. Da wir den Zweck der Funktion nicht kennen, generieren wir einige zufällige Daten dieses Typs:

>>> 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 !"#$%&\'(']

Wenn das Betrachten nativer Bytewerte in Python Sie mürrisch macht, können Sie in Hex-Strings konvertieren. Web3.py akzeptiert beides.

>>> 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']

Jetzt können Sie eine Transaktion senden mit:

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_arrayfunktioniert auch anstelle von input_array)

Es gibt folgenden Fehler zurück: Could not decode contract function call getJobStorageTime return data b''@carver

Sie müssen ein Array von Bytes übergeben. Der cntract erwartet ein Array von 10 Elementen, aber Sie übergeben eine Bytes-Variable. Sie können ein Array erstellen, bei dem alle anderen Elemente auf Null gesetzt sind.

Hoffe das hilft