Assignment ERC721

haha sorry i am not the best at explaining! So i have got all the problems except "Different number of components on the left hand side (1) than on the right hand side (0) on line 77 of the code.

never have seen this error message before and wanted to see if it was because I’m using the - sign instead of something else I should be using.

Also says on line 77, “Operator - not compatible with types tuple() and in_const1” So I’m not really sure what this error message is either.

These are the last two problems its says tho! so I’m getting there haha

The problem is on the _createKitty function, the way you assign the newKittenId might be incompatible with one of the solidity versions.

You could do this instead, which is to save first the kittie in the array, then take the length of the array minus 1 and use it has the Id.

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

Carlos Z

1 Like

my man!! got it figured out, that was exactly it! Thanks so much again!!

1 Like

@thecil Hey man hope you’re doing well :slight_smile: I really appreciate the help so far!

So I have run into this same problem again, this time with the approve function. Filip uses _owns which I was able to remove and make a new statement for but this time I’m not sure how to eliminate _owns without using it in the require statement. The code is below: and the problem is on line 40.

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

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

 contract Kittycontract is IERC721, Ownable {
    
    // Gen 0 Creation Limit
    uint256 public constant CREATION_LIMIT_GEN0 = 10;

    // Token name
    string public constant override name = "MickeyKitties";

    // Token symbol
    string public constant override symbol = "GG";

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


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

    Kitty[] kitties;

    mapping (uint256 => address) public kittyIndexToOwner; // tokenId => kitty owner
    mapping (address => uint) ownershipTokenCount; //count of how many kitties each owner has
    
    mapping(uint256 => address) public kittyIndexToApproved;
    mapping(address => mapping (address => bool)) private _operatorApprovals;
    
    uint256 public gen0Counter;

    function approve(address _to, uint256 _tokenId) public {
        require(_owns(msg.sender, _tokenId));
        

        approve(_tokenId, _to);
        emit Approval(msg.sender, _to, _tokenId);
    }

    function setApprovalForAll(address operator, bool approved) public {
        require(operator != msg.sender);

        _operatorApprovals[msg.sender][operator] = approved;
        emit setApprovalForAll(msg.sender, operator, approved);
    }

    function getApproved(uint256 tokenId) public view returns (address) {
        require(tokenId < kitties.length); //Token must exist

        return kittyIndexToApproved[tokenId];
    }

    function isApprovedForAll(address owner, address operator) public view returns (bool){
        return _operatorApprovals[owner][operator];
    }

    function getKittyByOwner(address _owner) external view returns(uint [] memory) {
        uint [] memory result = new uint [] (ownershipTokenCount[_owner]);
        uint counter = 0;
        for (uint i = 0; i < kitties.length; i++) {
            if (kittyIndexToOwner[i] == _owner) {
                result[counter] = i;
                counter++;
            }
        }
        return result;
    }


    function getKitty(uint256 _id) external view returns (
        uint256 genes,
        uint256 birthTime,
        uint256 momId,
        uint256 dadId,
        uint256 generation
    )
    {
        Kitty storage kitty = kitties[_id];

        birthTime = uint256(kitty.birthTime);
        momId = uint256(kitty.momId);
        dadId = uint256(kitty.dadId);
        generation = uint256(kitty.generation);
        genes = kitty.genes;
    }
    
    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 _momId,
        uint256 _dadId,
        uint256 _generation,
        uint256 _genes,
        address _owner
    )  private returns (uint256) {
        Kitty memory _kitty = Kitty({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            momId: uint32(_momId),
            dadId: uint32(_dadId),
            generation: uint16(_generation)
        });

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

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

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

        return newKittenId;
    }

     //Returns the number of tokens in ``owner``'s account.
    function balanceOf(address owner) external view override returns (uint256) {
        return ownershipTokenCount[owner];
    }

    /*
     * @dev Returns the total number of tokens in circulation.
     */
    function totalSupply() external view override returns (uint256){
        return kitties.length;
    }
    /*
     * @dev Returns the name of the token.
     */
    function catName() external pure returns (string memory){
        return name;
    }
    /*
     * @dev Returns the symbol of the token.
     */
    function catSymbol()  external pure returns (string memory) {
        return symbol;
    }
    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view override returns (address){
        require(kittyIndexToOwner[tokenId] != address(0));
        return kittyIndexToOwner[tokenId];
    }

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

        require(_to != address(0), "_to cant be a zero address");
        require(_to != address(this), "not the same address as _to");
        require(kittyIndexToOwner[_tokenId] == msg.sender);
    }


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

        kittyIndexToOwner[tokenId] = _to;

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

        // Emit the transfer event
        emit Transfer(_from, _to, tokenId);

    }

 }   

