Skip to main content

🐈 Purrnelope's Kittens

🐈 Contract · OpenSea · LooksRare 🐈

What are Kittens​

Purrnelope's Kittens is the 2nd collection in PCC Universe with 10,000 randomly generated NFTs that exist on the Ethereum Blockchain. And Kittens are the 1st companion to the Cats. Kittens are Tier 3 NFTs.

Mint / Claim​

Kittens are claimed with Kitten Basket, 1 Kitten Basket for 1 Kitten. Public Kittens Claim opened on Nov 15, 2021. Unredeemed Kitten Baskets were pulled back on Dec 20, 2021.

All unclaimed Kittens will be minted by the team. And will be used in giveaways. 1

Kittens #1 - #20 are not revealed. They are reserved for The Team for mysterious plan? Maybe.

Clubhouse Access​

Kittens owners can access Clubhouse channel in PCC Discord.

Earn $Token​

Kittens are Tier 3 NFTs, will earn 1 $TOKEN per day per Kitten.


Details for Tiers & $TOKEN has not been released yet.

Redeem for KittyVault Fractions​

Once the KittyVault is fractionalized, Kittens can be redeemed(burned) for KittyBank Token.

Cats & Kittens​

Kittens are held in arms of Cats, the arms holding the Kittens will match with the Cats with the same ID.

Learn More​


  • 2021-11-13: PCC Team minted Kitten #1 - #20 @ 11:08:44 PM +UTC
  • 2021-11-15: Public Kitten Claim opened, 1st claim @ 09:31:02 PM +UTC
  • 2021-12-20: Unredeemed Kitten Baskets are pulled back to purrnelope.pcc.eth Etherscan

The Kittens Contract​

Kittens are ERC-721 NFTs (Etherscan). And the contract itself is named PurrnelopesKittens. And here are some unique features in the Kittens contract:

devMint Function private​

This is a private function and can not be used by anyone after the contract is deployed. Using this function can mint Kittens with sequential ID.

This was used during the contract deployment, Kittens #1 - #20 were minted for the team. (Etherscan)

This function is the same as the Grandmas Contract

See Code
function devMint(uint256 _quantity, address _to) private {
uint256 remaining = MaxSupplyCount - CurrentTokenId.current();
for(uint256 i; i < _quantity; i++){
_safeMint(_to, CurrentTokenId.current());
Ids[i] = Ids[remaining] == 0 ? remaining : Ids[remaining];

constructor() ERC721("Purrnelopes Kittens", "PK"){
devMint(20, 0x112E62d5906F9239D9fabAb7D0237A328F128e22);

internalMint Function private​

This is a private function for minting Kittens using other functions in this contract.

This function makes public Kittens minting have non-sequential token IDs. And it used getRandomNumber function defined in this contract to arhieve that.

This function is the same as the Grandmas Contract

See Code
function internalMint(address _to, uint256 _quantity) private {
require(_quantity <= MaxMintCount && _quantity > 0, "Incorrect mint quantity");
require(_quantity.add(CurrentTokenId.current()) <= MaxSupplyCount, "Cannot exceed max supply");

uint256 remaining = MaxSupplyCount - CurrentTokenId.current();

for(uint256 i; i < _quantity; i++){

uint256 tokenId = CurrentTokenId.current();
uint256 index = getRandomNumber(remaining, i * tokenId);

_safeMint(_to, ((Ids[index] == 0) ? index : Ids[index]) + 1);

Ids[index] = Ids[remaining] == 0 ? remaining : Ids[remaining];

//"random" number.... using chainlink for VRF seems overkill
function getRandomNumber(uint256 maxValue, uint256 salt) private view returns(uint256) {
if (maxValue == 0)
return 0;

uint256 seed =
block.difficulty +
((uint256(keccak256(abi.encodePacked(tx.origin, msg.sig)))) / (block.timestamp)) +
block.number +
return seed.mod(maxValue);

mint Function​

This function only accepts Kittens mint by the KittyVault Purrks contract, the Purrks contract uses this function to mint Kittens to whom redeemed their Kitten Basket Purrks.

This was used for mint Kittens using the Kitten Basket Purrks.

This function is the same as the Grandmas Contract

See Code
function mint(address _to, uint256 _quantity) override public {
require(msg.sender == AllowedAddress || msg.sender == owner(), "Not allowed minting address");
internalMint(_to, _quantity);

mintKittens Function​

This is for minting Kittens by paying with Ether(ETH).

To use this, the PublicMintingOpen toggle needs to be opened. But it is never used since the Kittens now are redeemed with Kitten Basket. But this function leaves possiblities to make that happen. And a price for minting a Kitten was set to 0.1 ETH during the contract deployment, which can be changed later.

This function is the same as the Grandmas Contract

See Code
function mintKittens(uint256 _quantity) payable public nonReentrant {
require(msg.value == _quantity.mul(UnitPrice), "Incorrect ETH amount");
require(PublicMintingOpen, "Public minting is not currently open");

internalMint(msg.sender, _quantity);

updateBurnUri Function​

This is for updating metadata for "*burned(redeemed)" Kittens.

Kittens contract does not have a function to actually burn the Kittens, the Kittens NFT will always exist on blockchain. But "*burned" Kittens are transferred to the burn(blackhole) address 0x0000Β·Β·Β·Β·dEaD. When querying token uri of a Kitten in the burn(blackhole) address, the contract will return to a unique token uri set by this function.

This function is the same as the Grandmas Contract

See Code
function updateBurnUri(string memory _uri) public onlyOwner{
BurnUri = _uri;

function tokenURI(uint256 _tokenId) public view override returns (string memory) {
require(_exists(_tokenId), "ERC721Metadata: URI query for nonexistent token");

string memory baseURI = _baseURI();
string memory uri = bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, _tokenId.toString())) : "";
return (ownerOf(_tokenId) == BurnAddress) ? BurnUri : uri;

redeemKittyBankFractions Function​

This is likely to be used for redeem Kittens for KittyVault Fractions. But it is also possible to create another contract to archive that.

Using this function will transferred the Kittens to the burn(blackhole) address 0x0000Β·Β·Β·Β·dEaD, and give back the KittyVault Fractions Token back to the owner that gave up his Kitten. And the Kittens transferred to the burn(blackhole) address will never get their image back, which explained in updateBurnUri function.

And this function even supports redeeming multiple Kittens at once! What a cruel function!

See Code
function redeemKittyBankFractions(uint256[] calldata ids) public {
require(RedeemOpen, "ERC-20 redeem is not currently open");
require(FractionsPerNFT > 0, "Fractions per NFT currently not set");
uint256 amount = FractionsPerNFT.mul(ids.length);
require(FractionsContract.balanceOf(address(this)) >= amount, "Not enough balance of tokens to redeem");

for(uint256 i; i < ids.length; i++){
//we don't need to check the owner of the tokens because this is checked in transferFrom method
this.transferFrom(msg.sender, BurnAddress, ids[i]);

FractionsContract.transfer(msg.sender, amount);

See Also​

Secondary Markets​

  1. Kittens giveaway was mentioned in PurrCast 2020-04-13↩