I have started writing a smart contract for a gift registry.
When I write tests using the Truffle Framework I get unexpected return values.
For example, when calling the offerGift function from within the test it returns a tx object instead of the id.
If I use offerGift.call(...) it returns the id but when I call getGift the gift can't be found, and I get the error
Error: Returned error: VM Exception while processing transaction: revert Gift not found
I have tried the answers provided in Returns TX Object instead result in Truffle test but they didn't work for me.
Using
Truffle v5.0.18 (core: 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
What am I doing wrong?
The Contract Code
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;
}
}
The Truffle Test
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]);
});
});
});
pure
orview
) function returns the hash of the transaction when executed from the off-chain (i.e., by an externally-owned account). Such function should return something only if meant to be executed from the on-chain (i.e., by this contract or by some other contract). When called from the off-chain, they will always return the hash of the transaction (even if they are not declared to return anything). So unless you intend to call it from the on-chain, there is no point for this function to return anything.getGift
has anything to do with your question, and what do you mean by "same result"? Same result as what?