일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- git add
- 블록체인
- 트러블슈팅
- 인센티브 기반 커뮤니티
- 배팅
- 회로차단
- 프록시패턴
- git commit
- 스테이트머신패턴
- 디자인 패턴
- github 에러
- RBAC
- 일시정지
- 코드리뷰
- 웹툰
- 멀티시그
- 솔리디티
- 토큰노믹스
- 재진입
- solidity
- github
- 투표
- 부트캠프
- 팩토리패턴
- 옵저버패턴
- 싱글톤패턴
- 코드스테이츠
- 업그레이더블 컨트랙트
- 팀 프로젝트
- Today
- Total
보다 더 생생한 기록
[Solidity][코드리뷰] Lazy Minting in OpenSea (오픈씨내에서의 레이지민팅) 본문
1. NFT 발행 시 발생하는 가스비 문제
NFT 크리에이터들은 OpenSea 같은 마켓플레이스에 NFT를 리스팅하고, 일반 유저들에게 NFT를 판매합니다.
만약 어떤 크리에이터가 총 1000개의 NFT를 발행하여 오픈씨에 리스팅하려합니다. 그렇다면 크리에이터는 1000개 민팅에 대한 가스비를 전부 지불해야할까요?
제 경험상, 이더리움 PoS 마이그레이션 이후 현재, NFT 민팅을 진행해보면, 1$에서 많으면 4$에 달하는 가스비를 지불해왔습니다.
이 상황에서 크리에이터는 1000개의 NFT를 발행해야하므로, 2.5$(평균 가스비) x 1000 = 2500$ 즉 한화로 300만원 상당의 가스비를 지불해야합니다. 이 금액은 크리에이터에게 큰 리스크를 가져다 줍니다. 투자한 가스비 이상으로 NFT를 전부 판매하면 이득이겠지만, 수요가 없어 판매하지도 못한다면, 지불했던 가스비는 고스란히 크리에이터의 손해액이 됩니다.
이러한 상황을 해결하기 위해 OpenSea는 Lazy minting을 도입했습니다. OpenSea로 이동해볼까요?
2. OpenSea에서의 Lazy Minting
OpenSea에서 Create 메뉴를 이용하여 본인의 NFT를 만들어봅시다.
이미지와 상세설명을 기입해줍니다.
그 뒤 Create 버튼을 누르면 어떻게 될까요?
별다른 진행상황없이 create 되었다는 팝업이 뜨게됩니다.
이렇게 오픈씨내에서 보이기까지 합니다.
자 그렇다면 현재 NFT는 발행된 것일까요? 또한 온체인에 올라가있는 상태일까요?
그렇지 않습니다.
이제 우측 상단의 Sell 버튼을 눌러, 일반 유저들이 구매할 수 있도록 리스팅해 봅시다.
Complete Listing 버튼을 누르면 아래와 같은 메타마스크 팝업이 뜨게 됩니다.
서명을 눌러보면
위와 같이 리스팅이 완료되었다는 팝업이 뜨게됩니다.
혹시 여태까지의 어떤 과정에서도 NFT 민팅을 위한 가스비 지불을 한적이 없다는것과
오픈씨에 리스팅된 그림은 온체인된 NFT가 아닌 그저 껍데기에 불과한 것을 알고 계셨나요?
이는 OpenSea가 Lazy Minting을 지원하기 때문입니다.
3. Minting vs LazyMinting
일반적인 Minting과 LazyMinting은 가스비를 지불하는 주체가 누구인가로 판가름나게 됩니다.
Minting
1. 일반적인 Minting은 크리에이터가 이미지와 세부사항을 등록함과 동시에 온체인에 기록되고 가스비를 지불하게됩니다.
2. 그렇게 발행된 NFT를 마켓플레이스에 리스팅하여 일반유저가 구매할 수 있도록 합니다.
Lazy Minting
1. Lazy Minting을 이용하면, 똑같이 이미지와 세부사항을 등록하는 것 까진 똑같지만 이 내용들을 해쉬화 하여 signature 를생성시키고, 본인 지갑의 private key를 이용하여 sign까지 해놓습니다.
2. 마켓플레이스에서는 등록한 이미지와 세부사항을 토대로, 실제 민팅된 NFT처럼 마켓플레이스 내에 리스팅해둡니다. 실제로 체인상에 올라가있는 NFT가 아니고, 껍데기만 형성해둔 것입니다.
3. 이제 일반 유저가 NFT를 구매하려고 구매버튼을 누르면, sign된 signature 값을 불러오고 그때서야 가스비를 지불하여 minting이 이뤄지는 것입니다. 즉 껍데기에 불과했던 그림이 NFT로 발행되는 것이죠.
즉 Lazy Minting을 이용하면 가스비에 대한 부담이 작가에게 영향을 주지 않게 되는 것입니다. 천개를 발행하든 만개를 발행하든간에, 실구매자가 구매하기 전까지는 가스비가 지불되지 않다가, 구매버튼을 누르면 그제서야 지불됨과 동시에 NFT 발행이 되는것입니다.
4. Flow of Lazy Minting
아래 코드는 부트캠프내에서 프로젝트를 진행하며 작성했던 코드입니다.
우선 voucher을 생성합니다. 크리에이터 본인이 판매하고싶은 토큰아이디, 가격 그리고 uri를 지정해주는 코드입니다. uri는 ipfs 와 관련된 uri가 들어갑니다. 이 내용은 json 형태로 저장되어 있습니다.
struct NFTVoucher {
uint256 tokenId;
uint256 minPrice;
string uri;
}
아래부터는 유저가 Buy 버튼을 눌러 껍데기 상태의 NFT를 구매할때 실행되는 코드들입니다.
const Sign = async (props) => {
const { token_id, price, totalsupply } = props;
const contractAddress =
const privateKey =
let wallet = new ethers.Wallet(privateKey);
...
let walletWithProvider = new ethers.Wallet(privateKey, provider);
const contract = new ethers.Contract(
contractAddress,
exAbi,
walletWithProvider
);
const msg = [token_id, price, totalsupply];
const msgHx = await contract._hash(msg);
const messageHashBytes = ethers.utils.arrayify(msgHx); // 이 과정을 거쳐야 우리가 원하는 형태의 해쉬값이 나옴
const signature = await wallet.signMessage(messageHashBytes); // 최종 signature 해쉬값
}
크리에이터가 지정했던 voucher의 내용들을 _hash화와 bytes 형태로 바꾸는 작업을 진행합니다.
그 뒤 privateKey를 이용하여 sign하여 해시화된 signature 값을 생성합니다.
const txHash = await contract
.connect(signer)
.mint(
userData.wallet_address,
number,
[token_id, price, totalsupply],
signature,
{
value: totalprice * 10000,
}
);
그 뒤 mint 함수를 이용하여 민팅을 진행합니다. 파라미터로는 해쉬화된 signature 값과, 해쉬화 되기 이전의 voucher 내용들이 들어가야합니다. 그 이유는 아래 솔리디티 코드에서 찾을 수 있습니다.
function mint(address account, uint256 amount, NFTVoucher calldata voucher, bytes memory signature)
public payable returns (uint256)
{
address signer = _verify(voucher, signature);
require(hasRole(MINTER_ROLE,signer),"Signature invalid or unauthorized");
require(msg.value == voucher.Price * amount * toWei);
require(totalSupply(voucher.tokenId) + amount <= voucher.totalSupply);
_mint(signer, voucher.tokenId, amount, "");
_safeTransferFrom(signer,account,voucher.tokenId,amount,"");
ownerprice+=msg.value;
return voucher.tokenId;
}
}
4번째줄에서 _verify라는 함수를 이용해, signature로부터 어떤 지갑 주소가 sign 했는지를 뽑아냅니다. 이때 해쉬화되기 이전의 signature 내용과 voucher가 동일하지 않다면 옳바르지 않은 지갑주소가 나오게됩니다.
4번째줄에서 나온 지갑주소와 크리에이터의 주소가 동일하다면 5번째줄에서 에러가 생기지 않고 밑으로내려가 _mint를 통해 비로소 NFT 민팅이 이뤄지게 됩니다.
'블록체인' 카테고리의 다른 글
[Solidity] 다수의 반환값 처리하기 (0) | 2023.05.26 |
---|---|
[Solidity][코드리뷰] 스테이킹 시스템 코드 분석 (0) | 2023.01.30 |
[Solidity] 크립토좀비 Ch1,2 정리 (0) | 2022.12.26 |
[Solidity] UniSwap v2 - 이론 정리 (0) | 2022.12.25 |
[Solidity] Lazy Minting 코드 분석 (0) | 2022.11.16 |