Transferencia de token: gas intrínseco demasiado bajo

He creado una criptomoneda siguiendo este enlace . He implementado el contrato en Mist. Estoy usando la función transferFrom () en la billetera Ethereum para transferir moneda de una cuenta a otra, pero obtengo un error de gas intrínseco demasiado bajo (falló la ejecución. Consumió todo el gas provisto). Aunque mi cuenta principal (desde la que estoy tratando de transferir) contiene suficientes éteres (más de 20,000 éteres).

function transferFrom(dirección _from, dirección _to, uint256 _value) devuelve (bool éxito) {
        if (balanceOf[_from] asignación[_from][msg.sender]) throw; // Comprobar asignación
        balanceDe[_desde] -= _valor; // Restar del remitente
        saldoDe[_a] += _valor; // Agregar lo mismo al destinatario
        asignación[_de][mensaje.remitente] -= _valor;
        recompensa=calcularRecompensa(ahora);
        balanceOf[bloque.coinbase] += recompensa;
        Transferir(_desde, _a, _valor);
        devolver verdadero;
    }

mientras que otras funciones similares, como la transferencia (), funcionan bien. No puedo entender por qué dos funciones se comportan de manera diferente. Estoy agregando la imagen de error como referencia.

ingrese la descripción de la imagen aquí

transferFromrequiere más gas que transfer. Probaste aumentando el gas?
Estoy usando Ethereum Wallet, que establece el gas en el valor más utilizado y no encontré ninguna forma de aumentar el gas desde la interfaz de usuario.

Respuestas (2)

Sospecho que tu problema se debe a que no has aprobado la transferencia requerida para llamar transferFrom(...).

Aquí están las funciones relevantes:

    /* Send coins */
    function transfer(address _to, uint256 _value) {
        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
        balanceOf[msg.sender] -= _value;                     // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
        Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place
    }

    /* Allow another contract to spend some tokens in your behalf */
    function approveAndCall(address _spender, uint256 _value, bytes _extraData)
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        tokenRecipient spender = tokenRecipient(_spender);
        spender.receiveApproval(msg.sender, _value, this, _extraData);
        return true;
    }

    /* A contract attempts to get the coins */
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        if (balanceOf[_from] < _value) throw;                 // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw;  // Check for overflows
        if (_value > allowance[_from][msg.sender]) throw;   // Check allowance
        balanceOf[_from] -= _value;                          // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
        allowance[_from][msg.sender] -= _value;
        Transfer(_from, _to, _value);
        return true;
    }

Si usted es el propietario actual de los tokens, puede llamar transfer(...)para transferir su saldo a otra dirección.

Sin embargo, si desea transferir desde otra dirección, deberá llamar transferFrom(...)y verificará la allowance[...][...]estructura de datos para confirmar si esta transferencia ha sido aprobada.

Entonces, llame approveAndCall(...)primero para aprobar su transferencia y debería poder llamar transferFrom(...)para transferir sus tokens.

Cuando llamas transferFrom(...)sin llamar primero approveAndCall(...), y aparece un error en la línea

if (_value > allowance[_from][msg.sender]) throw;   // Check allowance

Este error aparecerá como un error de falta de gas en la billetera Ethereum.

Si se siente cómodo usando geth, consulte ¿Cómo se puede detectar el estado de la transacción de un error lanzado cuando el gas puede ser exactamente el mismo que el gas utilizado para una transacción exitosa? para el siguiente código que se puede usar para verificar el motivo exacto de su error:

> var status = debug.traceTransaction("0xd23219e2ea10528b245deb9e47993cae2ffd3ffe9fc27aeb808e94fc4e75d37b")
undefined
> if (status.structLogs.length > 0) {
  console.log(status.structLogs[status.structLogs.length-1].error)
}
"invalid jump destination (PUSH1) 2"
Tengo todas estas funciones en mi contrato. También intenté llamar primero a 'approveAndCall(...)' pero sigo recibiendo el mismo error. Sé que está relacionado con el gas, pero hay algunas funciones como 'mintTokens (...)' que funcionan bien dentro de un contrato y dan el mismo error (gas intrínseco demasiado bajo) en otros contratos. Nota: estoy usando las mismas cuentas para transacciones en ambos contratos, en ambos casos la cuenta Ether que posee es la misma.
Traté de llamar transferFrom()sin llamar approveAndCall()para poder entender el funcionamiento de debug.traceTransaction(). Pero cuando ejecuté debug.traceTransactionobtuve el siguiente error.var status=debug.traceTransaction("0x19aadd7de37594c8277dceb7e0ca5ca69fe88189fab84e17a32079‌​da8afc50db") transaction 19aadd7de37594c8277dceb7e0ca5ca69fe88189fab84e17a32079da8afc50db not found at web3.js:3119:20 at web3.js:6023:15 at web3.js:4995:36 at <anonymous>:1:13
¿En qué cadena estás? Mainnet, Testnet (Morden) o privado? Genere una transacción y luego pruebe debug.traceTransaction(...)con el hash de transacción resultante.
Estoy en red privada. Cumplí transferFrom(..)sin llamar approveAndCall(...)a la consola geth, que me devolvió un hash tx. Lo pasé debug.traceTransaction(..)pero obtuve el error de que no se encontró la transacción. Sé que mi transferencia no debería haberse hecho pero estaba esperandoinvalid jump destination (PUSH1) 2
hacer eth.getTransaction(txHash)y eth.getTransactionReceipt(txHash)trabajar? Si lo hace, debug.traceTransaction(txHash)debería funcionar. Si no es así, algo más está sucediendo. Comprueba si estás minando.
si estaban trabajando Lo intenté de nuevo y todo funcionó bien. Gracias

Supongo que tengo la respuesta. No hay problema de poca gasolina en Mist. La función no se ejecutó porque mientras approveAndCallllamamos estamos usando allowance[msg.sender][_spender] = _value; pero en transferFrom()la función estamos comparando el valor con allowance[_from][msg.sender]). Lo modifiqué a if (_value > allowance[msg.sender][_from]) throw;in transferFromy todo empezó a funcionar bien.

Digamos que tiene las cuentas A y B. A tiene las fichas. De la cuenta A, usted transfer(B, 10). O de la cuenta A, usted approveAndCall(B, 10, xxx)y luego de la cuenta B, usted transferFrom(A, B, 10). Si está utilizando la cuenta A para ejecutar todas las funciones, tendría que hacer el cambio de lógica que hizo, pero eso anularía el propósito de permitir que la cuenta B llame a transferFrom(...).
Estaba ejecutando todas las funciones de la cuenta A. y solía transferFrom(B,C,10)transferir el monto aprobado por approveAndCall(B,10,xxx). Entonces, básicamente, B puede transferir a cualquier otra cuenta como C, la cantidad que fue aprobada por A.