Skip to content

Commit

Permalink
Charge on mints optionally
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmichalis committed Feb 13, 2024
1 parent 00e9e0c commit b600889
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 12 deletions.
28 changes: 23 additions & 5 deletions src/DynamicTokenURI.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,25 @@ contract DynamicTokenURI is
ICreatorExtensionTokenURI,
IERC721CreatorExtensionApproveTransfer
{
// Immutable storage
// Cost to mint a token
uint256 public immutable mintCost;
// Total supply of tokens meant to be minted with this extension
uint256 public immutable maxSupply;
uint256 public minted;
// Manifold creator contract
IERC721CreatorCore public immutable creatorContract;

// Mutable storage
// Amount of tokens currently minted with this extension
uint256 public minted;
// Base URI for token URIs
string public baseURI;
mapping(uint256 => uint256) private tokenIdToMetadataId;

constructor(address creatorContract_, string memory baseURI_, uint256 maxSupply_) Ownable() {
constructor(
address creatorContract_,
string memory baseURI_,
uint256 maxSupply_,
uint256 mintCost_
) Ownable() {
require(
ERC165Checker.supportsInterface(creatorContract_, type(IERC721CreatorCore).interfaceId),
"creator must implement IERC721CreatorCore"
Expand All @@ -38,6 +46,7 @@ contract DynamicTokenURI is
creatorContract = IERC721CreatorCore(creatorContract_);
baseURI = baseURI_;
maxSupply = maxSupply_;
mintCost = mintCost_;
}

function setBaseURI(string memory baseURI_) external onlyOwner {
Expand Down Expand Up @@ -114,9 +123,18 @@ contract DynamicTokenURI is
return true;
}

function mint() external returns (uint256) {
function mint() external payable returns (uint256) {
require(msg.value == mintCost, "insufficient funds");
uint256 tokensMinted = minted;
require(tokensMinted < maxSupply, "mint complete");

// Transfer mint cost to owner
if (msg.value != 0) {
(bool success,) = owner().call{value: msg.value}("");
require(success, "transfer failed");
}

// Mint a token to the caller
unchecked {
// realistically never overflows
++tokensMinted;
Expand Down
29 changes: 22 additions & 7 deletions test/DynamicTokenURI.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ contract DynamicTokenURITest is Test {

// data
string baseURI = "ipfs://ipfs/examplevhbgbfjdg/";
uint256 maxSupply = 24;
uint256 mintCost = 0.1 ether;

function setUp() public {
// Deploy the creator contract
Expand All @@ -32,11 +34,14 @@ contract DynamicTokenURITest is Test {

// Deploy the extension contract
vm.prank(creator);
extension = new DynamicTokenURI(address(token), baseURI, 24);
extension = new DynamicTokenURI(address(token), baseURI, maxSupply, mintCost);

// Register the extension in the creator contract
vm.prank(creator);
token.registerExtension(address(extension), "");

vm.deal(alice, 10 ether);
vm.deal(bob, 10 ether);
}

function testSupportsInterface() public view {
Expand All @@ -53,13 +58,19 @@ contract DynamicTokenURITest is Test {
}

function testSimpleMintAndTransfer() public {
uint256 balanceBefore = address(creator).balance;

// 1. Alice mints a token
vm.prank(alice);
uint256 tokenId = extension.mint();
uint256 tokenId = extension.mint{value: mintCost}();
string memory aliceURI = token.tokenURI(tokenId);
string memory expectedAliceURI = string(abi.encodePacked(baseURI, "1.json"));
assertEq(aliceURI, expectedAliceURI);

// Check owner balance
uint256 balanceAfter = address(creator).balance;
assertEq(balanceAfter - balanceBefore, mintCost);

// 2. Alice transfers the token to Bob. The URI should change
vm.prank(alice);
token.transferFrom(alice, bob, tokenId);
Expand All @@ -71,10 +82,9 @@ contract DynamicTokenURITest is Test {
function testTransferUpToMaxChange() public {
// 1. Alice mints a token
vm.prank(alice);
uint256 tokenId = extension.mint();
uint256 tokenId = extension.mint{value: mintCost}();

// 2. Token URI changes up to maxSupply
uint256 maxSupply = extension.maxSupply();
address owner = alice;
address recipient = bob;
string memory lastURI;
Expand Down Expand Up @@ -139,17 +149,22 @@ contract DynamicTokenURITest is Test {
}

function testCannotMintMoreThanMaxSupply() public {
uint256 balanceBefore = address(creator).balance;

// Mint up to maxSupply
uint256 maxSupply = extension.maxSupply();
for (uint256 i = 0; i < maxSupply; i++) {
vm.prank(alice);
extension.mint();
extension.mint{value: mintCost}();
}
assertEq(token.balanceOf(alice), maxSupply);

// Check owner balance
uint256 balanceAfter = address(creator).balance;
assertEq(balanceAfter - balanceBefore, mintCost * maxSupply);

// Cannot mint more
vm.prank(alice);
vm.expectRevert("mint complete");
extension.mint();
extension.mint{value: mintCost}();
}
}

0 comments on commit b600889

Please sign in to comment.