Estoy tratando de probar mis contratos usando la suite Truffle, junto con Ganache.
Hasta ahora, he estado probando funciones de contrato que están restringidas a view
solo. Ahora, cuando intento hacer cambios en el estado del contrato, descubro que el estado en realidad no se cambia entre llamadas a funciones.
Considere el siguiente contrato simple:
pragma solidity ^0.4.24;
import "../OrderBook.sol";
contract IdManager {
uint256 newId;
function addId() public returns (uint256) {
newId++;
return newId;
}
}
Todo lo que deseo hacer es incrementar newId
y devolver su nuevo valor.
El código que he escrito para probar esto es:
const { getWeb3, getContractInstance, parseSignature } = require("./test_helper");
const web3 = getWeb3();
const getInstance = getContractInstance(web3);
contract('IdManager', (accounts) => {
let IdManager = getInstance('IdManager');
it('test addId()', async () => {
console.log(await IdManager.methods.addId().call());
console.log(await IdManager.methods.addId().call());
console.log(await IdManager.methods.addId().call());
});
});
La getInstance()
llamada está utilizando Web3 v1.0
, según este tutorial .
Con la prueba anterior, esperaría que el resultado fuera:
1
2
3
Pero, en realidad obtengo:
1
1
1
¿Alguien se ha encontrado con este problema antes?
Editar0:
console.log(await IdManager.methods.newId().call());
debería haber sido console.log(await IdManager.methods.addId().call());
— newId()
es ahora addId()
.
Edit1:
Siguiendo el consejo de goodvibration, he modificado el contrato de ejemplo para que sea el siguiente:
contract IdManager {
uint256 public newId;
function addId() public {
newId++;
}
function getId() public view returns (uint256) {
return newId;
}
}
El código de prueba ha sido modificado a lo siguiente:
it('test addId()', async () => {
await IdManager.methods.addId().call();
console.log(await IdManager.methods.getId().call());
await IdManager.methods.addId().call();
console.log(await IdManager.methods.getId().call());
await IdManager.methods.addId().call();
console.log(await IdManager.methods.getId().call());
});
Desafortunadamente, mi salida aún muestra que el estado no se conserva:
0
0
0
Una solución simple a esto estaba justo debajo de mis narices. Obviamente, solo tenía que leer la documentación que me dieron.
Tenga en cuenta que la llamada no puede alterar el estado del contrato inteligente .
Tenga en cuenta que esto puede alterar el estado del contrato inteligente .
Entonces, la alteración del último paso del código de prueba en mi pregunta es la siguiente:
it('test addId()', async () => {
await IdManager.methods.addId().send({from: accounts[0]});
console.log(await IdManager.methods.getId().call());
await IdManager.methods.addId().send({from: accounts[0]});
console.log(await IdManager.methods.getId().call());
await IdManager.methods.addId().send({from: accounts[0]});
console.log(await IdManager.methods.getId().call());
});
Lo que da como resultado mi resultado deseado:
1
2
3
Función addId
es una función no constante (es decir, no declarada como pure
o view
).
Como tal, su valor de retorno solo puede ser utilizado en la cadena, es decir, por otras funciones (en el mismo contrato o en otros contratos) que lo llamen.
Cuando llama a dicha función desde fuera de la cadena, se ejecuta una transacción en la cadena y lo que obtiene a cambio es un recibo de esa transacción.
Si desea obtener el valor de devolución real, debe incluirlo emit
en un correo electrónico event
, que luego podrá extraer del recibo.
Por ejemplo:
event Event(uint256 val);
function addId() public returns (uint256) {
newId++;
emit Event(newId);
return newId;
}
Alternativamente, dado que en su caso específico está devolviendo el valor de una variable global (de estado), puede declararla public
y luego simplemente leerla del contrato usando su función de obtención (implícita):
console.log(await IdManager.methods.newId().call());
Web3
y remix
! Pero modifiqué mi código de prueba para recuperar el miembro Id
a través de una llamada de función separada. Todavía no veo un cambio de estado entre llamadas.A partir de diciembre de 2021, Truffle cambió la forma en que se debe llamar el contrato. Esta pregunta es extremadamente importante para alguien tan distraído como yo, así que aquí hay una prueba de muestra para el contrato de Edit1
const idmanager= artifacts.require("IdManager");
contract('IdManager', async accounts => {
it('test addId()', async () => {
const instance = idmanager.deployed();
await instance.addId({from: account[0]});
const actual = await instance.getId.call({from: account[0]});
assert.equal(actual, 1);
});
});
buena vibración
addId
a ninguna parte en tu prueba!!!!!craig
newId()
debería haber sidoaddId()
. Disculpas.buena vibración
OrderBook
??? ¿Es posible que ese sea el antiguo contrato con el que intentabas realizar esta prueba?craig