Skip to content

Instantly share code, notes, and snippets.

@PedroCailleret
Forked from defijesus/cryptoheart.sol
Created July 30, 2022 11:18
Show Gist options
  • Select an option

  • Save PedroCailleret/07be1c5ac62b96c70ca4645a6d86a93d to your computer and use it in GitHub Desktop.

Select an option

Save PedroCailleret/07be1c5ac62b96c70ca4645a6d86a93d to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
// t11s god himself
// βœ… make mintPrice constant
// πŸ”΄ consider removing creators
// πŸ”΄ consider removing ourMessage
// βœ… make heartURIs a mapping of uint256s
// βœ… don't use OZ counters
// βœ… dont use a uint8 for the loop counter (its gonna get cast to 256 bits as thats the evm wordsize)
// βœ… dont cast to a uint8 for digit
// πŸ”΄ the "slow down" ratelimit in mint is basically useless, consider removing
// βœ… don't use uint8 for loop in mint
// βœ… dont use uint8 for loop in setHeartURIs
// βœ… don't use uint8 for loop in setCustomURIs
// βœ… make maxSupply constant
// βœ… precompute the empty hash in a constant for setCustomURIs (keccak256(abi.encodePacked("")))
// βœ… make all arrays args in external funcs `calldata`
// βœ… wrap all ur loop counters in unchecked
// βœ… rule of thumb: always calldata if the compiler will let u
//
// My attempt
// βœ… add custom errors
// βœ… converted creators string[] to string
pragma solidity ^0.8.2;
import "@openzeppelin/contracts@4.4.0/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts@4.4.0/security/Pausable.sol";
import "@openzeppelin/contracts@4.4.0/access/Ownable.sol";
error NonExistantToken();
error SlowDown();
error CorrectChangeOnly();
error TooMany();
error WrongArraySize();
contract CryptoHeart is ERC721, Pausable, Ownable {
// these 2 have to stay
string public constant CREATORS = "defijesus.eth+gbaby.eth+jpegmedia.eth+kingkav.eth";
string public constant README = "People with disabilities have helped us gain a better perspective on life. I hope this project does the same for you.";
uint256 public constant mintPrice = 50000000000000000;
bytes32 private constant emptyString = keccak256(abi.encodePacked(""));
// mapping is cheaper than string[]
mapping(uint256 => string) public heartURIs;
// token ID => custom token URI
mapping(uint256 => string) public customURIs;
uint256 public constant maxSupply = 1000;
uint256 public currentSupply = 0;
constructor(string[] memory _heartURIs) ERC721("CryptoHeart", "HEART") {
unchecked {
for (uint256 i = 0; i < 10; i++) {
heartURIs[i] = _heartURIs[i];
safeMint(msg.sender);
}
}
pause();
}
// CUSTOM FUNCTIONS
// PUBLIC
function tokenURI(uint256 tokenId) public view override returns (string memory) {
if (!_exists(tokenId)) {
revert NonExistantToken();
}
if (keccak256(abi.encodePacked(customURIs[tokenId])) != emptyString) {
return customURIs[tokenId];
}
uint256 digit = uint256(tokenId % 10);
return heartURIs[digit];
}
function mint(uint256 amount) external payable whenNotPaused {
if (amount > 20) {
revert SlowDown();
} else if (msg.value != mintPrice * amount) {
revert CorrectChangeOnly();
} else if (currentSupply + amount > maxSupply) {
revert TooMany();
}
unchecked {
for(uint256 i = 0; i < amount; i++) {
safeMint(msg.sender);
}
}
}
// ONLY OWNER
function setHeartURIs(string[] calldata URIs) external onlyOwner {
if (URIs.length != 10) {
revert WrongArraySize();
}
unchecked {
for (uint256 i = 0; i < URIs.length; i++) {
heartURIs[i] = URIs[i];
}
}
}
function setCustomURIs(uint256[] calldata tokenIDs, string[] calldata tokenURIs) external onlyOwner {
if (tokenIDs.length != tokenURIs.length) {
revert WrongArraySize();
}
unchecked {
for (uint256 i = 0; i < tokenIDs.length; i++) {
if (keccak256(abi.encodePacked(tokenURIs[i])) == emptyString) {
delete customURIs[tokenIDs[i]];
} else {
customURIs[tokenIDs[i]] = tokenURIs[i];
}
}
}
}
function withdrawEther(address payable to) external onlyOwner {
to.call{value: address(this).balance}("");
}
function safeMint(address to) internal {
_safeMint(to, currentSupply);
currentSupply += 1;
}
// DEFAULT FUNCTIONS
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
whenNotPaused
override
{
super._beforeTokenTransfer(from, to, tokenId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment