Access return value of a write function externally?

Not sure what has happened over here with my upgradeable contract, but just now I realized my createToken function, that specifies a return uint256, is… not actually returning that value? At least, not according to oz output:

function createToken(address tokenOwner) public returns (uint256) {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have minter role to mint");
        _tokenIds.increment();

        uint256 newItemId = _tokenIds.current();
        _mint(tokenOwner, newItemId);

        return newItemId;
    }
[20:50:50] [eviljordan@WAT ../Contract]$ npx oz send-tx
? Pick a network development
? Pick an instance Contract at 0x0290FB167208Af455bB137780163b7B7a9a10C16
? Select which function createToken(tokenOwner: address)
? tokenOwner: address: 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0
✓ Transaction successful. Transaction hash: 0xf51a155810709f5e953caaf3114bacd3af564c429ee9e986f9b6ff8cf3389900
Events emitted: 
 - Transfer(0x0000000000000000000000000000000000000000, 0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0, 1)

I was expecting an output of 1. Is this not possible in an upgradeable pattern or have I done something stupid?

1 Like

Hi @EvilJordan,

When we call functions that modify state externally we create a transaction and we don’t get the return value from the function, we get the transaction hash.

If you want to get information offchain from your smart contract you can emit events.

MAKES SENSE.
So, to “read” that value, I need to create an event listener, match it with the returned txID, and then investigate the Transfer topic to find the newItemId.

And, to be clear, this only applies to the Upgradeable paradigm… it did work in the “normal” version, right? I’m not mis-remembering?

1 Like

Hi @EvilJordan,

Yes, you need to listen for events.


This is for all write functions (that change state) regardless of whether they are for a proxy/upgradeable contract or not.

1 Like

This is for all write functions (that change state) regardless of whether they are for a proxy/upgradeable contract or not.

What about this?: https://docs.openzeppelin.com/contracts/3.x/erc721#constructing_an_erc721_token_contract

1 Like

Hi @EvilJordan,

The documentation on ERC721 has pseudo code.

The awardItem actually looks like this:

$ npx oz send-tx
? Pick a network development
? Pick an instance GameItem at 0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab
? Select which function awardItem(player: address, tokenURI: string)
? player: address: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1
? tokenURI: string: https://example.com/gameitem/7
✓ Transaction successful. Transaction hash: 0x45be90913170ff3d384e13969ef91a9213561e0f8a68251d57882ef7bb407cbe
Events emitted:
 - Transfer(0x0000000000000000000000000000000000000000, 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1, 1)

If the documentation is causing confusion I can update.

1 Like

I guess I totally hallucinated trying it myself :upside_down_face:

I mean, now that I know and understand, it makes sense, but I think it’s worth calling out in those examples that one can’t actually get the return value from a transactional function (because, duh, it’s being MINED).

Thanks for your patience!

1 Like

Hi @EvilJordan,

I have created an issue to update the documentation: https://github.com/OpenZeppelin/openzeppelin-contracts/issues/2272

1 Like

1 Like

I :heart: Bill Murray in Stripes.