Assignment - Get Kitty

Hello @thecil - Please help!!!
I keep getting this error msg when I try to compile, lmk how to best fix this error. Thanks a million!

truffle(develop)> instance.getKitty(0)
Thrown:
Error: Returned values aren't valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced.
    at evalmachine.<anonymous>:0:10
    at sigintHandlersWrap (vm.js:276:15)
    at Script.runInContext (vm.js:131:14)
    at runScript (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:364:1)
    at Console.interpret (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:379:1)
    at bound (domain.js:415:14)
    at REPLServer.runBound [as eval] (domain.js:428:12)
    at REPLServer.onLine (repl.js:665:10)
    at REPLServer.emit (events.js:196:13)
    at REPLServer.EventEmitter.emit (domain.js:471:20)
    at REPLServer.Interface._onLine (readline.js:314:10)
    at REPLServer.Interface._line (readline.js:691:8)
    at REPLServer.Interface._ttyWrite (readline.js:1011:14)
    at REPLServer.self._ttyWrite (repl.js:742:7) {
  hijackedStack: "Error: Returned values aren't valid, did it run Out of Gas? You might " +
    'also see this error if you are not using the correct ABI for the contract ' +
    'you are retrieving data from, requesting data from a block number that ' +
    'does not exist, or querying a node which is not fully synced.\n    at ' +
    'ABICoder.decodeParametersWith ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth-abi/lib/index.js:297:1)\n' +
    '    at ABICoder.decodeParameters ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth-abi/lib/index.js:284:1)\n' +
    '    at Contract._decodeMethodReturn ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-eth-contract/lib/index.js:469:1)\n' +
    '    at Method.outputFormatter ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-eth-contract/lib/index.js:759:1)\n' +
    '    at Method.formatOutput ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-core-method/lib/index.js:146:1)\n' +
    '    at sendTxCallback ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-core-method/lib/index.js:522:1)\n' +
    '    at ' +
    '/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-core-requestmanager/lib/index.js:307:1\n' +
    '    at ' +
    '/usr/local/lib/node_modules/truffle/build/webpack:/packages/provider/wrapper.js:107:1\n' +
    '    at XMLHttpRequest.request.onreadystatechange ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-providers-http/lib/index.js:98:1)\n' +
    '    at XMLHttpRequestEventTarget.dispatchEvent ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:1)\n' +
    '    at ' +
    'XMLHttpRequest.exports.modules.996763.XMLHttpRequest._setReadyState ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:208:1)\n' +
    '    at ' +
    'XMLHttpRequest.exports.modules.996763.XMLHttpRequest._onHttpResponseEnd ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:318:1)\n' +
    '    at IncomingMessage.<anonymous> ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:289:47)\n' +
    '    at IncomingMessage.emit (events.js:201:15)\n    at ' +
    'IncomingMessage.EventEmitter.emit (domain.js:494:23)\n    at endReadableNT ' +
    '(_stream_readable.js:1130:12)'
}
1 Like

TokenId zero (0) does not exist never in erc721 contracts, they always start with tokenId 1.

Carlos Z

2 Likes

Thanks so much Carlos @thecil! I really appreciate your help.

Now I am running into some other issues. Please take a look at both contracts and let me know if it has errors that Iā€™m not seeing.

Ownable.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Ownable {
    address owner;
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _;//run the function
    }
    
      constructor()  {
        owner = msg.sender;
    }
}

Kittycontract.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

import "./IERC721.sol";
import "./Ownable.sol";

contract Kittycontract is IERC721, Ownable {

    uint256 public constant CREATION_LIMIT_GEN0 = 10;
    string public constant name = "KittyCripto";
    string public constant symbol = "KC";

    event Birth(
    address owner, 
    uint256 kittenId,
    uint256 mumId, 
    uint256 dadId, 
    uint256 genes
    );

    struct Kitty {
        uint256 genes;
        uint64 birthTime;
        uint32 mumId;
        uint32 dadId;
        uint16 generation;
    }

   //Arrays of token Ids
   Kitty[] kitties;

    mapping (uint256 => address) public kittyIndexToOwner;
    mapping (address => uint256) ownershipTokenCount;

    uint256 public gen0Counter;

    function createKittyGen0(uint256 _genes) public onlyOwner returns (uint256) {
        require(gen0Counter < CREATION_LIMIT_GEN0);

        gen0Counter++;
        
        return _createKitty(0, 0, 0, _genes, msg.sender);
    }

    function _createKitty(
        uint256 _mumId,
        uint256 _dadId,
        uint256 _generation,
        uint256 _genes,
        address owner 
        
    ) private returns (uint256) {
        Kitty memory _kitty = Kitty({ 
            genes: uint64(_genes),
            birthTime: uint64(block.timestamp),
            mumId: uint32(_mumId),
            dadId: uint32(_dadId),
            generation: uint16(_generation)
        });
     
        kitties.push(_kitty);
        uint256 newKittenId = kitties.length -1; 

        emit Birth(owner, newKittenId, _mumId, _dadId, _genes);
 
        _transfer(address(0), owner, newKittenId);
    
        return newKittenId; 
    }
    function getKitty(uint256 kittyId) public view returns(uint256, uint64, uint32, uint32, uint16) {
        return 
        (
        kitties[kittyId].genes, 
        kitties[kittyId].birthTime, 
        kitties[kittyId].mumId, 
        kitties[kittyId].dadId,
        kitties[kittyId].generation
        );
    }
    function balanceOf(address owner) external  override view returns (uint256 balance) {
    return ownershipTokenCount[owner];
        
    }

    function totalSupply() external view returns (uint) {
        return kitties.length;
    }
  

    function ownerOf(uint256 _tokenId) external view returns (address)
    {
        return kittyIndexToOwner[_tokenId];
    }

    function transfer(address _to, uint256 _tokenId) external override 
    {

        require (_to != address(0));
        require (_to != address(this));
        require (_owns(msg.sender,_tokenId));

        _transfer(msg.sender, _to, _tokenId);
    }
    function _transfer(address _from, address _to, uint256 _tokenId) internal {
        ownershipTokenCount[_to]++;
    
    kittyIndexToOwner[_tokenId] = _to;

    if (_from != address (0)) {
        ownershipTokenCount[_from]--;
    }

    //Emit the transfer events
    emit Transfer(_from, _to, _tokenId); 

    }

    function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return kittyIndexToOwner[_tokenId] == _claimant;
    }
    
 }

