I've been developing a dApp that needs ERC721 tokens. I have three contracts, a base contract, the one to mint tokens and another one for auctions. The inheritance looks like Base > Token > Auctions. In this scenario AFAIK I should be able to access the functions from the Token contract from the Auctions one. When minting new tokens I call a function of Base from Token and the token is minted successfully, I can check the information of the token if I call the contract directly, i.e. from Truffle console
CToken.deployed().then(i => { return.i.ownerOf(0) })
This works after minting obviously but when I try to call that function from the Auctions contract the operation reverts.
truffle(development)> Auctions.deployed().then(i => { return i.__ownerOf.call(0) })
Error: VM Exception while processing transaction: revert
... Whole stacktrace...
Why can't I get this information? It should be noted that if I call the mint
function from another contract (Auctions or Base) I can get this information from those contracts but not from the Token one like if the storage is only for the contracts that called those functions initially. What I'm missing here?
Here are the relevant functions:
Token:
function createStallion(address _sender, string _hash) public payable {
require(stallionsAvailable > 0);
uint256 tokenId = addresses.push(_sender) - 1;
super._mint(_sender, tokenId); // This comes from OpenZeppelin.
super.buyStallion(_hash);
stallionsAvailable -= 1;
}
function ownerOf(uint256 _tokenId) public view returns(address) {
return super.ownerOf(_tokenId);
}
Base
function buyStallion(string _horseHash) internal returns(bool) {
counter += 1;
Horse memory horse;
// ... bunch of horse information
horses.push(horse);
return true;
}
Auctions:
// This function is only for testing since I'm not calling it anywhere yet but it had the same behaviour when I wanted to use it in a `require`
function __ownerOf(uint256 _horseId) public view returns(address) {
return super.ownerOf(_horseId);
}
Best Answer
Implementation
Here is a fully working implementation which demonstrates the inner-contract calling you are requesting. This uses the ERC-721 reference implementation.
Test case
Auction
contract.createStallion
using your own account for the sender and hash.__ownerOf
with an input of0
.Note that
_mint
increateStallion
is calling the internal_mint
function from https://github.com/0xcert/ethereum-erc721/blob/master/src/contracts/tokens/nf-token-enumerable.solDiscussion
Here are few extra notes that might help you with other stuff.
createStallion
, check for reentrant code.horses
,stallionsAvailable
,saleId
, the ERC-721 library (if usingERC721Enumerable
). I have removed some of the duplication. But with a fuller understanding of your implementation you can surely do better.bytes32
if at all possible for your hashes, rather thanstring
.