El método de contrato funciona solo con direcciones de contrato y no con direcciones de cuenta regulares

He escrito un contrato de token simple para fines de prueba:

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;
    }
}

Cada vez que llamo al creditmétodo en el contrato y paso la dirección de otro contrato como parámetro, todo funciona como se esperaba:

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

El estado de la transacción es 0x1.

El saldo se actualiza:

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

Pero cuando paso la dirección de una cuenta ethereum normal como parámetro, la transacción se extrae, pero no pasa nada.

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

El estado de la transacción es 0x0.

El saldo no cambia:

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

Al comparar los objetos de transacción firmados resultantes, la única diferencia aparte del datacampo es que el vvalor de la firma es siempre 0cuando la transacción falla y 1cuando la transacción es exitosa. Pero no estoy seguro de lo que eso significa.


Actualizar:

Parece que ni siquiera es contrato vs no contrato, es solo que algunas direcciones no funcionan.

Por ejemplo, esto funciona:

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

Esto no:

token.methods.credit('0xc4beccd2ebdb32203800dfbc60ff0dd7c2762b48', 500000000000000000).send({from: accounts[0], gas: "0xB3E4", gasPrice: "0x4A817C800", value: "0x"})
Una posible causa es que su gasolina no sea suficiente para cubrir su transacción. Una transacción será más barata si el destinatario tiene un saldo distinto de cero.
Ese es exactamente el problema, no tomé en cuenta el hecho de que si una cuenta aún no tiene un saldo, costará más gasolina crear el mapeo de saldo para esa cuenta. Y entonces me estaba quedando sin gasolina cuando llamé al método con nuevas direcciones.

Respuestas (2)

Lo más probable es que el problema esté en el límite de gas. ¿Cómo lo calculaste?

Cuando la transacción tiene algunos datos adjuntos, por ejemplo, el selector de método y los parámetros del contrato, los bytes cero cuestan menos que los distintos de cero. Por lo tanto, la transacción que envía tokens a 0x0011223344556677889900112233445566778899costará menos que la transacción que envía la misma cantidad de tokens a 0x112233445566778899aa112233445566778899aa. Además, cambiar el valor en el almacenamiento de cero a distinto de cero cuesta más que cambiarlo de distinto a cero. Entonces balanceOf[to] += amount;cuesta menos si tola dirección ya tiene algunos tokens.

  1. está enviando de la cuenta [0] a la cuenta [0], por lo que el saldo permanece igual
  2. si el saldo de (cuentas[0]) es cero, como muestra en su segunda llamada, entonces la llamada de transferencia fallará debido a require(balanceOf[msg.sender] >= cantidad)
Lo siento, escribí mal el título de la pregunta, estaba hablando de la creditfunción que acuña nuevos tokens.