I now get this error message:

truffle(develop)> await instance.createKittyGen0(1001)
{
  tx: '0xe2db058d1f4f102bf991677deb157890a646d8bec866d131105d77ed33c42017',
  receipt: {
    transactionHash: '0xe2db058d1f4f102bf991677deb157890a646d8bec866d131105d77ed33c42017',
    transactionIndex: 0,
    blockHash: '0x621ca9b2086bfaa7265a8de801c11f54852b0568825ff88e6e18108b4c788a05',
    blockNumber: 4,
    from: '0x10b4aa9b0360ad4e1234ed1a359da219098f1bd0',
    to: '0xfdfbbeb69047ac767960f787a2720907587b3fb3',
    gasUsed: 21216,
    cumulativeGasUsed: 21216,
    contractAddress: null,
    logs: [],
    status: true,
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    rawLogs: []
  },
  logs: []
}
truffle(develop)> instance.totalSupply()
Thrown:
Error: Returned values aren't valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced.
    at evalmachine.<anonymous>:0:10
    at sigintHandlersWrap (vm.js:276:15)
    at Script.runInContext (vm.js:131:14)
    at runScript (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:364:1)
    at Console.interpret (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:379:1)
    at bound (domain.js:415:14)
    at REPLServer.runBound [as eval] (domain.js:428:12)
    at REPLServer.onLine (repl.js:665:10)
    at REPLServer.emit (events.js:196:13)
    at REPLServer.EventEmitter.emit (domain.js:471:20)
    at REPLServer.Interface._onLine (readline.js:314:10)
    at REPLServer.Interface._line (readline.js:691:8)
    at REPLServer.Interface._ttyWrite (readline.js:1011:14)
    at REPLServer.self._ttyWrite (repl.js:742:7) {
  hijackedStack: "Error: Returned values aren't valid, did it run Out of Gas? You might " +
    'also see this error if you are not using the correct ABI for the contract ' +
    'you are retrieving data from, requesting data from a block number that ' +
    'does not exist, or querying a node which is not fully synced.\n    at ' +
    'ABICoder.decodeParametersWith ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth-abi/lib/index.js:297:1)\n' +
    '    at ABICoder.decodeParameters ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth-abi/lib/index.js:284:1)\n' +
    '    at Contract._decodeMethodReturn ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-eth-contract/lib/index.js:469:1)\n' +
    '    at Method.outputFormatter ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-eth-contract/lib/index.js:759:1)\n' +
    '    at Method.formatOutput ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-core-method/lib/index.js:146:1)\n' +
    '    at sendTxCallback ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3-eth/node_modules/web3-core-method/lib/index.js:522:1)\n' +
    '    at ' +
    '/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-core-requestmanager/lib/index.js:307:1\n' +
    '    at ' +
    '/usr/local/lib/node_modules/truffle/build/webpack:/packages/provider/wrapper.js:107:1\n' +
    '    at XMLHttpRequest.request.onreadystatechange ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/web3/node_modules/web3-providers-http/lib/index.js:98:1)\n' +
    '    at XMLHttpRequestEventTarget.dispatchEvent ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:1)\n' +
    '    at ' +
    'XMLHttpRequest.exports.modules.996763.XMLHttpRequest._setReadyState ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:208:1)\n' +
    '    at ' +
    'XMLHttpRequest.exports.modules.996763.XMLHttpRequest._onHttpResponseEnd ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:318:1)\n' +
    '    at IncomingMessage.<anonymous> ' +
    '(/usr/local/lib/node_modules/truffle/build/webpack:/node_modules/xhr2-cookies/dist/xml-http-request.js:289:47)\n' +
    '    at IncomingMessage.emit (events.js:201:15)\n    at ' +
    'IncomingMessage.EventEmitter.emit (domain.js:494:23)\n    at endReadableNT ' +
    '(_stream_readable.js:1130:12)'
}
2 Likes

You might also need to use await to trigger this function, await instance.totalSupply(). :nerd_face:

Carlos Z

2 Likes

Awesome! I will give this a try, I am sure Iā€™ll be bugging you again LOL :smile:

2 Likes

This is my create a doggy function

