Error: *** Deployment Failed ***
“Kittycontract” is an abstract contract or an interface and cannot be deployed.
- Import abstractions into the ‘.sol’ file that uses them instead of deploying them separately.
- Contracts that inherit an abstraction must implement all its method signatures exactly.
- A contract that only implements part of an inherited abstraction is also considered abstract.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./Ownable.sol";
import "./IERC721Receiver.sol";
abstract contract Kittycontract is IERC721, Ownable {
address contractOwner;
uint256 CREATION_LIMIT_GEN0 = 10;
constructor() {
contractOwner = msg.sender;
}
event Birth(
address owner,
uint256 kittenId,
uint256 mumId,
uint256 dadId,
uint256 genes
);
struct Kitty {
uint256 genes;
uint64 birthTime;
uint32 mumId;
uint32 dadId;
uint16 generation;
}
Kitty[] kitties;
mapping(address => uint256) ownershipTokenCount;
mapping(uint256 => address) tokenIdOwners;
mapping(uint256 => bool) tokenExists;
mapping(uint256 => address) kittyIndexToApproved;
bytes4 internal constant MAGIC_ERC20_RECIVER =
bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
uint256 gen0counter;
//MYADDR => OPERATORADDR => TRUE/FALSE
// _operatorApprovals[MYADDR][OPERATORADDR] = false;
mapping(address => mapping(address => bool)) private _operatorApprovals;
function _safeTransfer(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) external {
_transfer(_from, _to, _tokenId);
require(_checkERC721Support(_from, _to, _tokenId, _data));
}
function createKittyGen0(uint256 _genes) public isOwner 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: _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 _id)
external
view
returns (
uint256 genes,
uint256 birthTime,
uint256 mumId,
uint256 dadId,
uint256 generation
)
{
Kitty storage kitty = kitties[_id]; // storage is a pointer to the original mapping, memory creates a local copy
genes = kitty.genes;
birthTime = uint256(kitty.birthTime);
mumId = uint256(kitty.mumId);
dadId = uint256(kitty.dadId);
generation = uint256(kitty.generation);
}
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 pure override returns (string memory tokenName) {
return "Mubashir_Kitties";
}
function symbol()
external
pure
override
returns (string memory tokenSymbol)
{
return "MK";
}
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"
);
_transfer(msg.sender, _to, _tokenId);
}
function _transfer(
address _from,
address _to,
uint256 _tokenId
) internal {
ownershipTokenCount[_to]++;
tokenIdOwners[_tokenId] = _to;
if (_from != address(0)) {
ownershipTokenCount[_from]--;
delete kittyIndexToApproved[_tokenId];
}
emit Transfer(_from, _to, _tokenId);
}
function _owns(address _claimant, uint256 _tokenId)
internal
view
returns (bool)
{
return tokenIdOwners[_tokenId] == _claimant;
}
function approve(address _approved, uint256 _tokenId) external override {
require(_owns(msg.sender, _tokenId));
_approve(_tokenId, _approved);
emit Approval(msg.sender, _approved, _tokenId);
}
function _approve(uint256 _tokenId, address _approved) internal {
kittyIndexToApproved[_tokenId] = _approved;
}
function setApprovalForAll(address operator, bool approved)
public
override
{
require(operator != msg.sender);
_operatorApprovals[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function getApproved(uint256 tokenId)
external
view
override
returns (address)
{
require(tokenId < kitties.length);
return kittyIndexToApproved[tokenId];
}
function isApprovedForAll(address owner, address operator)
external
view
override
returns (bool)
{
return _operatorApprovals[owner][operator];
}
function transferFrom(
address _from,
address _to,
uint256 _tokenId
) external override {
require(
_owns(_from, _tokenId),
"Owner address is not connected to this token!"
);
require(
msg.sender == _from ||
msg.sender == kittyIndexToApproved[_tokenId] ||
_operatorApprovals[_from][msg.sender],
"Only Owner, Operator or Approved Addresses can transfer!"
);
require(_to != address(0), "Transfer to zero-address is not possible!");
require(_tokenId < kitties.length, "This token does not exist!");
_transfer(_from, _to, _tokenId);
}
function _checkERC721Support(
address _from,
address _to,
uint256 _tokenId,
bytes memory _data
) internal returns (bool) {
if (!_isContract(_to)) {
return true;
}
bytes4 returnData = IERC721Receiver(_to).onERC721Received(
msg.sender,
_from,
_tokenId,
_data
);
return returnData == MAGIC_ERC20_RECIVER;
}
function _isContract(address _to) internal view returns (bool) {
uint32 size;
assembly {
size := extcodesize(_to)
}
return size > 0;
}
}