¿Cómo manipular datos en un contrato inteligente de Solidity?

Tengo un contrato inteligente con algunos miembros que debería modificarse en ciertos eventos. Para simplificar, imaginemos que tenemos un contrato de bienvenida.

Si llamo greeter.greet()a la consola de JavaScript, responde con algo como Hello World. Pero, ¿y si quiero contar la cantidad de saludos y almacenarlos dentro del contrato?

Mi primer intento fue el siguiente:

contract greeter
{
  string greeting;
  uint calls;

  function greeter ( string _greeting ) public
  {
    greeting = _greeting;
    calls = 0;
  }

  function greet ( ) constant returns ( string )
  {
    calls = calls + 1; // does not work
    return greeting;
  }
}

No se actualizó la variable llamadas. Mi primera conjetura es que necesito crear de alguna manera una transacción para pagar el gas. Yo solía web3.jsimplementar el contrato. ¿Debo usar web3 también para llamar greet()con una transacción?

¿O podría financiar la cuenta del contrato con algo de Ether para permitir que el contrato pague su propia gasolina? ¿Cómo manipular datos en un contrato inteligente de Solidity?

Todavía no he mirado web3.js, pero tengo curiosidad por saber cómo usted, como escribió, implementó su contrato con él. ¿Podría indicarme más detalles?
@hcvst puede seguir mis pequeños pasos implementando con web3js en github .

Respuestas (2)

Debido a que su greet()función está marcada constant, web3 por defecto simula la llamada y devuelve el valor, pero no se envía ninguna transacción y, por lo tanto, no se retienen los cambios de estado. Este comportamiento se puede forzar en métodos no constantes usando contract.method.call().

Para llamar a la función de una manera que envíe una transacción y actualice la cadena, use greeter.greet.sendTransaction({from:eth.coinbase, gas:100000}).

Desafortunadamente, mientras que otros contratos recibirán el valor de retorno adecuado, web3 devolverá un hash de transacción, en lugar de un valor de retorno. En este caso, tiene sentido usar Eventos .

Por ejemplo, la solidez sería algo como:

contract greeter { 
    string greeting; 
    uint calls; 
    event Greet (string greeting);
    function greeter ( string _greeting ) public { 
        greeting = _greeting; 
        calls = 0; 
     }
     function greet ( ) public returns ( string ) { 
         calls = calls + 1; 
         Greet(greeting);
          return greeting; 
     } 
 }

Y para obtener un valor de retorno:

 greeter.greet.sendTransaction(
    {from:eth.coinbase, gas:100000},

    function (error, result){ 
    var event = greeter.Greet()
    event.watch(
        function(error, result){ 
             if (!error) console.log(result.args.greeting); 
         }
    );
)
Votado a favor, buen punto sobre el valor de retorno; edité mi respuesta para referirme a la suya para web3js y eventos, y mencioné brevemente el caso de contrato a contrato.
Creo que quieres eliminar la "constante" en saludar ()? Además, "resultado.saludo" podría no ser preciso. IIRC puede necesitar algo como "result.args.greeting".
@eth Gracias, me olvidé por completo de la constante, y result.args.greetinges correcta.

El problema es que greetes una constantfunción, por lo que no se permiten cambios de estado. Cambiar el valor de algo almacenado sería un cambio de estado.

Solución: quitar constant.

Sí, debe usar web3 sendTransactioncuando desee un cambio de estado. sendTransactiones el valor predeterminado para funciones no constantes, pero no se usó porque constantse especificó. Tenga en cuenta que solo se podrá acceder al valor de retorno desde otro contrato : con las transacciones web3js, se deberán usar los eventos para obtener el valor de retorno, como respondió Tjaden Hess .

Más de las preguntas frecuentes :

¿Cuál es la diferencia entre una función marcada como constante y una que no lo es?

constantLas funciones pueden realizar alguna acción y devolver un valor, pero no pueden cambiar de estado (esto aún no lo aplica el compilador). En otras palabras, una función constante no puede guardar ni actualizar ninguna variable dentro del contrato o de una cadena de bloques más amplia. Estas funciones se llaman c.someFunction(...)desde geth o cualquier otro entorno web3.js.

Las funciones "no constantes" (aquellas que carecen del especificador constante) deben llamarse con c.someMethod.sendTransaction({from:eth.accounts[x], gas: 1000000});Es decir, debido a que pueden cambiar de estado, deben recibir un pago de gas para realizar el trabajo.


Para responder a la pregunta restante, un contrato no puede pagar su propio gas , de la forma en que podría imaginarse con este ejemplo, por lo que financiarlo con Ether no ayuda.