Skip to content

Commit b0427a8

Browse files
authored
Merge pull request #1 from Juan-Fuente-T/NFT_branch
CatapultNFT branch
2 parents 568af09 + 216b773 commit b0427a8

File tree

2 files changed

+247
-0
lines changed

2 files changed

+247
-0
lines changed

script/Deploy.s.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ contract DeploySiege is Script {
1212

1313
vm.startBroadcast(deployerPrivateKey);
1414

15+
new CatapultNFT("https://ipfs.io/ipfs/QmUCd8sGk4uVhGFfXX5aixNod3Eky8kD4Cvjo25UDnhPrQ")
1516
new BatteringRam(50);
1617
new Catapult(100);
1718
new Trebuchet(200, msg.sender);

src/CatapultNFT

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// SPDX-License-Identifier: AGPL-3.0-only
2+
pragma solidity >=0.8.20;
3+
4+
import "@openzeppelin/contracts/utils/Strings.sol";
5+
6+
/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
7+
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
8+
contract ERC721 {
9+
using Strings for uint256;
10+
/*//////////////////////////////////////////////////////////////
11+
EVENTS
12+
//////////////////////////////////////////////////////////////*/
13+
14+
event Transfer(address indexed from, address indexed to, uint256 indexed id);
15+
16+
event Approval(address indexed owner, address indexed spender, uint256 indexed id);
17+
18+
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
19+
20+
/*//////////////////////////////////////////////////////////////
21+
METADATA STORAGE/LOGIC
22+
//////////////////////////////////////////////////////////////*/
23+
24+
string public name = "Catapulta NFT";
25+
26+
string public symbol = "CNFT";
27+
28+
string internal baseURI;
29+
30+
uint256 public tokenId;
31+
32+
// function tokenURI(uint256 id) public view virtual returns (string memory){
33+
// return tokenURI(id);
34+
// };
35+
36+
/*//////////////////////////////////////////////////////////////
37+
ERC721 BALANCE/OWNER STORAGE
38+
//////////////////////////////////////////////////////////////*/
39+
40+
mapping(uint256 => address) internal _ownerOf;
41+
42+
mapping(address => uint256) internal _balanceOf;
43+
44+
function ownerOf(uint256 id) public view virtual returns (address owner) {
45+
require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
46+
}
47+
48+
function balanceOf(address owner) public view virtual returns (uint256) {
49+
require(owner != address(0), "ZERO_ADDRESS");
50+
51+
return _balanceOf[owner];
52+
}
53+
54+
/*//////////////////////////////////////////////////////////////
55+
ERC721 APPROVAL STORAGE
56+
//////////////////////////////////////////////////////////////*/
57+
58+
mapping(uint256 => address) public getApproved;
59+
60+
mapping(address => mapping(address => bool)) public isApprovedForAll;
61+
62+
/*//////////////////////////////////////////////////////////////
63+
CONSTRUCTOR
64+
//////////////////////////////////////////////////////////////*/
65+
66+
constructor(string memory _baseURI) {
67+
baseURI = _baseURI;
68+
_mint(msg.sender, tokenId);
69+
}
70+
71+
/*//////////////////////////////////////////////////////////////
72+
ERC721 LOGIC
73+
//////////////////////////////////////////////////////////////*/
74+
75+
function approve(address spender, uint256 id) public virtual {
76+
address owner = _ownerOf[id];
77+
78+
require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
79+
80+
getApproved[id] = spender;
81+
82+
emit Approval(owner, spender, id);
83+
}
84+
85+
function setApprovalForAll(address operator, bool approved) public virtual {
86+
isApprovedForAll[msg.sender][operator] = approved;
87+
88+
emit ApprovalForAll(msg.sender, operator, approved);
89+
}
90+
91+
function transferFrom(
92+
address from,
93+
address to,
94+
uint256 id
95+
) public virtual {
96+
require(from == _ownerOf[id], "WRONG_FROM");
97+
98+
require(to != address(0), "INVALID_RECIPIENT");
99+
100+
require(
101+
msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
102+
"NOT_AUTHORIZED"
103+
);
104+
105+
// Underflow of the sender's balance is impossible because we check for
106+
// ownership above and the recipient's balance can't realistically overflow.
107+
unchecked {
108+
_balanceOf[from]--;
109+
110+
_balanceOf[to]++;
111+
}
112+
113+
_ownerOf[id] = to;
114+
115+
delete getApproved[id];
116+
117+
emit Transfer(from, to, id);
118+
}
119+
120+
function safeTransferFrom(
121+
address from,
122+
address to,
123+
uint256 id
124+
) public virtual {
125+
transferFrom(from, to, id);
126+
127+
require(
128+
to.code.length == 0 ||
129+
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
130+
ERC721TokenReceiver.onERC721Received.selector,
131+
"UNSAFE_RECIPIENT"
132+
);
133+
}
134+
135+
function safeTransferFrom(
136+
address from,
137+
address to,
138+
uint256 id,
139+
bytes calldata data
140+
) public virtual {
141+
transferFrom(from, to, id);
142+
143+
require(
144+
to.code.length == 0 ||
145+
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
146+
ERC721TokenReceiver.onERC721Received.selector,
147+
"UNSAFE_RECIPIENT"
148+
);
149+
}
150+
151+
function tokenURI(uint256 id) public view virtual returns (string memory) {
152+
return string(abi.encodePacked(baseURI, "/", Strings.toString(id), ".json"));
153+
}
154+
155+
/*//////////////////////////////////////////////////////////////
156+
ERC165 LOGIC
157+
//////////////////////////////////////////////////////////////*/
158+
159+
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
160+
return
161+
interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
162+
interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
163+
interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
164+
}
165+
166+
/*//////////////////////////////////////////////////////////////
167+
INTERNAL MINT/BURN LOGIC
168+
//////////////////////////////////////////////////////////////*/
169+
170+
function _mint(address to, uint256 id) internal virtual {
171+
require(to != address(0), "INVALID_RECIPIENT");
172+
173+
require(_ownerOf[id] == address(0), "ALREADY_MINTED");
174+
175+
// Counter overflow is incredibly unrealistic.
176+
unchecked {
177+
_balanceOf[to]++;
178+
}
179+
180+
_ownerOf[id] = to;
181+
182+
emit Transfer(address(0), to, id);
183+
184+
tokenId++;
185+
}
186+
187+
function _burn(uint256 id) internal virtual {
188+
address owner = _ownerOf[id];
189+
190+
require(owner != address(0), "NOT_MINTED");
191+
192+
// Ownership check above ensures no underflow.
193+
unchecked {
194+
_balanceOf[owner]--;
195+
}
196+
197+
delete _ownerOf[id];
198+
199+
delete getApproved[id];
200+
201+
emit Transfer(owner, address(0), id);
202+
}
203+
204+
/*//////////////////////////////////////////////////////////////
205+
INTERNAL SAFE MINT LOGIC
206+
//////////////////////////////////////////////////////////////*/
207+
208+
function _safeMint(address to, uint256 id) internal virtual {
209+
_mint(to, id);
210+
211+
require(
212+
to.code.length == 0 ||
213+
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
214+
ERC721TokenReceiver.onERC721Received.selector,
215+
"UNSAFE_RECIPIENT"
216+
);
217+
}
218+
219+
function _safeMint(
220+
address to,
221+
uint256 id,
222+
bytes memory data
223+
) internal virtual {
224+
_mint(to, id);
225+
226+
require(
227+
to.code.length == 0 ||
228+
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
229+
ERC721TokenReceiver.onERC721Received.selector,
230+
"UNSAFE_RECIPIENT"
231+
);
232+
}
233+
}
234+
235+
/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
236+
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
237+
abstract contract ERC721TokenReceiver {
238+
function onERC721Received(
239+
address,
240+
address,
241+
uint256,
242+
bytes calldata
243+
) external virtual returns (bytes4) {
244+
return ERC721TokenReceiver.onERC721Received.selector;
245+
}
246+
}

0 commit comments

Comments
 (0)