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.js
implementar 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?
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);
}
);
)
result.args.greeting
es correcta.El problema es que greet
es una constant
funció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 sendTransaction
cuando desee un cambio de estado. sendTransaction
es el valor predeterminado para funciones no constantes, pero no se usó porque constant
se 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?
constant
Las 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 llamanc.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.
hcvst
q9f