function _createDoggy(
        uint256 _mumId,
        uint256 _dadId,
        uint256 _generation,
        uint256 _genes,
        address _owner
    ) private returns (uint256) {
        Doggy memory _doggy = Doggy({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            mumId: uint32(_mumId),
            dadId: uint32(_dadId),
            generation: uint16(_generation)

        });
        
        doggys.push(_doggy);
        uint256 newDoggyId = doggys.length -1;

        emit Birth(_owner, newDoggyId, _mumId, _dadId, _genes);

        _transfer(address(0), _owner, newDoggyId);

        return newDoggyId;
    }
2 Likes
pragma solidity 0.8.0;
pragma abicoder v2;

import "./IERC721.sol";
import "./Ownable.sol";

contract Kittycontract is IERC721, Ownable {
    
    mapping(address => uint) OwnershipTokenCout;
    mapping(uint => address)  public TokenIdOwner;
    
    uint public constant Gen0SupplyLimit = 10;
    string public constant projectName = "CreativeKitties";
    string public constant projectSymbol = "CK";

    event Birth(address owner, uint kittenId, uint momId, uint dadId, uint genes);

    struct Kitty {
        uint genes;
        uint64 birthTime;
        uint32 momId;
        uint32 dadId;
        uint16 generation;
    }

    Kitty[] kitties;

    uint gen0Counter = 0;

    function getKittyInfo(uint catId) public view returns (Kitty memory, address owner) {
        Kitty storage kitty = kitties[catId];
        return (kitty, TokenIdOwner[catId]);
    }

    function createKittyGen0(uint _genes) public onlyOwner returns (uint) {
        require(gen0Counter < Gen0SupplyLimit, "Gen 0 supply fully minted");
        gen0Counter++;
        return _createKitty(_genes, 0, 0, 0, msg.sender);

    }

    function _createKitty (uint _genes, uint _momId, uint _dadId, uint _generation, address _owner) private returns (uint) {
        Kitty memory _newKitty = Kitty({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            momId: uint32(_momId),
            dadId: uint32(_dadId),
            generation: uint16(_generation)
        });
        kitties.push(_newKitty);
        uint newCatId = kitties.length - 1;

        emit Birth(_owner, newCatId, _momId, _dadId, _genes);

        _transfer(address(0), _owner, newCatId);
       
        return newCatId;
    }

    function balanceOf(address owner) external override view returns (uint256 balance) { 
        return OwnershipTokenCout[owner];
    }

    function totalSupply() external override view  returns (uint256 total) {
        return kitties.length;
    }

    function name() external override view returns (string memory tokenName) {
        return projectName;
    }
  
    function symbol() external override view returns (string memory tokenSymbol) {
        return projectSymbol;
    }

    function ownerOf(uint256 tokenId) external override view returns (address owner) {
        return TokenIdOwner[tokenId];
    }
  
    function transfer(address _to, uint256 _tokenId) external override {
        require(_to != address(0), 'Cant send to 0 address');
        require(_to != address(this), 'Cant send to this contract');
        require(TokenIdOwner[_tokenId] == address(msg.sender), 'You dont own this token'); //make _owns function out of this comparison since it will be used again im sure

        _transfer(msg.sender, _to, _tokenId);
    }

    function _transfer(address _from, address _to, uint _tokenId) internal {
        OwnershipTokenCout[_to] ++;
        TokenIdOwner[_tokenId] = _to;

        if (_from != address(0)){
             OwnershipTokenCout[_from] --;
        }
        
        emit Transfer(_from, _to, _tokenId);
    }

}
2 Likes

KittyContract.sol

pragma solidity ^0.5.0;

import "./Ownable.sol";
import "./IERC721.sol";

