adjust contract and add partial test

This commit is contained in:
han 2025-01-17 00:36:33 +07:00
parent 1e79751809
commit b883596a4e
2 changed files with 113 additions and 8 deletions

View File

@ -2,23 +2,61 @@
pragma solidity 0.8.28;
import {ERC721} from "solmate/tokens/ERC721.sol";
import {Ownable} from "openzeppelin-contracts/access/Ownable.sol";
import {Strings} from "openzeppelin-contracts/utils/Strings.sol";
contract NFT is ERC721 {
contract NFT is ERC721, Ownable {
using Strings for uint256;
string public baseURI;
uint256 public currentTokenId;
uint256 public constant TOTAL_SUPPLY = 10_000;
uint256 public constant MINT_PRICE = 0.08 ether;
error MintPriceNotPaid();
error MaxSupply();
error NonExistentTokenURI();
error WithdrawTransfer();
constructor(
string memory _name,
string memory _symbol
) ERC721(_name, _symbol) {}
string memory _symbol,
string memory _baseURI
) ERC721(_name, _symbol) Ownable(msg.sender) {
baseURI = _baseURI;
}
function mintTo(address recipient) public payable returns (uint256) {
uint256 newItemId = ++currentTokenId;
_safeMint(recipient, newItemId);
return newItemId;
if (msg.value != MINT_PRICE) {
revert MintPriceNotPaid();
}
uint256 newTokenId = currentTokenId + 1;
if (newTokenId > TOTAL_SUPPLY) {
revert MaxSupply();
}
currentTokenId = newTokenId;
_safeMint(recipient, newTokenId);
return newTokenId;
}
function tokenURI(uint256 id) public view virtual override returns (string memory) {
return Strings.toString(id);
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (ownerOf(tokenId) == address(0)) {
revert NonExistentTokenURI();
}
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
function withdrawPayments(address payable payee) external onlyOwner {
if (address(this).balance == 0) {
revert WithdrawTransfer();
}
payable(payee).transfer(address(this).balance);
}
function _checkOwner() internal view override {
require(msg.sender == owner(), "Onable: caller is not the owner");
}
}

67
test/NFT.t.sol Normal file
View File

@ -0,0 +1,67 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.28;
import {stdStorage, StdStorage, Test} from "forge-std/Test.sol";
import {NFT} from "src/NFT.sol";
contract NFTTest is Test {
using stdStorage for StdStorage;
NFT private nft;
function setUp() public {
nft = new NFT("NFT_Tutorial", "TUT", "baseUri");
}
function test_RevertMintWithoutValue() public {
vm.expectRevert(NFT.MintPriceNotPaid.selector);
nft.mintTo(address(1));
}
function test_MintPricePaid() public {
nft.mintTo{value: 0.08 ether}(address(1));
}
function test_RevertMintMaxSupplyReached() public {
string memory signature = "currentTokenId()";
uint256 slot = stdstore.target(address(nft)).sig(signature).find();
bytes32 loc = bytes32(slot);
bytes32 mockedCurrentTokenId = bytes32(abi.encode(10000));
vm.store(address(nft), loc, mockedCurrentTokenId);
vm.expectRevert(NFT.MaxSupply.selector);
nft.mintTo{value: 0.08 ether}(address(1));
}
function test_RevertMintToZeroAddress() public {
vm.expectRevert("INVALID_RECIPIENT");
nft.mintTo{value: 0.08 ether}(address(0));
}
function test_NewMintOwnerRegistered() public {
nft.mintTo{value: 0.08 ether}(address(1));
uint256 slotOfNewOwner = stdstore.target(address(nft)).sig(nft.ownerOf.selector).with_key(address(1)).find();
uint160 ownerOfTokenIdOne = uint160(
uint256(
(vm.load(address(nft), bytes32(abi.encode(slotOfNewOwner))))
)
);
assertEq(address(ownerOfTokenIdOne), address(1));
}
function test_BalanceIncremented() public {
nft.mintTo{value: 0.08 ether}(address(1));
uint256 slotBalance = stdstore.target(address(nft)).sig(nft.balanceOf.selector).with_key(address(1)).find();
uint256 balanceFirstMint = uint256(
vm.load(address(nft), bytes32(slotBalance))
);
assertEq(balanceFirstMint, 1);
nft.mintTo{value: 0.08 ether}(address(1));
uint256 balanceSecondMint = uint256(
vm.load(address(nft), bytes32(slotBalance))
);
assertEq(balanceSecondMint, 2);
}
}