hgame 易画行复现
此题是为了让⼤家稍微了解⼀下区块链。需要的知识是区块链的⼀些基本知识和ipfs的⼀些知识。
这道题确实不难,可惜我没有认真学Blockchain,做这个题也没有投入精力,只是看了看,赛后9C±Void师傅给我写了一份解析,在此致谢!
题目给了一个Typescript文件
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
| import { ethers } from 'ethers'; import config from './config.json';
const abi = [ 'function safeTransferFrom(address from, address to, uint256 tokenId) external', 'function approve(address to, uint256 tokenId) external', 'function getApproved(uint256 tokenId) external view returns (address)', 'function ownerOf(uint256 tokenId) external view returns (address)', ];
async function transferNFT(tokenId: number, toAddress: string) { const provider = new ethers.JsonRpcProvider('https://sepolia.drpc.org'); const wallet = new ethers.Wallet(config.privateKey, provider);
if (wallet.address.toLowerCase() !== config.fromAddress.toLowerCase()) { throw new Error('私钥与发送方地址不匹配'); }
const nftContract = new ethers.Contract(config.nftAddress, abi, wallet);
try { console.log('开始转移NFT...'); const tx = await nftContract.safeTransferFrom( config.fromAddress, toAddress, tokenId );
console.log('等待交易确认...'); const receipt = await tx.wait(); console.log(`NFT转移成功! 交易哈希: ${receipt.hash}`);
return receipt; } catch (error) { console.error('转移NFT时发生错误:', error); throw error; } }
const tokenId = 1; const toAddress = '0x74520Ad628600F7Cc9613345aee7afC0E06EFd84';
transferNFT(tokenId, toAddress) .then(() => console.log('转移完成')) .catch(console.error);
|
代码使用 ethers.js
进行智能合约交互,代码中使用了ethers.JsonRpcProvider('https://sepolia.drpc.org')
,意味着这个脚本是连接Sepolia 测试网,并有NFT转移的操作,最后告诉了我们转移的NFT的TokenID和NFT接收方的地址,因此我们肯定是要从接收方地址开始下手。
用Etherscan浏览器搜索,不过是测试网,所以用这个https://sepolia.etherscan.io/

看到那个Vidar的NFT,获取NFT的 tokenURI 有2种做法
两种解法
第一种:纯粹的溯源
点击右下那个 NFT: Vidar#1 我们能进入
下面一共就只有铸
造(Mint)和转移(Transfer)两个操作,而一般来说对于一个NFT而言,它的Metadata只会在铸造的
时候进行设定,之后它的Metadata将不再发生改变,因此我们需要查看它的铸造操作

我们点击最下面那个




用ipfs desktop打开ipfs地址

不下载这个也可,访问这个https://ipfs.io/ipfs/(Link Hash)
第二种:合约调用
这个是9C±Void师傅写的脚本,本人太菜,入门程度都未到
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
| from web3 import Web3
RPC_URL = "https://sepolia.drpc.org" NFT_ADDRESS = "0x0c5ABBB0743a3Ac77C2c301eD63810F3353c59F8"
w3 = Web3(Web3.HTTPProvider(RPC_URL))
if not w3.is_connected(): raise ConnectionError("无法连接到以太坊节点,请检查 RPC URL")
ABI = [ { "inputs": [ {"internalType": "uint256", "name": "tokenId", "type": "uint256"}, ], "name": "tokenURI", "outputs": [{"internalType": "string", "name": "", "type": "string"}], "stateMutability": "view", "type": "function", }, ]
nft = w3.eth.contract(address=NFT_ADDRESS, abi=ABI)
token_id = 1 try: uri = nft.functions.tokenURI(token_id).call() print(f"Token {token_id} URI: {uri}") except Exception as e: print(f"调用 tokenURI 失败: {e}")
|

接下来就和上面一样了
有关上面的MetadataUpdate事件,这个事件来自EIP5008: ERC-721 Nonce and Metadata
Update Extension - EIPs - Fellowship of Ethereum Magicians,直接去官网上看EIP-5008的话只
会看到它对Nonce拓展的定义,但是官网给出了通往上面这个链接的跳转
参考:ERC-721:非同质化代币标准