Empecé a escribir un contrato inteligente para un registro de regalos.
Cuando escribo pruebas usando Truffle Framework, obtengo valores de retorno inesperados.
Por ejemplo, al llamar a la función offerGift desde dentro de la prueba, devuelve un objeto tx en lugar de la identificación.
Si uso offerGift.call(...) devuelve la identificación, pero cuando llamo a getGift, no se puede encontrar el regalo y aparece el error.
Error: error devuelto: excepción de máquina virtual al procesar la transacción: revertir el regalo no encontrado
Probé las respuestas proporcionadas en Returns TX Object en lugar de dar como resultado la prueba Truffle , pero no funcionaron para mí.
Uso de
Truffle v5.0.18 (núcleo: 5.0.18)
Solidity v0.5.0 (solc-js)
Node v10.15.3
Web3.js v1.0.0-beta.37
Ganache v1.3.1
truffle-assertions 0.9.0
¿Qué estoy haciendo mal?
El Código de Contrato
pragma solidity >=0.4.21 <0.6.0;
contract GiftRegistry {
uint256 idCounter = 0;
enum GiftStatus { Offered }
struct Gift {
string description;
uint256 value;
GiftStatus status;
address giftGiver;
address giftReceiver;
address giftApprover;
}
mapping(uint256 => Gift) public giftMap;
function doesGiftExist(uint256 _giftId) private view returns(bool){
Gift memory gift = giftMap[_giftId];
bytes memory giftAsBytes = bytes(gift.description);
return giftAsBytes.length > 0;
}
function getGift(uint256 _giftId) public view returns(string memory, uint256, GiftStatus, address, address, address){
require(doesGiftExist(_giftId), 'Gift not found');
Gift memory gift = giftMap[_giftId];
return (
gift.description,
gift.value,
gift.status,
gift.giftGiver,
gift.giftReceiver,
gift.giftApprover
);
}
function offerGift(string memory _description, uint256 _value, address _giftReceiver) public returns(uint256) {
uint256 currentId = idCounter;
giftMap[currentId] = Gift(_description, _value, GiftStatus.Offered, msg.sender, _giftReceiver, address(0));
idCounter = idCounter + 1;
return currentId;
}
}
La prueba de la trufa
const GiftRegistry = artifacts.require('GiftRegistry');
const truffleAssert = require('truffle-assertions');
contract('The Gift Registry contract', accounts => {
let contract;
const giftGiverAddress = accounts[1];
const giftReceiverAddress = accounts[2];
beforeEach(async () => {
contract = await GiftRegistry.new({from: accounts[0]});
});
describe('given offerGift is called', () => {
const OfferedStatus = 0;
it('the status should be set to offered', async () => {
const fiveDollars = 500;
// Calling like this returns a tx instead of the id, the gift can be found with a hard coded index of 0
const giftId1 = await contract.offerGift('coffee', fiveDollars, giftReceiverAddress, {from: giftGiverAddress});
// This call returns the new giftId, however the gift can't be found and the call to getGift throws the error
// Error: Returned error: VM Exception while processing transaction: revert Gift not found
const giftId2 = await contract.offerGift.call('coffee', fiveDollars, giftReceiverAddress, {from: giftGiverAddress});
const gift = await contract.getGift.call(0);
assert.equal(OfferedStatus, gift[2]);
});
});
});
.call()
finge hacer la transacción y le da el resultado, pero no vuelve a enviar ningún cambio a la cadena de bloques.
Puede encontrar más detalles en Truffle docs pero básicamente dirá que
Cuando ejecuta una función de contrato a través de una llamada, recibirá el valor de retorno inmediatamente
Ejecutar getGift
después offerGift.call(...)
no funcionará porque idCounter
no se actualizó.
Tienes que hacerlo contract.offerGift('coffee', fiveDollars, giftReceiverAddress, {from: giftGiverAddress});
y obtendrás el objeto tx. Luego, debe verificar si se extrajo y luego obtener el registro y, del evento de registro, obtener la identificación del regalo que esperaba. No obtendrá el valor de retorno.
contract.idCounter({from: giftGiverAddress})
buena vibración
pure
sea oview
) devuelve el hash de la transacción cuando se ejecuta fuera de la cadena (es decir, por una cuenta de propiedad externa). Tal función debe devolver algo solo si está destinado a ser ejecutado desde la cadena (es decir, por este contrato o por algún otro contrato). Cuando se les llama desde fuera de la cadena, siempre devolverán el hash de la transacción (incluso si no están declarados para devolver nada). Entonces, a menos que tenga la intención de llamarlo desde la cadena, no tiene sentido que esta función devuelva nada.lukemccarthy
buena vibración
getGift
con su pregunta y qué quiere decir con "mismo resultado"? ¿El mismo resultado que qué?