-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNFTSimple.sol
138 lines (120 loc) · 4.07 KB
/
NFTSimple.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Klaytn IDE uses solidity 0.4.24, 0.5.6 versions.
pragma solidity >=0.4.24 <=0.5.6;
contract NFTSimple {
string public name = "KlayLion";
string public symbol = "KL";
mapping(uint256 => address) public tokenOwner;
mapping(uint256 => string) public tokenURIs;
// 소유한 토큰 리스트
mapping(address => uint256[]) private _ownedTokens;
bytes4 private constant _KIP17_RECEIVED = 0x6745782b;
// mint(tokenId, uri, owner)
// transferFrom(from, to, tokenId) -> owner가 바뀌는 것(from -> to)
function mintWithTokenURI(
address to,
uint256 tokenId,
string memory tokenURI
) public returns (bool) {
// to에게 tokenId(일련번호)를 발행하겠다.
// 적힐 글자는 tokenURI
tokenOwner[tokenId] = to;
tokenURIs[tokenId] = tokenURI;
// add token to the list
_ownedTokens[to].push(tokenId);
return true;
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public {
require(from == msg.sender, "from != msg.sender");
require(
from == tokenOwner[tokenId],
"you are not the owner of the token"
);
//
_removeTokenFromList(from, tokenId);
_ownedTokens[to].push(tokenId);
//
tokenOwner[tokenId] = to;
//
require(
_checkOnKIP17Received(from, to, tokenId, _data),
"KIP17: transfer to non KIP17Receiver implementer"
);
}
function _removeTokenFromList(address from, uint256 tokenId) private {
// [10, 15, 19, 20] -> 19번을 삭제 하고 싶어요
// [20, 15, 20, 19]
// [10, 15, 20]
uint256 lastTokenIdex = _ownedTokens[from].length - 1;
for (uint256 i = 0; i < _ownedTokens[from].length; i++) {
if (tokenId == _ownedTokens[from][i]) {
// Swap last token with deleting token;
_ownedTokens[from][i] = _ownedTokens[from][lastTokenIdex];
_ownedTokens[from][lastTokenIdex] = tokenId;
break;
}
}
//
_ownedTokens[from].length--;
}
function ownedTokens(address owner) public view returns (uint256[] memory) {
return _ownedTokens[owner];
}
function setTokenUri(uint256 id, string memory uri) public {
tokenURIs[id] = uri;
}
function _checkOnKIP17Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal returns (bool) {
bool success;
bytes memory returndata;
if (!isContract(to)) {
return true;
}
(success, returndata) = to.call(
abi.encodeWithSelector(
_KIP17_RECEIVED,
msg.sender,
from,
tokenId,
_data
)
);
if (
returndata.length != 0 &&
abi.decode(returndata, (bytes4)) == _KIP17_RECEIVED
) {
return true;
}
return false;
}
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(account)
}
return size > 0;
}
/// @notice Count all NFTs assigned to an owner
/// @dev NFTs assigned to the zero address are considered invalid, and this function throws for queries about the zero address.
/// @param owner An address for whom to query the balance
/// @return The number of NFTs owned by `owner`, possibly zero
function balanceOf(address owner) public view returns (uint256) {
require(
owner != address(0),
"KIP17: balance query for the zero address"
);
return _ownedTokens[owner].length;
}
}