1 Like

I might have to check your Ownable contract, someone must contain the declaration of the _owns function, since is not in the contract that you provided, i assume it should be on the Ownable.

What you could do to remove it and change the require to something like what the _owns function does, you can do.

Taking in consideration that: _owns will return true or false if the msg.sender is the owner of the token Id.

require(kittyIndexToOwner[tokenId] == msg.sender, "not token owner");

Keep in mind:

mapping (uint256 => address) public kittyIndexToOwner; // tokenId => kitty owner

So basically will return the owner of the tokenId, which is kinda the logic that _owns have (i assume).

Carlos Z

code

pragma solidity ^0.8.4;

import "./IERC721.sol";

contract Gkittycontract is IERC721 {

string public constant _name = "Gkitties";
string public constant _symbol = "GKT"; 

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

Kitty[] kitties;

mapping(address=>uint256) ownershipTokenCount; // address => how many token owned by the address
mapping(uint256=>address) kittyIndexToOwner; // tokenID => owner of the token

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

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

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

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

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

function transfer(address to, uint256 tokenId) override external {
    require(to != address(0), "This address doesn't exist");
    require(to != address(this), "Cannot transfer to this contract");
    require(kittyIndexToOwner[tokenId] == msg.sender, "You are not the owner of this token!");
    _transfer(msg.sender, to, tokenId);
}

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


}

Awesome! Sorry i ahould have uploaded the Ownable.sol here that is!

  
// SPDX-License-Identifier: MIT

pragma solidity >=0.4.22 <0.9.0;

import "./Context.sol";

/**
 * @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 is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _setOwner(_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() == _msgSender(), "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 {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

So upon removing the old _owns function, I did the one you pasted and then my approve(_tokenId, _to); are wrong?

posting the errors for reference!

I was able to figure it out! having to put hte event in the Ownable.sol with the correct event paramaters was the issue! So sorry for the spam man!!!

function approve(address _to, uint256 _tokenId) public {
        require(kittyIndexToOwner[_tokenId] == msg.sender, "not token owner");

        

        approve(_tokenId, _to);
        emit Approval(msg.sender, _to, _tokenId);
    }

    function setApprovalForAll(address operator, bool approved) public {
        require(operator != msg.sender);

        _operatorApprovals[msg.sender][operator] = approved;
        emit setApprovalForAll(msg.sender, operator, approved);
    }

Soooo i got the first one, but it says the 2nd function, Expression has to be an event invocation? so do i need the make the setApprovalForAll as a event like the Birth event?

My code!

pragma solidity ^0.8.6;

import "./IERC721.sol";

contract Kittycontract is IERC721{

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

    Kitty[] kitties;

    mapping(address => uint256) ownershipTokenCount;
    mapping(uint => address) tokenIdOwners;
    mapping(uint => bool) tokenExists;

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

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

    function name() external override pure returns (string memory tokenName){
        return "Maxs Kitties";
    }

    function symbol() external override pure returns (string memory tokenSymbol){
        return "MXK";
    }

    function ownerOf(uint256 tokenId) external view override returns (address owner){
        require(tokenExists[tokenId] == true, "Token does not exist");
        return tokenIdOwners[tokenId];
    }

    function transfer(address to, uint256 tokenId) external override{
        require(tokenExists[tokenId] == true, "Token does not exist");
        require(to != address(0), "You can't transfer to address 0");
        require(to != address(this), "You can't transfer to this contract");
        require(msg.sender == tokenIdOwners[tokenId], "You can't transfer tokens you don't own");
        ownershipTokenCount[msg.sender] -= 1;
        ownershipTokenCount[to] += 1;
        tokenIdOwners[tokenId] = to;

    }
}
1 Like

I have added info from the book Mastering Ethereum by Antonopoulos for this assignment. I didn’t even test anything yet.

pragma solidity 0.5.12;

import"./IERC271.sol";
import "./node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol";


contract kittycontract is IERC721{
    using SafeMath for uint256;
    
    string private constant Name = "CreepyKitty";
    string private constant Symbol = "CRPY";

    
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed_owner, address indexed_operator,bool_approved);

    mapping(address => uint256) ownershipTokenCount;
    
    
    function balanceOf(address owner) external view returns (uint256 balance);
        return ownershipTokenCount [owner];

    
    function totalSupply() external view returns (uint256 total);

    
    function name() external view returns (string memory tokenName);

    
    function symbol() external view returns (string memory tokenSymbol);

   
    function ownerOf(uint256 tokenId) external view returns (address owner);


    function transfer(address to, uint256 tokenId) external payable;
    function transferFrom (address_from, address_to, uint256_tokenId) external payable;
    function approve(address_approved, uint256_tokenId) external payable;
    function setApprovalForAll(address_operator, boolean_approved) payable;
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
}

1 Like

Here is my Catcontract.sol:

// SPDX-License-Identifier: MIT
pragma solidity = 0.8.7;

import "./IERC721.sol";

abstract contract Catcontract is  IERC721 {

/*Storage:
**********/
    uint256 public _maxSupply; // Token max supply
    string public _name; // Token name
    string public _symbol; // Token symbol

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

    Cat[] cats;
    mapping(uint256 => address) private _catOwner;  // Map from token ID to owner address
    mapping(address => uint256) _catTokenCount; //Map cats number by owner == get cats per address


