преобразование bytes32 в uint неверно

Я создаю следующий контракт с _numberas 10. Когда я проверяю значение number, я получаю 72370055773322622139731865630429942408293740416025352524660990004945706024960. Это проблема с моим контрактом или это ошибка web3?

contract Thing{
  uint public number;
  function Thing(bytes32 _number){
    number = uint(_number);
  }
}
Можете ли вы включить код web3, который вы используете для его создания?
@NickJohnson Я использую надежность браузера chriseth.github.io/browser-solidity/#version=soljson-latest.js

Ответы (2)

72370055773322622139731865630429942408293740416025352524660990004945706024960is 0xa000000000000000000000000000000000000000000000000000000000000000L- или 10в шестнадцатеричном формате со сдвигом влево. Не видя ваш код web3, трудно сказать, почему он был проанализирован таким образом, но вполне вероятно, что web3 обработал ваш ввод как однобайтовую байтовую строку и выровнял ее по левому краю в аргументе bytes32.

Резюме

Есть некоторые странности при использовании bytes32в качестве параметров функции.

Из возможностей Solidity — массивы байтов :

PT Базовая поддержка массивов байтов переменной длины. Это включает

  • тип байтов для хранения переменных
  • msg.data имеет тип bytes и содержит данные вызова
  • функции с произвольными параметрами (call, sha3, ...) могут вызываться с байтовыми аргументами.
  • копирование между переменными хранения msg.data и bytes

Что еще notвозможно:

  • function parameters of bytes type
  • локальные переменные типа bytes
  • доступ к индексу или срезу


Подробности

Я использую следующий исходный код на основе вашего исходного кода:

contract ByteToInt {
    uint public number;
    bytes32 public thebytes32;

    function ByteToInt(bytes32 _number) {
        thebytes32 = _number;
        number = uint(_number);
    }
}

И сгладил его до:

var byteToIntSource='contract ByteToInt { uint public number; bytes32 public thebytes32;  function ByteToInt(bytes32 _number) { thebytes32 = _number; number = uint(_number); }}'

Запустил в geth --dev console:

> var byteToIntSource='contract ByteToInt { uint public number; bytes32 public thebytes32;  function ByteToInt(bytes32 _number) { thebytes32 = _number; number = uint(_number); }}'
undefined

Скомпилировал это:

> var byteToIntCompiled = web3.eth.compile.solidity(byteToIntSource);
undefined

Вставил его в блокчейн:

> 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

И проверил значения:

> byteToInt.thebytes32()
"0xa000000000000000000000000000000000000000000000000000000000000000"

> byteToInt.number()
7.237005577332262213973186563042994240829374041602535252466099000494570602496e+76

Я выполнил следующие операторы в Java:

BigInteger num = new BigInteger("a000000000000000000000000000000000000000000000000000000000000000", 16);
System.out.println(num.toString(10));

И результаты таковы:

72370055773322622139731865630429942408293740416025352524660990004945706024960

Итак 10, кодируется как первый байт в вашей переменной bytes32, а uint(...)приведение преобразует все данные bytes32 в файл uint.


Проверяя, как web3 преобразует десятичные значения в параметры, я попытался отправить в 0xabcконструктор, используя десятичный эквивалент 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

Попробуйте следующее:

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"