1. What is the time complexity of creating new cats?
Constant, due to same steps needed each time a kitty is created.
2. What is the time complexity of the getAllCatsFor function?
Linear, since it loops through the array which grows in size as more kitties are added.
3. How could the storage design be changed to make the getAllCats function constant?
Use a mapping to map the address to an array of kitty IDs, update the function, and add a new function to account for deleting a cat from the ownerâs owned cat array.
pragma solidity ^0.8.0;
contract KittyTwo {
string public constant name = "TestKitties";
string public constant symbol = "TK";
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
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 (uint256 => address) public kittyIndexToOwner;
mapping (address => uint256[]) public ownedCats;
function balanceOf(address owner) external view returns (uint256 balance){
return ownedCats[owner].length;
}
function totalSupply() public view returns (uint) {
return kitties.length;
}
function ownerOf(uint256 _tokenId) external view returns (address)
{
return kittyIndexToOwner[_tokenId];
}
function transfer(address _to,uint256 _tokenId) external
{
require(_to != address(0));
require(_to != address(this));
require(_owns(msg.sender, _tokenId));
_transfer(msg.sender, _to, _tokenId);
}
function getCatsfor(address _owner) external view returns (uint[] memory cats) {
cats = ownedCats[_owner];
}
function createKittyGen0(uint256 _genes) public returns (uint256) {
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 _transfer(address _from, address _to, uint256 _tokenId) internal {
kittyIndexToOwner[_tokenId] = _to;
ownedCats[_to].push(_tokenId);
if (_from != address(0)) {
_removeOwnership(_from, _tokenId);
}
emit Transfer(_from, _to, _tokenId);
}
function _removeOwnership(address _owner, uint256 _tokenId) internal {
for (uint i = 0; i < ownedCats[_owner].length; i++) {
if (ownedCats[_owner][i] == _tokenId) {
ownedCats[_owner][i] = ownedCats[_owner][ownedCats[_owner].length-1];
ownedCats[_owner].pop();
return;
}
}
}
function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) {
return kittyIndexToOwner[_tokenId] == _claimant;
}
}
This increases the efficiency of the function getting all cats for an owner, but at the expense of more complexity with transfers of cats (new linear function).