/*Constructor:
**************/

    constructor(string memory name_, string memory symbol_, uint256 maxSupply_) {
            _name = name_;
            _symbol = symbol_;
            _maxSupply = maxSupply_;
        }


/*Functions:
************/

    //Returns the number of tokens in ``owner``'s account
    function balanceOf(address owner) external override view returns (uint256 balance) {
        return _catTokenCount[owner];
    }

    //Returns the total number of tokens in circulation
    function totalSupply() external override view returns (uint256 total) {
        return _maxSupply;
    }

    //Returns the name of the token
    function name() external override view returns (string memory tokenName) {
        return _name;
    }

    //Returns the symbole of the token
    function symbol() external override view returns (string memory tokenSymbol) {
        return _symbol;
    }

    //Returns the owner of the `tokenId` token
    function ownerOf(uint256 tokenId) public view override returns (address owner) {
        address _owner = _catOwner[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return _owner;
    }

    //Transfers `tokenId` token from `msg.sender` to `to`.
    function transfer(address from, address to, uint256 tokenId) internal {
        require(ownerOf(tokenId) == from, "You're not the owner of this cat!");
        require(to != address(0), "ERC721: transfer to the zero address");
        require(to != address(this), "ERC721: transfer to the contract address");

        _catTokenCount[from] -= 1;
        _catTokenCount[to] += 1;
        _catOwner[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

}
1 Like

How to solve this problem?
image
Here is my contract :

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

import "./IERC721.sol";
import "../node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol";

  contract Kittycontract is IERC721 {
    
     using SafeMath for uint256;

     string public TokenName;
     string public TokenSymbol;
     uint256 TokenAmount;

     mapping (address => uint256) tokenBalance;
     mapping (uint256 => address) ownerOfToken; 

     struct cat{
         address owner; 
         uint256 catID;
     }

     cat[] cats;

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

    function totalSupply() override external view returns (uint256 total){
         total = TokenAmount;
    }

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

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

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

    function transfer(address to, uint256 tokenId) override external{
        require(to != address(0), "cannot be the zero address");
        require(to != address(this), "can not be the contract address");
        require(ownerOfToken[tokenId] == msg.sender);

        tokenBalance[to] = tokenBalance[to].add(tokenId);
        tokenBalance[to] = tokenBalance[to].sub(tokenId);

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

}

hey @Lane11 ! Is this after your deployment runs correct? Make sure you are into the truffle console in order to declare this instance.
Please provide a picture of the final contract deployment.

Yes, I did do that in the truffle console after successful migration.
Screenshot_4 Screenshot_5
2_kitties_migration.js :

const Token = artifacts.require("Kittycontract");

module.exports = function (deployer) {
  deployer.deploy(Token);
};

1 Like
Kittycontract.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "./IERC721.sol";

//Contracts are considered abstract if at least ONE of their functions is not implemented

abstract contract Kittycontract is IERC721 {

    constructor() IERC721() {}

    string public constant Name = "HelloKitties";
    string public constant Symbol ="HKTS";

    struct Token {
        uint256 genes;
        uint64 birthTime;
        uint32 mumId;
        uint32 dadId;
        uint16 generation;
        
        address owner;
        uint id;
    }
    Token[] allTokens;

    mapping(uint256 => address) ownership;
    mapping(address => uint) tokenAmount;
    mapping(address => Token[]) allTokensPerOwner;

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

    function allNFTsPerOwner() public view returns (Token[] memory) {
        return allTokensPerOwner[msg.sender];
    }

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

    function name() external pure returns (string memory tokenName) {
        return Name;
    }

    function symbol() external pure returns (string memory tokenSymbol) {
        return Symbol;
    }

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

    function transfer(address to, uint256 tokenId) external {
        require(to != address(0));
        require(to != address(this));
        require(allTokens[tokenId].owner == msg.sender);

        tokenAmount[msg.sender] -= 1;
        tokenAmount[to] += 1;
        ownership[tokenId] = to;

        emit Transfer(msg.sender, to, tokenId);
    }
}
1 Like
Kittycontract.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "./IERC721.sol";
import "../node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol";


contract Kittycontract is IERC721 {

    using SafeMath for uint256;

    string public constant tokenName = "Chibilions";
    string public constant tokenSymbol = "CBL";

    struct Kitty {
        uint256 genes;
        uint64 birthTime;
        uint32 mumID;
        uint32 dadID;
        uint16 generation;
    }

    Kitty[] kitties;

    //kitty ID      owner
    mapping(uint256 => address) public kittyIndexToOwner;

    //owner         # of kitties owned
    mapping(address => uint256) ownershipTokenCount; //Token owners balance


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


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


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


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


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


    function transfer(address to, uint256 tokenId) override external {
        require(to != address(0), "Cannot send to a zero address");
        require(kittyIndexToOwner[tokenId] == msg.sender, "Owner must own token");
        require(to != address(this), "Cannot transfer to this contract");

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

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

        if (from != address(0)) {
            ownershipTokenCount[from] = ownershipTokenCount[from].sub(1);
        }

        emit Transfer(from, to, tokenId);
    }


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

}

try
let instance = await Kittycontract.deployed()
or just
await Kittycontract.deployed()

1 Like

Assignment:

contract Kittycontract is IERC721{

    string private _name;
    string private _symbol;

    mapping(address=>uint256) ownershipTokenCount;
    mapping(uint256=>uint256) totalNFTSupply;
    mapping(uint256 => address) private _owners;

    function balanceOf(address owner) external view returns (uint256 balance){
        require(owner != address(0), "ERC721: balance query for the zero address");
        return ownershipTokenCount[owner];
    }
    
    function totalSupply() external view returns (uint256 total){
        return totalNFTSupply[total];
    }

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

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

    function ownerOf(uint256 tokenId) external view returns (address owner){
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    function transfer(address to, uint256 tokenId) external{
        require(_owners[tokenId] == msg.sender, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");
        require(to != msg.sender, "ERC721: cannot send to yourself");
        ownershipTokenCount[msg.sender] -= 1;
        ownershipTokenCount[to] += 1;
        _owners[tokenId] = to;

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

}
1 Like

that should do it

pragma solidity 0.8.0;

import "./IERC721.sol";

contract Kittycontract is IERC721 {

    string public tickerName;
    string public tickerSymbol;
    uint256 totalTokenCount;

    //need constructor for ticker name/symbol

    //need struct for token

    mapping(address => uint256) private ownershipTokenCount;
    mapping(uint256 => address) private ownedBy;


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

    function totalSupply() external view returns (uint256 total) {
        return totalTokenCount;
    }

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

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

    function ownerOf(uint256 tokenId) external view returns (address owner) {
        address tokenOwner = ownedBy[tokenId];
        require(tokenOwner != address(0), "Token does not exist");
        return tokenOwner;
    }

    function transfer(address to, uint256 tokenId) external {
        require(to != address(0), "Invalid recipient, cannot transfer to zero addres");
        require(to != address(this), "Invalid recipient, cannot transfer to this contract");
        require(ownedBy[tokenId] == msg.sender, "Invalid owner");

        ownershipTokenCount[msg.sender] -= 1; //change effects to SafeMath
        ownershipTokenCount[to] += 1;

        ownedBy[tokenId] = to;

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

}
2 Likes