Bytes32-zu-uint-Konvertierung ist falsch

Ich instanziiere den folgenden Vertrag mit _numberas 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);
  }
}
Können Sie den web3-Code einfügen, den Sie zum Instanziieren verwenden?

Antworten (2)

72370055773322622139731865630429942408293740416025352524660990004945706024960ist 0xa000000000000000000000000000000000000000000000000000000000000000L- oder 10in 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.

Zusammenfassung

Es gibt einige Kuriositäten bei der Verwendung bytes32als 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 notmöglich ist:

  • function parameters of bytes type
  • lokale Variablen vom Typ Bytes
  • Index- oder Slice-Zugriff


Einzelheiten

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 10als 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, 0xabcin 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"