Ich habe es mit einem sehr einfachen Smart Contract zu tun:
contract MyRegistry {
struct MyEvent {
string code; // service code, e.g. 1001/FOO/BAR
string desc; // long string
uint count;
bool recorded;
}
event Record(bytes32 hash, string desc, uint count);
function record(bytes32 hash, string code, string desc, uint count) external {
if (registry[hash].recorded)
throw;
registry[hash] = MyEvent(code, desc, count, true);
}
mapping (bytes32 => MyEvent) public registry;
}
Ich verwende dann web3s getData()
zum Generieren von Transaktionsnutzlasten:
var EthTX = require('ethereumjs-tx')
[...]
var calldata = Registry.record.getData(hash, code, desc, count)
[...]
var transaction = new EthTX({
to: registry_address,
gasLimit: 500000,
gasPrice: +web3.toWei(10, 'gwei'),
nonce: myNonce,
data: calldata,
})
Die Transaktion läuft gut, aber dann registry
sehe ich beim Abfragen des durchgehenden Remix:
code: ""
desc: ""
count: 27
recorded: true
Streicher wurden nicht aufgenommen!
Ich habe auch versucht, getData
auf diese Weise zu verwenden:
getData(hash, Web3.fromAscii(code), Web3.fromAscii(desc), count)
und auf diese andere Weise:
getData(hash, Web3.toHex(code), Web3.toHex(desc), count)
aber das Ergebnis ist noch schlimmer:
code: ""
desc: "<long hex string containing both code and desc strings>"
count: 27
recorded: true
Ich kann nicht verstehen, was passiert. Es ist, als wäre web3 nicht in der Lage, die Nutzdaten korrekt zu serialisieren, und als Folge davon kann die intelligente Vertragsschnittstelle nicht die richtige Anzahl von Bytes in die richtigen "Slots" stecken.
Irgendeine Idee?
PSrecord
wenn ich die Methode von Remix aufrufe , mit den gleichen Werten, funktioniert es offensichtlich!
Ich habe das Problem gefunden.
Der Fehler ist tatsächlich das, was ich vermutet hatte: Die Nutzlast wurde nicht korrekt serialisiert und als Folge davon konnte die Smart Contract-Schnittstelle nicht die richtige Anzahl von Bytes in die richtigen "Slots" stecken.
Grund? Mein Fehler...
hash
ist der erste Parameter der record
Methode. Variable ist auch hash
das Ergebnis einer keccak256-JS-Bibliothek, hex-kodiert . Nun, getData()
auf diese Weise verwenden:
contract.record.getData(hash, code, desc, count)
ist total falsch . hash
ist bereits hexadezimal kodiert, aber ohne 0x
Präfix. Erkennt es also getData()
als normalen String und wandelt es wieder in einen anderen Hex-String um. Was das bedeutet? das bedeutet, der neu konvertierte Hex-String passt nicht mehr inbytes32
.
Lösung:0x
Präfix hinzufügen , hash
um anzuzeigen, getData()
dass es sich bereits um eine Hex-Zeichenfolge handelt (d. h. unberührt lassen):
contract.record.getData(`0x${hash}`, code, desc, count)
Außerdem besteht absolut keine Notwendigkeit, für die anderen zwei Strings zu verwenden .fromAscii()
, da getData()
sie als normale Strings erkannt werden, weil sie kein 0x
Präfix haben, und sie daher automatisch in Hex konvertieren.