NFTs in zkSync 1.x を試す
セットアップ
yarn add zksync@beta ethers
適当にドキュメントを読む
To mint an NFT, we will introduce a new opcode MINT_NFT with arguments:
新しいオペコードってなんの基盤でのオペコードなんだ...?
Enforcing Uniqueness
NFT の token id は必ずインクリメントされるし、あるアカウントが mint するたびに serial id もインクリメントされる?
目的はユニークにするため
getTransactionFee
で手数料を計算
mint のインタフェース
recipient
が受け取り手で、contentHash
が NFT を一意に表す32Byteの値。token id とは別に contentHash が必要なんだ
async mintNFT(mintNft: {
recipient: string;
contentHash: string;
feeToken: TokenLike;
fee?: BigNumberish;
nonce?: Nonce;
}): Promise<Transaction>
NFT を見る方法
state.committed.nfts
で参照できるの面白い。たしか state.committed
以下に FT の情報もあったよね
// Get state of account
const state = await syncWallet.getAccountState('<account-address>');
// View committed NFTs
console.log(state.committed.nfts);
// View verified NFTs
console.log(state.verified.nfts);
Swap
atomically swap
ができる。便利
one NFT for another NFT
one NFT for fungible tokens (buying the NFT)
Buy / Sell NFTs
トークンの売買のインタフェースもある
使える FT は https://zkscan.io/explorer/tokens/ にあるやつだけ
syncSwap
や getOrder
はプリミティブな命令に対応してるのか、syncTransferNFT
などの応用なのかどっちなんだろう
Withdrawal to Layer 1
Withdrawals to L1 will require 3 actors:
Factory: L1 contract that can mint L1 NFT tokens
Creator: user which mints NFT on L2
NFTOwner: user which owns NFT on L2
Creator が必要なのは意外、Creator が拒否すれば Owner が望んでも L1 に退避できないんだろうか
This guide will demonstrate 2 types of withdrawals: normal and emergency, and explain under what conditions each type should be used.
normal
と emergency
の2つがある
normal
は withdrawNFT
で、emergency
は emergencyWithdraw
を使う
Factory and zkSync Smart Contract Interaction
registerFactory
は↑の Factory を登録するためのもの?
mint してみる
まずはデポジット
async function deposit() {
const { syncWallet } = await getProviderAndWallet();
const deposit = await syncWallet.depositToSyncFromEthereum({
depositTo: syncWallet.address(),
token: "ETH",
amount: ethers.utils.parseEther("0.01"),
});
console.log({ deposit });
}
アンロックする
async function unlock() {
const { syncWallet } = await getProviderAndWallet();
const changePubkey = await syncWallet.setSigningKey({
feeToken: "ETH",
ethAuthType: "ECDSA",
});
console.log({ changePubkey });
// Wait until the tx is committed
await changePubkey.awaitReceipt();
}
mint する。エラーもなく成功した
async function mint() {
const { syncWallet } = await getProviderAndWallet();
const contentHash =
"0x571de4a8d1e739e2045f9543eebb535c9169dfdc56f00521bb8b9f0c93d44b49";
const nft = await syncWallet.mintNFT({
recipient: syncWallet.address(),
contentHash,
feeToken: "ETH",
});
console.log({ nft });
const receipt = await nft.awaitReceipt();
console.log({ receipt });
}
表示してみる
async function showState() {
const { syncWallet } = await getProviderAndWallet();
const state = await syncWallet.getAccountState();
console.log(state.committed.nfts);
console.log(state.verified.nfts);
}
出力
{
'66805': {
id: 66805,
contentHash: '0x571de4a8d1e739e2045f9543eebb535c9169dfdc56f00521bb8b9f0c93d44b49',
creatorId: 190274,
creatorAddress: '0x9f1f5d94324ba4f8ceb6fe3eb3215a536fcb6c9e',
serialId: 0,
address: '0x76cb15fa8c90d5a7a3d08cd447286e55691802a2',
symbol: 'NFT-66805'
}
}
トランザクション
L1 に withdraw する
async function withdrawNFT() {
const id = 66805;
const { syncWallet } = await getProviderAndWallet();
const withdraw = await syncWallet.withdrawNFT({
to: syncWallet.address(),
token: id,
feeToken: "ETH",
});
console.log({ withdraw });
const receipt = await withdraw.awaitReceipt();
console.log({ receipt });
}
出力
{
withdraw: Transaction {
txData: { tx: [Object], ethereumSignature: [Object] },
txHash: 'sync-tx:cca4462b00b778f7c4a003f007f814dedf67e7c5fd3258bc744eaace9e5681e2',
sidechainProvider: Provider {
transport: [HTTPTransport],
pollIntervalMilliSecs: 500,
contractAddress: [Object],
tokenSet: [TokenSet]
},
state: 'Sent'
}
}
トランザクション
トークンを調べる
withdraw した ethereum の Tx は https://rinkeby.etherscan.io/tx/0x7b2db2fc4f896497cd6243cbb1d4cdb247bb44cfd01f094aa69018423ae15d1d
ZkSync NFT Factory
というコントラクトのトークンが発行されていた
このコントラクト自由に変更可能なのかな...?
66805
はこのコントラクトでの token id だった
感想
雑に NFT を mint して withdraw できてすごい
コントラクトの自由度がどれぐらいか調べる必要がありそう