Метод контракта работает только с контрактными адресами, а не с обычными адресами счетов.

Я написал простой контракт токена для целей тестирования:

pragma solidity ^0.4.18;

contract TestToken {
    uint public totalSupply;

    mapping(address => uint) public balanceOf;

    function transfer(address to, uint amount) public returns (bool) {
        require(balanceOf[msg.sender] >= amount);
        balanceOf[msg.sender] -= amount;
        balanceOf[to] += amount;
        return true;
    }

    function credit(address to, uint amount) public {
        balanceOf[to] += amount;
        totalSupply += amount;
    }

    function debit(address from, uint amount) public {
        balanceOf[from] -= amount;
        totalSupply -= amount;
    }
}

Всякий раз, когда я вызываю creditметод для контракта и передаю адрес другого контракта в качестве параметра, все работает так, как ожидалось:

token.methods.credit(wallet._address, 500000).send({from: accounts[0], gas: "0xB3E4", gasPrice: "0x4A817C800", value: "0x"})

Статус сделки такой 0x1.

Баланс обновляется:

token.methods.balanceOf(wallet._address).call()
'500000'

Но когда я передаю в качестве параметра адрес обычной учетной записи ethereum, транзакция майнится, но ничего не происходит.

token.methods.credit(accounts[0], 500000).send({from: accounts[0], gas: "0xB3E4", gasPrice: "0x4A817C800", value: "0x"})

Статус сделки такой 0x0.

Баланс не меняется:

token.methods.balanceOf(accounts[0]).call()
'0'

При сравнении результирующих объектов подписанных транзакций единственное различие, кроме поля, dataзаключается в том, что значение подписи vвсегда 0при сбое транзакции и 1при успешном выполнении транзакции. Но я не уверен, что это значит.


Обновлять:

Похоже, это даже не контракт против неконтракта, просто некоторые адреса не работают.

Например, это работает:

token.methods.credit('0xd2d0aD819B2679FBDD5C75F93fa13242bfd7E2A5', 500000000000000000).send({from: accounts[0], gas: "0xB3E4", gasPrice: "0x4A817C800", value: "0x"})

Это не:

token.methods.credit('0xc4beccd2ebdb32203800dfbc60ff0dd7c2762b48', 500000000000000000).send({from: accounts[0], gas: "0xB3E4", gasPrice: "0x4A817C800", value: "0x"})
Одна из возможных причин заключается в том, что вашего газа недостаточно для покрытия вашей транзакции. Транзакция будет дешевле, если у получателя ненулевой баланс.
Это именно то, в чем была проблема, я не учел тот факт, что если у учетной записи еще нет баланса, создание сопоставления баланса для этой учетной записи будет стоить больше газа. И поэтому у меня заканчивался бензин при вызове метода с новыми адресами.

Ответы (2)

Проблема скорее всего в лимите газа. Как вы его рассчитали?

Когда к транзакции присоединены некоторые данные, например, селектор метода контракта и параметры, нулевые байты стоят меньше, чем ненулевые. Таким образом, транзакция, которая отправляет токены, 0x0011223344556677889900112233445566778899будет стоить меньше, чем транзакция, которая отправляет такое же количество токенов на 0x112233445566778899aa112233445566778899aa. Кроме того, изменение значения в хранилище с нуля на ненулевое стоит дороже, чем изменение его с ненулевого на ненулевое. Так что balanceOf[to] += amount;стоит меньше, если toв адресе уже есть токены.

  1. вы отправляете со счета [0] на счет [0], поэтому баланс остается прежним
  2. если баланс (accounts[0]) равен нулю, как вы показываете во втором вызове, то вызов передачи завершится ошибкой из-за require(balanceOf[msg.sender] >= сумма)
Извините, я опечатался в названии вопроса, я говорил о creditфункции, которая чеканит новые токены.