Skip to content

Instantly share code, notes, and snippets.

@kkszay
Created February 5, 2022 12:21
Show Gist options
  • Save kkszay/411f3cd71e02e3a248eb38f877532643 to your computer and use it in GitHub Desktop.
Save kkszay/411f3cd71e02e3a248eb38f877532643 to your computer and use it in GitHub Desktop.
pragma solidity >=0.4.24 <=0.5.6;
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value -= 1;
}
}
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;
// onKIP17Received bytes value
bytes4 private constant _KIP17_RECEIVED = 0x6745782b;
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _ownedTokensCount;
// mint(tokenId, uri, owner)
// transferFrom(from, to, tokenId)
function mintWithTokenURI(address to, uint256 tokenId, string memory tokenURI) public returns (bool) {
// to에게 tokenId(일련번호)를 발행하겠다.
// 적힐 글자는 tokenURI
tokenOwner[tokenId] = to;
tokenURIs[tokenId] = tokenURI;
_ownedTokens[to].push(tokenId);
_ownedTokensCount[to].increment();
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;
_ownedTokensCount[from].decrement();
_ownedTokensCount[to].increment();
// 만약에 받는쪽이 실행할 코드가 있는 스마트 컨트랙트이면 코드를 실행할 것
require(
_checkOnKIP17Received(from, to, tokenId, _data), "KIP17: transfer to non KIP17Receiver implementer"
);
}
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;
}
// 해당 주소가 갖고있는 NFT의 갯수
function balanceOf(address owner) public view returns (uint256) {
require(
owner != address(0),
"KIP17: balance query for the zero address"
);
return _ownedTokensCount[owner].current();
}
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function _removeTokenFromList(address from, uint256 tokenId) private {
// [10, 15, 19, 20] -> 19번 삭제
// [10, 15, 20, 19]
// [10, 15, 20]
uint256 lastTokenIndex = _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][lastTokenIndex];
_ownedTokens[from][lastTokenIndex] = 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;
}
}
contract NFTMarket {
mapping(uint256 => address) public seller;
function buyNFT(uint256 tokenId, address NFTAddress) public payable returns (bool) {
// 구매한 사람한테 0.01 KLAY전송
address payable receiver = address(uint160(seller[tokenId]));
// Send 0.01 KLAY to receiver
// 10 ** 18 PEB = 1 KLAY
// 10 ** 16 PEB = 0.01 KLAY
receiver.transfer(10 ** 16);
NFTSimple(NFTAddress).safeTransferFrom(address(this), msg.sender, tokenId, '0x00');
return true;
}
// Market이 토큰을 받았을 때 (판매대에 올라갔을 때), 판매자가 누구인지 기록해야함
function onKIP17Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4){
seller[tokenId] = from;
return bytes4(keccak256("onKIP17Received(address,address,uint256,bytes)"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment