Contract Source Code:
// SPDX-License-Identifier: CC0
/*
/$$$$$$$$ /$$$$$$$ /$$$$$$$$ /$$$$$$$$ /$$$$$$ /$$$$$$$
| $$_____/| $$__ $$| $$_____/| $$_____/ /$$__ $$| $$____/
| $$ | $$ \ $$| $$ | $$ |__/ \ $$| $$
| $$$$$ | $$$$$$$/| $$$$$ | $$$$$ /$$$$$$/| $$$$$$$
| $$__/ | $$__ $$| $$__/ | $$__/ /$$____/ |_____ $$
| $$ | $$ \ $$| $$ | $$ | $$ /$$ \ $$
| $$ | $$ | $$| $$$$$$$$| $$$$$$$$ | $$$$$$$$| $$$$$$/
|__/ |__/ |__/|________/|________/ |________/ \______/
/$$
| $$
| $$$$$$$ /$$ /$$
| $$__ $$| $$ | $$
| $$ \ $$| $$ | $$
| $$ | $$| $$ | $$
| $$$$$$$/| $$$$$$$
|_______/ \____ $$
/$$ | $$
| $$$$$$/
\______/
/$$$$$$ /$$$$$$$$ /$$$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$$ /$$$$$$$
/$$__ $$|__ $$__/| $$_____/| $$ | $$|_ $$_/| $$_____/| $$__ $$
| $$ \__/ | $$ | $$ | $$ | $$ | $$ | $$ | $$ \ $$
| $$$$$$ | $$ | $$$$$ | $$ / $$/ | $$ | $$$$$ | $$$$$$$/
\____ $$ | $$ | $$__/ \ $$ $$/ | $$ | $$__/ | $$____/
/$$ \ $$ | $$ | $$ \ $$$/ | $$ | $$ | $$
| $$$$$$/ | $$ | $$$$$$$$ \ $/ /$$$$$$| $$$$$$$$| $$
\______/ |__/ |________/ \_/ |______/|________/|__/
CC0 2023
*/
pragma solidity ^0.8.23;
import "./FreeChecker.sol";
interface ColdHardCash {
function ownerOf(uint256) external view returns (address);
function isRedeemed(uint256) external view returns (bool);
}
contract Free25 is FreeChecker {
mapping(uint256 => address) public cashToMinter;
ColdHardCash public cash = ColdHardCash(0x6DEa3f6f1bf5ce6606054BaabF5452726Fe4dEA1);
function setMinter(uint256 cashTokenId, address minter) external {
require(cash.ownerOf(cashTokenId) == msg.sender, 'Not owner of CASH token');
require(cash.isRedeemed(cashTokenId), 'CASH token not redeemed');
cashToMinter[cashTokenId] = minter;
}
function claim(uint256 free0TokenId, uint256 cashTokenId) external {
preCheck(free0TokenId, '25');
require(cashToMinter[cashTokenId] == msg.sender, 'Address cannot mint');
postCheck(free0TokenId, 25, '25');
}
}
// SPDX-License-Identifier: CC0
/*
CC0 2023
*/
pragma solidity ^0.8.23;
interface IFree {
function totalSupply() external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function ownerOf(uint256 tokenId) external view returns (address owner);
function tokenIdToCollectionId(uint256 tokenId) external view returns (uint256 collectionId);
function collectionSupply(uint256 collectionId) external view returns (uint256);
function collectionIdToMinter(uint256 collectionId) external view returns (address);
function mint(uint256 collectionId, address to) external;
function appendAttributeToToken(uint256 tokenId, string memory attrKey, string memory attrValue) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
}
abstract contract FreeChecker {
mapping(uint256 => bool) public free0TokenIdUsed;
IFree public immutable free = IFree(0x30b541f1182ef19c56a39634B2fdACa5a0F2A741);
function preCheck(uint256 free0TokenId, string memory freeStr) internal view {
require(free.tokenIdToCollectionId(free0TokenId) == 0, 'Invalid Free0');
require(!free0TokenIdUsed[free0TokenId],
string(abi.encodePacked('This Free0 has already been used to mint a Free', freeStr))
);
require(free.ownerOf(free0TokenId) == msg.sender, 'You must be the owner of this Free0');
}
function postCheck(uint256 free0TokenId, uint256 freeNumber, string memory freeStr) internal {
free0TokenIdUsed[free0TokenId] = true;
free.appendAttributeToToken(free0TokenId,
string(abi.encodePacked('Used For Free', freeStr, ' Mint')),
'true'
);
free.mint(freeNumber, msg.sender);
}
function checkFreeToken(uint256 freeTokenId, uint256 collectionId) internal view {
require(free.ownerOf(freeTokenId) == msg.sender, 'Not owner of token');
require(free.tokenIdToCollectionId(freeTokenId) == collectionId, 'Token collection mismatch');
}
}