Ich instanziiere den folgenden Vertrag mit _number
as 10
. Wenn ich den Wert von überprüfe number
, erhalte ich 72370055773322622139731865630429942408293740416025352524660990004945706024960
. Ist das ein Problem mit meinem Vertrag oder handelt es sich um einen Web3-Bug?
contract Thing{
uint public number;
function Thing(bytes32 _number){
number = uint(_number);
}
}
72370055773322622139731865630429942408293740416025352524660990004945706024960
ist 0xa000000000000000000000000000000000000000000000000000000000000000L
- oder 10
in Hex, nach links verschoben. Ohne Ihren web3-Code zu sehen, ist es schwierig zu sagen, warum er auf diese Weise analysiert wurde, aber es scheint wahrscheinlich, dass web3 Ihre Eingabe als Einzelbyte-Byte-String behandelt und linksbündig in das bytes32-Argument eingefügt hat.
Es gibt einige Kuriositäten bei der Verwendung bytes32
als Funktionsparameter.
Von Solidity Features - Byte-Arrays :
PT Grundlegende Unterstützung für Byte-Arrays variabler Länge. Das beinhaltet
- Bytes-Typ für Speichervariablen
- msg.data ist vom Typ Bytes und enthält die Anrufdaten
- Funktionen mit beliebigen Parametern (call, sha3, ...) können mit Bytes-Argumenten aufgerufen werden.
- Kopieren zwischen msg.data und bytes Speichervariablen
Was noch
not
möglich ist:
function parameters of bytes type
- lokale Variablen vom Typ Bytes
- Index- oder Slice-Zugriff
Ich verwende den folgenden Quellcode basierend auf Ihrem Quellcode:
contract ByteToInt {
uint public number;
bytes32 public thebytes32;
function ByteToInt(bytes32 _number) {
thebytes32 = _number;
number = uint(_number);
}
}
Und flachgelegt zu:
var byteToIntSource='contract ByteToInt { uint public number; bytes32 public thebytes32; function ByteToInt(bytes32 _number) { thebytes32 = _number; number = uint(_number); }}'
Lief es ein geth --dev console
:
> var byteToIntSource='contract ByteToInt { uint public number; bytes32 public thebytes32; function ByteToInt(bytes32 _number) { thebytes32 = _number; number = uint(_number); }}'
undefined
Kompiliert es:
> var byteToIntCompiled = web3.eth.compile.solidity(byteToIntSource);
undefined
In die Blockchain eingefügt:
> var byteToIntContract = web3.eth.contract(byteToIntCompiled.ByteToInt.info.abiDefinition);
var byteToInt = byteToIntContract.new(10, {from:web3.eth.accounts[0], data: byteToIntCompiled.ByteToInt.code, gas: 1000000},
function(e, contract) {
if (!e) {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " +
contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
}
)
...
Contract mined! Address: 0x49617e1728c53a3e31ccf21faf6ba344af90f04c
Und die Werte überprüft:
> byteToInt.thebytes32()
"0xa000000000000000000000000000000000000000000000000000000000000000"
> byteToInt.number()
7.237005577332262213973186563042994240829374041602535252466099000494570602496e+76
Ich habe die folgenden Anweisungen in Java ausgeführt:
BigInteger num = new BigInteger("a000000000000000000000000000000000000000000000000000000000000000", 16);
System.out.println(num.toString(10));
Und die Ergebnisse sind:
72370055773322622139731865630429942408293740416025352524660990004945706024960
Wird also 10
als erstes Byte in Ihrer bytes32-Variablen codiert, und die uint(...)
Umwandlung konvertiert die gesamten bytes32-Daten in eine uint
.
Als ich überprüfte, wie web3 die Dezimalwerte in die Parameter umwandelt, habe ich versucht, 0xabc
in den Konstruktor einzusenden, indem ich das dezimale Äquivalent von verwendete 2748
:
var byteToInt = byteToIntContract.new(2748, {from:web3.eth.accounts[0], data: byteToIntCompiled.ByteToInt.code, gas: 1000000},
function(e, contract) {
if (!e) {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " +
contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
}
)
...
Contract mined! Address: 0xb086848ed791c87a6659ed17fb6fd85e37aae97b
...
> byteToInt.thebytes32()
"0xabc0000000000000000000000000000000000000000000000000000000000000"
> byteToInt.number()
7.7684731744176002203118424512664641303902811977827214350690781458433906311168e+76
Probieren Sie Folgendes aus:
var byteToInt = byteToIntContract.new(0x0000000000000000000000000000000000000000000000000000000000000abc, {from:web3.eth.accounts[0], data: byteToIntCompiled.ByteToInt.code, gas: 1000000},
function(e, contract) {
if (!e) {
if (!contract.address) {
console.log("Contract transaction send: TransactionHash: " +
contract.transactionHash + " waiting to be mined...");
} else {
console.log("Contract mined! Address: " + contract.address);
console.log(contract);
}
}
}
)
...
> byteToInt.thebytes32()
"0xabc0000000000000000000000000000000000000000000000000000000000000"
Nick Johnson
AF