contract KittyContract is IERC721, Ownable{

    // Mapping owner address to token count
    mapping(address => uint256) ownershipTokenCount;

    // Mapping from token ID to owner address
    mapping(uint256 => address) public _owners;

    //birth event
    event Birth(address owner, uint256 kittenId, uint256 mumId, uint256 dadId, uint256 genes);

    //stuct of kittens
    struct kitten{
        uint genes;
        uint64 birthTime;
        uint32 momId;
        uint32 dadId;
        uint16 generation;
    }

    //array of kittens for totalSupply function
    kitten[] internal kittens;

    // Token name
    string public constant _name = "Kittycoin";

    // Token symbol
    string public constant _symbol = "KITTY";

    //limit of gen0 kittens
    uint256 public constant CREATION_LIMIT_GEN0 = 10;

    //counts # of gen0 kittens
    uint256 public gen0Counter;

    function createKittyGen0(uint256 _genes) public onlyOwner returns (uint256){
        require(gen0Counter < CREATION_LIMIT_GEN0);

        gen0Counter++;

        return _createKitty(0, 0, 0, _genes, msg.sender);
    }

    function _createKitty(
        uint256 _mumId,
        uint256 _dadId,
        uint256 _generation,
        uint256 _genes,
        address _owner
    ) private returns (uint256) {
        kitten memory _kitten = kitten({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            momId: uint32(_mumId),
            dadId: uint32(_dadId),
            generation: uint16(_generation) 
        });

        uint256 newKittenId = kittens.push(_kitten) -1;

        emit Birth(_owner, newKittenId, _mumId, _dadId, _genes);

        _transfer(address(0), _owner, newKittenId);

        return newKittenId;
    }

    function balanceOf(address owner) external view returns (uint256 balance) {
        return ownershipTokenCount[owner];
    }

    function totalSupply() external view returns (uint256 total){
        return kittens.length;
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() external view returns (string memory tokenSymbol){
        return _symbol;
    }

    function ownerOf(uint256 tokenId) external view returns (address owner){
        return _owners[tokenId];
    }

    function transfer(address to, uint256 tokenId) external{
        require(to != address(0), "ERC721: transfer to the zero address");
        require(to != address(this), "Cannot transfer to the contract address");
        require(_owners[tokenId] == address(msg.sender), 'nice try but you dont own this');

        _transfer(msg.sender, to, tokenId);
        emit Transfer(msg.sender, to, tokenId);
    }

    function _transfer(address _from, address _to, uint256 _tokenId) internal{
        ownershipTokenCount[_to]++;

        _owners[_tokenId] = _to;

        if (_from != address(0)) {
            ownershipTokenCount[_from]--;
        }

        emit Transfer(msg.sender, _to, _tokenId);
    }
}
2 Likes

Good afternoon everybody,
Hope everyone is doing fine this day?

You can find my function below

    function getKatInformation(uint256 _tokenId) public view returns( uint256 genes, uint64 timeOfBirth, uint32 mumId, uint32 dadId, uint16 generation){
        return (Kitties[_tokenId].genes, Kitties[_tokenId].timeOfBirth, Kitties[_tokenId].mumId, Kitties[_tokenId].dadId, Kitties[_tokenId].generation);
    }
2 Likes

Here is my current progress.

Bearcontract.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
pragma experimental ABIEncoderV2;

import "./IERC721.sol";
import "./Ownable.sol";

contract Bearcontract is IERC721, Ownable {

    uint256 public constant CREATION_LIMIT_GEN0 = 10;
    string public constant bearTicker = "AcademyBear";
    string public constant bearSymbol = "ABT";

    event Birth(
        address owner, 
        uint256 bearId, 
        uint256 mumId, 
        uint256 dadId, 
        uint256 genes
    );

    struct Bear {
        uint256 genes;
        uint64 birthTime;
        uint32 mumId;
        uint32 dadId;
        uint16 generation;
    }

    Bear[] bears;

    mapping(address => uint256) ownershipTokenCount;
    mapping(uint256 => address) tokenOwner;

    uint256 public gen0Counter;

    //Owner can create gen0 bears
    function createBearGen0(uint256 _genes) public onlyOwner returns(uint256){
        require(gen0Counter < CREATION_LIMIT_GEN0, "Generation 0 supply already fully minted!");

        gen0Counter++;

        //Gen0 are owned by the contract
        return(_createBear(_genes, 0, 0, 0, address(0)));
    }

    //create Bear
    function _createBear( 
        uint256 _genes,
        uint256 _mumId,
        uint256 _dadId,
        uint256 _generation,
        address _owner
    ) private returns (uint256) {
        Bear memory _bear = Bear({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            mumId: uint32(_mumId),
            dadId: uint32(_dadId),
            generation: uint16(_generation)
        });

        bears.push(_bear);

        uint256 newBearId = bears.length - 1;

        emit Birth(_owner, newBearId, _mumId, _dadId, _genes);

        _transfer(address(0), _owner, newBearId);

        return newBearId;
    }

    //returns bear properties
    function getBear(uint256 tokenId) public view returns(
        uint256 genes,
        uint64 birthTime,
        uint32 mumId,
        uint32 dadId,
        uint16 generation
    ){ return(
        bears[tokenId].genes,
        bears[tokenId].birthTime,
        bears[tokenId].mumId,
        bears[tokenId].dadId,
        bears[tokenId].generation
        );
    }

    function balanceOf(address owner) external view returns (uint256 balance) {
        return ownershipTokenCount[owner];
    }

    function totalSupply() external view returns (uint256) {
        return bears.length;
    }

    function name() external view returns (string memory tokenName) {
        tokenName = bearTicker;
    }

    function symbol() external view returns (string memory tokenSymbol) {
        tokenSymbol = bearSymbol;
    }

    function ownerOf(uint256 tokenId) external view returns (address) {
        require(tokenOwner[tokenId] != address(0), "Invalid token ID");
        return tokenOwner[tokenId];
    }

    function transfer(address to, uint256 tokenId) external {
        require(to != address(0), "Invalid Address; Cannot transfer to Address 0!");
        require(to != address(this), "Invalid Address; Cannot transfer to Contract Address!");
        require(tokenOwner[tokenId] == address(msg.sender), "Invalid Address; Cannot transfer to own Address!");

        _transfer(msg.sender, to, tokenId);
    }

    function _transfer(address _from, address _to, uint256 _tokenId) internal {
        ownershipTokenCount[_to]++;
        
        if(_from != address(0)) {
            ownershipTokenCount[_from]--;
        }

        tokenOwner[_tokenId] = _to;

        emit Transfer(_from, _to, _tokenId);
    }
}

Ownable.sol

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.16;

abstract contract Ownable {

    address private _owner = msg.sender;

    // Returns the address of the owner.
    function owner() public view returns (address) {
        return _owner;
    }

    //onlyOwner modifier
    modifier onlyOwner() {
        require(owner() == msg.sender, "Caller is not the owner");
        _;
    }
}
2 Likes
function getKitty(uint256 tokenId) external view returns(uint256, uint64, uint32,uint32,uint16){
        require(tokenId < kitties.length);
        return (
            kitties[tokenId].genes,
            kitties[tokenId].birthTime,
            kitties[tokenId].mumId,
            kitties[tokenId].dadId,
            kitties[tokenId].generation
        );
    }
1 Like

Hi fam,
Re: Video: Get Kitty Solution at 6:26.

In truffle console, when I input,
result["genes"],
I get:
Genes
And,
When I input,
result["genes"].toNumber(),
I get:

Anyone know what I am seeing and, how to get the genes actual number?

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// import ā€œ./IERC721.solā€;
import ā€œ@openzeppelin/contracts/token/ERC721/ERC721.solā€;
import ā€œā€¦/contracts/Ownable.solā€;

// bygg kitty kontraktet
contract Kitty is ERC721, Ownable {
event Birth(
address owner,
uint256 newKittenId,
uint256 mumId,
uint256 dadId,
uint256 genes
);

mapping(address => uint256) ownershipTokenCount;
mapping(uint256 => address) kittyIndexToOwner;
mapping(uint256 => Kitties[]) kittyOwner;

struct Kitties {
    uint256 genes;
    uint256 birthTime;
    uint256 mumId;
    uint256 dadId;
    uint256 generation;
}

// Kitties[] kitties;

uint256 gen0Counter;
uint256 gen0Limit;
uint256 totSupply;

constructor() ERC721("", "") {
    owner = msg.sender;
}

function createKittyGen0(uint256 _genes)
    public
    onlyOwner
    returns (uint256)
{
    require(gen0Counter >= gen0Limit, "reached gen0 creation limit");
    ownershipTokenCount[msg.sender]++;
    gen0Counter++;
    return _createKitty(0, 0, 0, _genes, msg.sender);
}

function _createKitty(
    uint256 _mumId,
    uint256 _dadId,
    uint256 _generation,
    uint256 _genes,
    address _owner
) private returns (uint256) {
    kittyOwner[_genes].push(
        Kitties(
            _genes,
            uint256(block.timestamp),
            _mumId,
            _dadId,
            _generation
        )
    );
    // kitty specific genes counter
    uint256 newKittenId = kittyOwner[_genes].length - 1;

    totSupply++;

    emit Birth(_owner, newKittenId, _mumId, _dadId, _genes);

    _transfer(address(0), _owner, newKittenId);

    return newKittenId;
}

function getKitty(uint256 _genes) public view returns (Kitties[] memory) {
    return kittyOwner[_genes];
}

function balanceOf(address owner)
    public
    view
    override
    returns (uint256 balance)
{
    return ownershipTokenCount[owner];
}

function ownerOf(uint256 index) public view override returns (address) {
    return kittyIndexToOwner[index];
}

function totalSupply(uint256 _genes) public view returns (uint256) {
    return kittyOwner[_genes].length;
}

function transfer(address _to, uint256 _tokenId) external {
    require(_to != address(0), "cant be the zero address");
    require(_to != address(this), "cant be the contract address");
    require(_to == ownerOf(_tokenId), "need to be the owner");

    _transfer(msg.sender, _to, _tokenId);
}

function _transfer(
    address _from,
    address _to,
    uint256 _tokenId
) internal override {
    ownershipTokenCount[_to]++;

    kittyIndexToOwner[_tokenId] = _to;

    if (_from != address(0)) {
        ownershipTokenCount[msg.sender]--;
    }
    emit Transfer(_from, _to, _tokenId);
}

function _owns(address _claimant, uint256 _tokenId)
    internal
    view
    returns (bool)
{
    return kittyIndexToOwner[_tokenId] == _claimant;
}

}

1 Like

Hello everyone :grinning:,

This is the Kittycontract.sol with the getKitty() function.

I compile, deployed and tested it in Truffle.

Kittycontract.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";
import "./Ownable.sol";

contract Kittycontract is IERC721, Ownable {
    struct Kitty {
        uint256 genes;
        uint64 birthTime;
        uint32 mumId;
        uint32 dadId;
        uint16 generation;
    }

    event Birth(
        address owner,
        uint256 tokenId,
        uint32 dadId,
        uint32 mumId,
        uint256 genes
    );

    Kitty[] kitties;

    //Associates an EOA with its balance
    mapping(address => uint256) private balances;

    //Associates a token id with its owner
    mapping(uint256 => address) private tokenowners;

    function balanceOf(address owner) external view returns (uint256 balance) {
        return balances[owner];
    }

    function totalSupply() external view returns (uint256 total) {
        return kitties.length;
    }

    function name() external view returns (string memory tokenName) {
        return "ScaredKitty";
    }

    function symbol() external view returns (string memory tokenSymbol) {
        return "SCARKIT";
    }

    // Reverts if a token id does not exists?
    function ownerOf(uint256 tokenid) external view returns (address owner) {
        owner = tokenowners[tokenid];

        require(owner != address(0), "Token id does not exist");
    }

    function transfer(address to, uint256 tokenId) external {
        require(to != address(0), "invalid to address");
        require(to != address(this), "to cannot be the contract address");

        address owner = tokenowners[tokenId];

        require(owner != address(0), "Token id does not exist");
        require(msg.sender == owner, "only owner can make a transfer");

        _transfer(owner, to, tokenId);
    }

    function _transfer(
        address _from,
        address _to,
        uint256 _tokenId
    ) internal {
        if (_from != address(0)) {
            assert(balances[_from] > 0);

            balances[_from]--;
        }

        tokenowners[_tokenId] = _to;
        balances[_to]++;

        emit Transfer(_from, _to, _tokenId);
    }

    function createKittyGen0(uint256 _genes) public onlyOwner {
        _createKitty(0, 0, 0, _genes, msg.sender);
    }

    function getKitty(uint256 _id)
        public
        view
        returns (
            uint256 genes,
            uint256 birthTime,
            uint32 mumId,
            uint32 dadId,
            uint16 generation
        )
    {
        require(_id < kitties.length, "Invalid cat id");

        Kitty storage kitty = kitties[_id];

        genes = kitty.genes;
        birthTime = kitty.birthTime;
        mumId = kitty.mumId;
        dadId = kitty.dadId;
        generation = kitty.generation;
    }

    function _createKitty(
        uint32 _mumId,
        uint32 _dadId,
        uint16 _generation,
        uint256 _genes,
        address _owner
    ) internal returns (uint256) {
        Kitty memory _kitty = Kitty({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            mumId: _mumId,
            dadId: _dadId,
            generation: _generation
        });

        kitties.push(_kitty);
        uint256 newKittyTokenId = kitties.length - 1;

        _transfer(address(0), _owner, newKittyTokenId);

        emit Birth(_owner, newKittyTokenId, _dadId, _mumId, _genes);
    }
}

Ownable.sol

(slightly modified from Ownable.sol in Openzeppelin library)

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable  {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () {
        address msgSender = msg.sender;
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}


1 Like
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "./IERC721.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";

contract Kittycontract is IERC721, Ownable {
	string public constant name = 'KittyCool';
	string public constant symbol = "KTY";

	event Birth(address owner, uint256 kittenId, uint256 mumId, uint256 dadId, uint256 genes);
	mapping(address => uint256) ownershipTokenCount;
	mapping(uint256 => address) kittyIndexToOwner;

	struct Kitty {
		uint256 genes;
		uint64 birthTime;
		uint32 mumId;
		uint32 dadId;
		uint16 generation;
	}

	Kitty[] kitties;
	
	uint256 public total;             // Total number of tokens

	function balanceOf(address owner) external view returns (uint256 balance) {
		return ownershipTokenCount[owner];
	}
	// Return the total number of tokens in circulation
	function totalSupply() public view returns (uint256) {
		return kitties.length;
	}
	
	function ownerOf(uint256 tokenId) external view returns (address owner) {
		return kittyIndexToOwner[tokenId];
	}
	// Transfer tokens from msg.sender to a specified address
	function transfer(address to, uint256 tokenId) public {
		require(to != address(0), "Wrong address");
		require(to != address(this), "Cannot transfer to the same address.");
		require(_owns(payable(msg.sender), tokenId), "Token id unknown");
		
		_transfer(msg.sender, to, tokenId); //solhintā€disableā€line indent, noā€unusedā€vars
	}

	function _transfer(address from, address to, uint256 tokenId) internal {
		ownershipTokenCount[to] ++;
		kittyIndexToOwner[tokenId] = to;

		if(from != address(0)) {
			ownershipTokenCount[from] --;
		}
		// Emit transfer event
		emit Transfer(from, to, tokenId);
	}

	function _owns(address payable claimant, uint256 tokenId) internal view returns (bool) {
        return kittyIndexToOwner[tokenId] == claimant;
    }

	function createKittyGene0(uint256 _genes) public onlyOwner {
		createKitty(
			0,
			0,
			0,
			_genes,
			msg.sender
		);
		
	}
	
	function createKitty(
		uint256 _mumId,
		uint256 _dadId,
		uint256 _generation,
		uint256 _genes,
		address _owner
	) private returns (uint256) {
		Kitty memory _kitty = Kitty({
			genes: _genes,
			birthTime: uint64(block.timestamp),
			mumId: uint32(_mumId),
			dadId: uint32(_dadId),
			generation: uint16(_generation)
		});

		kitties.push(_kitty);
		uint256 newKittenId = kitties.length - 1;
		emit Birth(_owner, newKittenId, _mumId, _dadId, _genes);
		_transfer(address(0), _owner, newKittenId);

		return newKittenId;
	}
	
}

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "./IERC721.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";

contract Kittycontract is IERC721, Ownable {
	string public constant name = 'KittyCool';
	string public constant symbol = "KTY";

	event Birth(address owner, uint256 kittenId, uint256 mumId, uint256 dadId, uint256 genes);
	mapping(address => uint256) ownershipTokenCount;
	mapping(uint256 => address) kittyIndexToOwner;

	struct Kitty {
		uint256 genes;
		uint64 birthTime;
		uint32 mumId;
		uint32 dadId;
		uint16 generation;
	}


	Kitty[] kitties;
	
	uint256 public total;             // Total number of tokens
	// string public name;                   // Descriptive name 
	// string public symbol;                 // Short identifier for token (i.e. KTY)


	function balanceOf(address owner) external view returns (uint256 balance) {
		return ownershipTokenCount[owner];
	}
	// Return the total number of tokens in circulation
	function totalSupply() public view returns (uint256) {
		return kitties.length;
	}
	
	function ownerOf(uint256 tokenId) external view returns (address owner) {
		return kittyIndexToOwner[tokenId];
	}
	// Transfer tokens from msg.sender to a specified address
	function transfer(address to, uint256 tokenId) public {
		require(to != address(0), "Wrong address");
		require(to != address(this), "Cannot transfer to the same address.");
		require(_owns(payable(msg.sender), tokenId), "Token id unknown");
		
		_transfer(msg.sender, to, tokenId); //solhintā€disableā€line indent, noā€unusedā€vars
	}

	function _transfer(address from, address to, uint256 tokenId) internal {
		ownershipTokenCount[to] ++;
		kittyIndexToOwner[tokenId] = to;

		if(from != address(0)) {
			ownershipTokenCount[from] --;
		}
		// Emit transfer event
		emit Transfer(from, to, tokenId);
	}

	function _owns(address payable claimant, uint256 tokenId) internal view returns (bool) {
        return kittyIndexToOwner[tokenId] == claimant;
    }

	function createKittyGene0(uint256 _genes) public onlyOwner {
		createKitty(
			0,
			0,
			0,
			_genes,
			msg.sender
		);
		
	}
	
	function createKitty(
		uint256 _mumId,
		uint256 _dadId,
		uint256 _generation,
		uint256 _genes,
		address _owner
	) private returns (uint256) {
		Kitty memory _kitty = Kitty({
			genes: _genes,
			birthTime: uint64(block.timestamp),
			mumId: uint32(_mumId),
			dadId: uint32(_dadId),
			generation: uint16(_generation)
		});

		kitties.push(_kitty);
		uint256 newKittenId = kitties.length - 1;
		emit Birth(_owner, newKittenId, _mumId, _dadId, _genes);
		_transfer(address(0), _owner, newKittenId);

		return newKittenId;
	}

	function getKitty(uint32 _kittyId) public view returns (uint256, uint64, uint32, uint32, uint16){
        return (
			kitties[_kittyId].genes,
			kitties[_kittyId].birthTime,
			kitties[_kittyId].mumId,
			kitties[_kittyId].dadId,
			kitties[_kittyId].generation
		);
    }


	
}

I deployed var instance = await KittyContract.deployed() and create Kitty instance.createKittyGen0(1001).

When I try getKitty, I got just info about tx, cannot get actual Kitty logs with instance.getKitty(0)? image
Why is that?

truffle(ganache)> instance.getKitty(0)
{
  tx: '0x908b36ac2b294d95ffa3da919daa53638419070bb27b732465e06c775c06ff11',
  receipt: {
    transactionHash: '0x908b36ac2b294d95ffa3da919daa53638419070bb27b732465e06c775c06ff11',
    transactionIndex: 0,
    blockNumber: 31,
    blockHash: '0x466045a9b1a51f99b81158cd5f9647ddb7a4ba0ba0fb78bc7282cc53dcb9b62f',
    from: '0xe325549b694ee660c0095db0ecf86c5e82025c12',
    to: '0x42b82ec17f97a6ef35fe0a64c447c63f00eeaaa6',
    cumulativeGasUsed: 28790,
    gasUsed: 28790,
    contractAddress: null,
    logs: [],
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    status: true,
    effectiveGasPrice: 2521389297,
    type: '0x2',
    rawLogs: []
  },
  logs: []
}
Kittycontract.sol
// SPDX-License-Identifier: MIT
pragma solidity >0.6.0 <0.9.0;

import "./IERC721.sol";
import "./Ownable.sol";

contract KittyContract is IERC721{ // inheriting KittyContract from IERC721

    string public constant TokenName = "LOLChain";
    string public constant Ticker = "LOL";

    event Birth(address owner, uint256 kittyId, uint256 mumId, uint256 dadId, uint256 genes);

    mapping(address => uint256) balanceOfKitties;
    mapping(uint256 => address) tokenOwner;

    struct Kitty{
        uint256 genes;
        uint64 birthTime;
        uint32 mumId;
        uint32 dadId;
        uint16 generation;
    }

    Kitty[] kitties;

    uint256 public constant CREATION_LIMIT_GEN0 = 10;
    uint256 public gen0counter;

    function createKittyGen0(uint256 _genes) public returns(uint256){ // genes from frontend slider
        require(gen0counter <= CREATION_LIMIT_GEN0);
        gen0counter++;
        // Gen0 have no owners, they are own by the contract
        return _createKitty(0, 0, 0, _genes, msg.sender); // owner can be also this contract --> address(this)
    }

    //creating cats
    function  _createKitty(uint256 _mumId, uint256 _dadId, uint256 _generationId, uint256 _genes, address _owner
) private returns (uint256) { // returns catId, function that will be use during brathing and creating from nowhere (birth of ta cat)
        Kitty memory _kitty = Kitty({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            mumId: uint32(_mumId), //easier to input uint256 and then converting to uint32, rather than inputing uint32 in function
            dadId: uint32(_dadId),
            generation: uint16(_generationId)
        });

        kitties.push(_kitty); // push will return size of array
        uint256 newKittyId = kitties.length - 1; //-1 because we want to start from 0 (first cat will have ID 0)
        emit Birth(_owner, newKittyId, _mumId, _dadId, _genes);
        _transfer(address(0), _owner, newKittyId); // --> from address(0) newKittyId will be transferred to _owner, CREATION A CAT FROM NOWHERE (BIRTH)
        return newKittyId;
    }

    function getKitty(uint256 _kittyId) external returns(uint256 genes, uint256 birthTime, uint256 mumId, uint256 dadId, uint256 generation){
        Kitty storage kitty = kitties[_kittyId]; // storage -> pointer to kitties array, memory will create a copy

        // uint256 is easier to read on frontend rather small values of uint
        birthTime = uint256(kitty.birthTime);
        mumId = uint256(kitty.mumId);
        dadId = uint256(kitty.dadId);
        generation = uint256(kitty.generation);
        genes = kitty.genes;
    }

    function balanceOf(address owner) external override view returns (uint256 balance){
        return balanceOfKitties[owner];
    }

    function totalSupply() external override view returns (uint256 total){
        return kitties.length;
    }

    function name() external override view returns (string memory tokenName){
        return TokenName;
    }

    function symbol() external override view returns (string memory tokenSymbol){
        return Ticker;
    }

    function ownerOf(uint256 tokenId) external override view returns (address owner){
        require(owner != address(0));
        address owner = tokenOwner[tokenId];
        return owner;
    }

    function transfer(address to, uint256 tokenId) external override{ // this function only sends from msg.sender to recipient
        require(to != address(0));
        require(to != address(this));
        require(_owns(msg.sender, tokenId));

        _transfer(msg.sender, to, tokenId);
    }

    function _owns(address claimant, uint256 tokenId) internal view returns(bool){
        return tokenOwner[tokenId] == claimant; // claimant -> person who is claiming the ownership
    }

    function _transfer(address _from, address _to, uint256 _tokenId) internal{
        balanceOfKitties[_to]++;
        tokenOwner[_tokenId] = _to; // _to is owner of _tokenId
        if(_from != address(0)){ // zbog mintanja nove mačke, jer tad nema oduzimanja tokena ako je nova
            balanceOfKitties[_from]--; // decreasing token from sender
        }
        emit Transfer(_from, _to, _tokenId);
    }
}

@thecil @kenn.eth

Hello @Lane11

For further analysis, to determine if the contract deployment had no errors, have you tried other functions like totalSupply ?

Hi @alp257,

Here is the result:

truffle(ganache)> var inst = await KittyContract.deployed()
undefined
truffle(ganache)> inst.name()
'LOLChain'
truffle(ganache)> inst.totalSupply()
BN { negative: 0, words: [ 0, <1 empty item> ], length: 1, red: null }
inst.createKittyGen0(101)

{ tx: '0x19f8973828a0fec6c945ad5d3bf87d886618f22fb7de7f6bf7344dd071b129ca', receipt: { transactionHash: '0x19f8973828a0fec6c945ad5d3bf87d886618f22fb7de7f6bf7344dd071b129ca', transactionIndex: 0, blockNumber: 5, blockHash: '0xed8150ddd41d163a30057863d809bccfe71777bad29483c948b033b3677479c2', from: '0x6bf6887a3932a2efbb7d59a824ac0a46ea80d2bd', to: '0x4bad07831d49491cf82dc237c0116f11871e0783', cumulativeGasUsed: 160512, gasUsed: 160512, contractAddress: null, logs: [ [Object], [Object] ], logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000010000020000000000000000000000000000000000040000008000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000100002000000000010000000000000000000000000000000000000000020000000000100000000000000000000000400000000000000000000000000000000', status: true, effectiveGasPrice: 3034479064, type: '0x2', rawLogs: [ [Object], [Object] ] }, logs: [ { address: '0x4bAd07831d49491CF82DC237c0116f11871e0783', blockHash: '0xed8150ddd41d163a30057863d809bccfe71777bad29483c948b033b3677479c2', blockNumber: 5, logIndex: 0, removed: false, transactionHash: '0x19f8973828a0fec6c945ad5d3bf87d886618f22fb7de7f6bf7344dd071b129ca', transactionIndex: 0, id: 'log_f44f9314', event: 'Birth', args: [Result] }, { address: '0x4bAd07831d49491CF82DC237c0116f11871e0783', blockHash: '0xed8150ddd41d163a30057863d809bccfe71777bad29483c948b033b3677479c2', blockNumber: 5, logIndex: 1, removed: false, transactionHash: '0x19f8973828a0fec6c945ad5d3bf87d886618f22fb7de7f6bf7344dd071b129ca', transactionIndex: 0, id: 'log_4b841bfe', event: 'Transfer', args: [Result] } ] }

inst.getKitty(0)

{ tx: '0xfda71ca9019564d6facb26f13dca29e092f082a9fb919e07f6a6aee445783311', receipt: { transactionHash: '0xfda71ca9019564d6facb26f13dca29e092f082a9fb919e07f6a6aee445783311', transactionIndex: 0, blockNumber: 6, blockHash: '0x94a400e118b26583beba669e200f4bf23852c0f4bda1c4f7619ff2c5e0861013', from: '0x6bf6887a3932a2efbb7d59a824ac0a46ea80d2bd', to: '0x4bad07831d49491cf82dc237c0116f11871e0783', cumulativeGasUsed: 28790, gasUsed: 28790, contractAddress: null, logs: [], logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', status: true, effectiveGasPrice: 2970859848, type: '0x2', rawLogs: [] }, logs: [] }

I migrated again and create new var inst, but on previous comment it was instance (just for clarity).

Hello,
Anything unusual if you check the total supply? it should give you an output if a Kitty or Kitties were generated successfully
How about trying to pass in a different index (instead of 0)? ~ getKitty(1)