Closed earth2travis closed 5 days ago
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
contract TestWe is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Pausable, Ownable, ERC721Burnable {
uint256 private _nextTokenId;
constructor(address initialOwner)
ERC721("Test We", "TEST")
Ownable(initialOwner)
{}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi";
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
function safeMint(address to, string memory uri) public onlyOwner {
uint256 tokenId = _nextTokenId++;
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
// The following functions are overrides required by Solidity.
function _update(address to, uint256 tokenId, address auth)
internal
override(ERC721, ERC721Enumerable, ERC721Pausable)
returns (address)
{
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value)
internal
override(ERC721, ERC721Enumerable)
{
super._increaseBalance(account, value);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable, ERC721URIStorage)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
Updated remappings.txt
to:
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
And ran:
forge remappings
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ forge-std/=lib/forge-std/src/
forge build
Is producing the following error:
failed to resolve file: "/Users/earth/Sites/crypto/DAO/warframes/mint/contracts/lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol": No such file or directory (os error 2); check configured remappings
--> /Users/earth/Sites/crypto/DAO/warframes/mint/contracts/src/TestWe.sol
@openzeppelin/contracts/token/ERC721/ERC721.sol
Think I may have installed Open Zeppelin in the directory above Contracts
Ran:
forge install OpenZeppelin/openzeppelin-contracts
And deleted mint/lib
forge remappings
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
forge-std/=lib/forge-std/src/
openzeppelin-contracts/=lib/openzeppelin-contracts/
forge build
[⠊] Compiling...
[⠊] Compiling 22 files with Solc 0.8.23
[⠒] Solc 0.8.23 finished in 940.75ms
Compiler run successful!
Removed the argument in the Constructor and just used msg.sender as the owner, i.e. whoever deploys the contract will be the owner.
Changed:
constructor(address initialOwner)
ERC721("Test We", "TEST")
Ownable(initialOwner)
{}
to:
constructor()
ERC721("Test We", "TEST")
Ownable(msg.sender)
{}
Removed the restriction of onlyOwner on the safeMint function. This allows people to mint their own NFT but of course adjust based on your needs.
Changed:
function safeMint(address to, string memory uri) public onlyOwner {
uint256 tokenId = _nextTokenId++;
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
to:
function safeMint(address to, string memory uri) public {
uint256 tokenId = _nextTokenId++;
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
From How to Mint NFTs with Foundry, Viem, and Pinata
forge build
[⠊] Compiling...
[⠊] Compiling 1 files with Solc 0.8.23
[⠒] Solc 0.8.23 finished in 887.25ms
Compiler run successful!
Added TestWe.t.sol
(updated in https://github.com/onchain-warfare/contracts/issues/1)
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
import {Test, console} from "forge-std/Test.sol";
import {TestWe} from "../src/TestWe.sol";
contract TestWeTest is Test {
TestWe instance;
address owner;
address recipient;
function setUp() public {
instance = new TestWe();
owner = address(this);
recipient = makeAddr("recipient");
}
function testSafeMint() public {
string memory tokenURI = "ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi";
instance.safeMint(recipient, tokenURI);
assertEq(instance.ownerOf(0), recipient);
assertEq(instance.tokenURI(0), tokenURI);
}
}
forge test
[⠒] Compiling...
No files changed, compilation skipped
Ran 1 test for test/TestWe.t.sol:TestWeTest
[FAIL. Reason: assertion failed: ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPiipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi != ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi] testSafeMint() (gas: 191891)
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 1.30ms (166.31µs CPU time)
Ran 1 test suite in 339.68ms (1.30ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/TestWe.t.sol:TestWeTest
[FAIL. Reason: assertion failed: ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPiipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi != ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi] testSafeMint() (gas: 191891)
Encountered a total of 1 failing tests, 0 tests succeeded
The error you are encountering is due to the tokenURI function returning a concatenation of the base URI and the provided token URI, rather than just the provided token URI. This results in a mismatch when comparing the expected URI with the returned URI.
To account for the base URI in the test without changing TestWe.sol, you can concatenate the base URI with the provided token URI in the test file. Here is the modified TestWe.t.sol:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
import {Test, console} from "forge-std/Test.sol";
import {TestWe} from "../src/TestWe.sol";
contract TestWeTest is Test {
TestWe instance;
address owner;
address recipient;
string constant baseURI = "ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi";
function setUp() public {
instance = new TestWe();
owner = address(this);
recipient = makeAddr("recipient");
}
function testSafeMint() public {
string memory tokenURI = "ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi";
instance.safeMint(recipient, tokenURI);
assertEq(instance.ownerOf(0), recipient);
assertEq(instance.tokenURI(0), string(abi.encodePacked(baseURI, tokenURI)));
}
}
forge test
[⠒] Compiling...
[⠒] Compiling 1 files with Solc 0.8.23
[⠑] Solc 0.8.23 finished in 3.53s
Compiler run successful!
Ran 1 test for test/TestWe.t.sol:TestWeTest
[PASS] testSafeMint() (gas: 192663)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 50.96ms (2.51ms CPU time)
Ran 1 test suite in 380.73ms (50.96ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
forge create src/TestWe.sol:TestWe \
--rpc-url https://sepolia.base.org \
--private-key <PRIVATE_KEY>
[⠒] Compiling...
No files changed, compilation skipped
Deployer: 0x1a75971C77957d26f8D81C29f9A2093f5F989Dd5
Deployed to: 0x5324735Aa67FaE868C90795CBbAD9F78700664dD
Transaction hash: 0x31c1f682e83d9188174516420ffd21626f72d2ff04a51d90097ef53422be7081
https://sepolia.basescan.org/address/0x5324735Aa67FaE868C90795CBbAD9F78700664dD
forge v 0x5324735Aa67FaE868C90795CBbAD9F78700664dD \
src/TestWe.sol:TestWe \
-e <ETHERSCAN_API_KEY> \
--rpc-url https://sepolia.base.org
Start verifying contract `0x5324735Aa67FaE868C90795CBbAD9F78700664dD` deployed on base-sepolia
Submitting verification for [src/TestWe.sol:TestWe] 0x5324735Aa67FaE868C90795CBbAD9F78700664dD.
Submitted contract for verification:
Response: `OK`
GUID: `ayycj2dznfktfyzjfda8haan8yyzqwyemnvkmgzybguzbpvajr`
URL: https://sepolia.basescan.org/address/0x5324735aa67fae868c90795cbbad9f78700664dd
https://sepolia.basescan.org/address/0x5324735Aa67FaE868C90795CBbAD9F78700664dD
ipfs://QmYNsRQWtiC37rkf66gxPSvu4FRtFWp2kgMU9z2yi1HfPi (shall-we.json
)
https://sepolia.basescan.org/tx/0x2e568d31c57d61c8b03d0c1c3bc22f966acb7a1628111cae2b1d293ca2d86a4b
https://testnets.opensea.io/assets/base-sepolia/0x5324735aa67fae868c90795cbbad9f78700664dd/0
safeMint
?)#0
(Should probably start with #1
.)safeMint
ipfs://QmSouB7L7mVsonRtp168ybpFkQThwmtZLeanjJ6uynY1bs (shall-we.png
)
https://sepolia.basescan.org/tx/0x6a66a61f3c66664cc84415d4bd4ae16373c0c8e76c27af3c7683b334faa89674
https://testnets.opensea.io/assets/base-sepolia/0x5324735aa67fae868c90795cbbad9f78700664dd/1
+Unknown NFT onchain-warfare/mint#1
Moved repo to: https://github.com/onchain-warfare/contracts
TestWe.sol
ERC-721 contract is deployed. Moving resolution of issues to https://github.com/onchain-warfare/contracts/issues/3
New Foundry Project and OpenZeppelin contracts installed in issue https://github.com/onchain-warfare/mint/issues/6
TestWe.sol
ERC-721 contractTestWe.t.sol