OpenSea免費創造的NFT都沒上鍊竟能出現在我的錢包裡?
內容概要
粉絲反饋,他在opensea無gas免費建立的NFT資產,竟能出現在小狐狸錢包裡,而opensea官方宣告的此NFT在正式交易前是未上鍊鑄造的,這就很奇怪,中心化應用的資產出現在為去中心化應用服務的錢包裡,到底是官方代付gas上鍊還是烏龍,隨我一文揭曉!
目錄大綱
1. 背景簡述
2. 破案歷程
2.1 小狐狸網路抓包
2.2 鏈上的交易統計
2.3 合約反編譯分析
3. 破案總結
面向物件
- Web3新手,有無技術背景均可理解此文解密過程
背景簡述
1.1 opensea 是什麼?
全球最大的公鏈NFT交易平臺,也是目前除以太坊鏈底層外營收最大的web3平臺,下文簡述為os

1.2 NFT是什麼? 可見前文: 【原始碼解讀】你買的NFT到底是什麼?
1.3 NFT鑄造是什麼?
可見前文: 當奈飛的NFT忘記了web2的業務安全
大意是,只有在鏈上 Mint 後的才能認為是資產,且一般使用者需要付gas
1.4 os的免費創造NFT服務是什麼?
NFT上鍊成本高,標準 ERC721 的 mint 需要8W的gas,約5刀
NFT定製合約難,雖有標準但頂級NFT專案會定製且部分強化功能,例如azuki(出品721A,降低批量 mint 成本)

因此,易用性一直就是市場的痛點,畢竟藝術家不是合約工程師,需更低成本的試錯來探索有價值的藝術品,官方也特別說明過(原文見附錄)
在 http:// opensea.io 上create的NFT,符合ERC1155標準,即使是它們存在於鏈上之前,這些 NFT 也可以在任何平臺上出售,在交易時才上鍊鑄造
破案歷程
2.1 案例來源
某粉絲很驚奇發現,自己確實可以在os上按流程進行 create ,但按官方說法此時是未上鍊的,但是他嘗試在小狐狸錢包裡匯入資產時發現, 竟然已經可見,甚至嘗試匯入一個自己未 create 的NFTID時也能匯入成功,因此反饋我尋找技術維度的全貌解讀
2.2 還原方式
1:os上 createNFT(附錄有官方教程)得到合約地址與ID
2:小狐狸上開啟NFT檢測後,再手動新增收藏品,即出現Shared Storefront

2.3 調查不易
其實查詢資產是否上鍊是個非常容易的過程,用區塊鏈瀏覽器即可
見前文: 當我們在看Etherscan的時候,到底在看什麼?
但是由於此os的NFT共享商店的合約並沒有做驗證。所以無法直接看原始碼查資料
但使用未經開源以及安全審計的合約,著實讓我這從事多年安全行業的職業強迫症有些難受
如果真存在風險,其危害是巨大的
- 如果真未上鍊,小狐狸錢包去讀取中心化平臺數據?放在我的資產裡?
- 如果真上了鏈,使用者無需gas,則可能官方付費上鍊,雷同羊毛有被攻擊風險
- 未上鍊的資產,如產生衝突風險,那此NFT屬於誰的?
2.4 小狐狸app抓包
首先咱們通過對照實驗做手機抓包,發現整體小狐狸會做的事情很多
拉取地址餘額,交易,最新塊內容,指定地址合約位元組碼等等

對數百個網路包逐個分析後,發現其小狐狸會使用infura(提供api介面同以太坊節點做互動的平臺)的 eth-call 方法,功能是查詢指定NFT合約中標準的 balanceof 方法
為何我如此肯定?此請求包裡沒有 balanceof 呀?
咱們用實驗說話雙向校驗,標準的1155協議的標準函式名及引數為:
function balanceOf(address,uint256)
由於data構建指定函式呼叫,其生成 Mothod-ID 的原理是名字+引數型別組合,因此他構建的 call 方法,data欄位的開頭必然為 00fdd58e
我輸 入的要新增資產是123號,其data引數末尾對應是7b=(7*16+11=123) 也對應上。
同時發現其缺乏防重放的措施,所以我可以直接編輯引數
重發請求查詢其他NFT合約所有權來對比:
- azuki:721標準,無得到0,有則非0
- 愛宕機:1155標準,無得到0,有則得1
- 查os共享商店,修改引數尾數(剛才的123)確實會得到值但意義不明
所以這裡我得出的一大驚奇猜想是(是錯誤的):
鏈上可查得NFT所有權的值,難道真的上鍊了嗎?
2.5 鏈上交易統計
如果真上鍊其實也可以不由使用者支付gas,有種“元交易”的技術手法,就是交易發起方和gas支付者不同的形式,並且 openzepplin 裡特地有個 content 合約就是用於額外支援元交易產生的 msg.sender 可能特殊化的問題
但是,我通過對此合約的鏈上交易資料統計(etherscan+dune),抽取23號一天出現的交易頻率可見下圖,都證明了好像並沒有固定由官方發起的元交易型別交易

2.6 破局得靠合約反編譯
由於官方沒有驗證合約,導致分析起來費勁多了,但可通過合約反編譯來大致摸清邏輯
如果只是 openzepplin 的標準1155庫進行反編譯的話,行數是170行
但是此1155則反編譯後是1000行,因此必然有較多自定義實現
反編譯後整體是吻合1155的資料標準
mapping (uint256 => [uint256]) _balanceOf; mapping (uint256 => [uint256]) _setApprovalForAll; uint256[] _name; uint256[] _symbol; mapping (uint256 => [uint256]) _totalSupply;
但是也顯著有不是標準資料部分
mapping (uint256 => [uint256]) owner_a; mapping (uint256 => [uint256]) _creator;
由於鏈上資料讀取返回了結果,所以重點分析balanceOf函式,他整體實現用了30多行,這是很明顯重寫了原先的標準函式
//此為標準1155協議的balanceOf 函式實現,只是讀取指定id和地址的數值而已 function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: balance query for the zero address"); return _balances[id][account];}
由於os他依舊是沿用標準,所以他的兩個引數是固定的可以理解為:
- Varg0 = 待查詢NFTid所有權的使用者地址
- varg1 = 待查詢的NFTID 數字
從反編譯程式裡看邏輯,他會讀取待查地址的 _balanceOf 總餘額數,以及此NFTID是否被 _creator 等等
//此為反編譯os合約的片段(太長不粘來,反編譯網址在附錄) function balanceOf(address varg0, uint256 varg1) public payable { require(msg.data.length - 4 >= 64); v0 = v1 = _balanceOf[varg0]; if (address(_creator[varg1]) == 0) { v2 = v3 = address(varg1 >> 96) == varg0; if (address(varg1 >> 96) != varg0) { if (!(0xff & owner_a[varg0])) { 。。。
最關鍵的一句 address(varg1 >> 96) != varg0
由於反編譯不會完全按照 solidity 的語法,所以原本不支援的位移運算子就出現了
不講複雜的,總之這裡將 varg1 (NFTID)的其中一部分,和 varg0 (使用者地址)做比較
這也意味著,原來此NFT的ID包含了使用者的地址
我頓然醒悟,寫個進位制轉換,將我在os上 create 得到的NFTid傳入,解密得出

這個數值也和我在小狐狸抓包看到的data後半段內容是一致
這裡還可以繼續研讀程式碼來挖掘細節
- 比如 balanceOf 返回結果為2個值,會審計編號是否會超出 _totalSupply 限定發行量
- 比如 safeTransferFrom 專門設定 _mint 防重放攻擊,在其中若未 mint 則進行首次鑄造
在解讀出 NFTID 的組成後,我也頓時明白此合約的核心邏輯了
此ID由3部分構成,使用者地址+系列編號+指定ID ,這也意味著無論我鑄造多少次,前xx位都是固定的,即我的錢包地址轉為10進位制而已,而他查詢的 balanceof 函式也因為我字首統一,從而判別我是未鑄造前的所有者,因此理論上我的鑄造空間極其大。
因此小狐狸確實能匯入,因為字首一致, balanceof 在沒有所有者的情況下,會預設依據此NFTID對應的空間的所有者返回結果,如果發生鑄造轉移,也有合約中配套的 owner_a 和 _creator 來證明這個創作者和當前所有者的關係。
至於為何小狐狸能出現NFT圖,這點是他官方宣告過的設定,出於讀取更多維度的描述說明、稀有度、原圖uri等資訊,且使用者可關閉這個錢包去查詢os中心化資料庫的功能。

破案總結
- 小狐狸是無辜的,他只是用標準方法走infura讀取鏈上資料而已,並沒有特別加工並修改返回資料
- os不去驗證合約,有一定自我市場競爭保護的目的,但是不能阻擋妙手玩家對合約分析,卻給不少使用者帶來無法證明資產所有的困境
- 最終,確實其NFT資產在 交易轉移前未被鑄造上鍊 ,但由NFTID定義的空間已經被特殊設計可查得餘額結果,所以理論上其他交易平臺也可買賣此NFT
附錄:
- gas價格圖: https:// etherscan.io/gastracker
- 反編譯平臺: https:// library.dedaub.com/deco mpile
- metamask的NFT檢測功能說明:
- https:// metamask.zendesk.com/hc /en-us/articles/360058238591-NFT-tokens-in-your-MetaMask-wallet
- os共享商店合約地址:
- 0x495f947276749ce646f68ac8c248420045cb7b5e
- OS官方宣告:
- 【ERC-1155 NFT 會出現在我的錢包中嗎?】
- https:// support.opensea.io/hc/e n-us/articles/1500003082561-Will-ERC-1155-NFTs-appear-in-my-wallet-
- 【在 OpenSea 上免費建立 NFT指南】
- https:// opensea.io/blog/announc ements/introducing-the-collection-manager/
前文回顧
- ECCV 2022 Oral | 自反饋學習的mixup訓練框架AutoMix
- 萬向區塊鏈成為中國電子工業標準化技術協會元宇宙工作委員會副會長單位
- 萬能的Hive Metastore能存哪些型別的表?
- Group DETR: 分組一對多匹配是加速 DETR 收斂的關鍵
- ttypescript plugin 入門指南
- React Fiber 架構 —— “更新”到底是個啥
- 紙上談兵之 Git 原理
- ECCV 2022 | SSP: 自支援匹配的小樣本任務新思想
- ECCV 2022 通往資料高效的Transformer目標檢測器
- ECCV 2022 | AirDet: 無需微調的小樣本目標檢測方法
- [ECCV 2022] CST: 首個嵌入光譜稀疏性的Transformer
- 二次疫情對遊戲行業流水的影響以及其它
- 【塔山之石】塔勒布比特幣黑皮書
- yolov7正負樣本分配詳解
- ECCV2022 Oral Unicorn: Towards Grand Unification of Object Tracking
- ECCV2022論文 | EAGAN:一種高效的用於搜尋GAN 的兩階段進化演算法
- RIFE 後記 - 光流插幀論文避坑指南
- 面向工業落地的新檢測框架【AIRDet】,超越YOLO系列
- ECCV2022 (Oral) | 無需前置條件的自動著色演算法 | CT2: Coloriztation Transformer via Color Tokens
- 漫談:從電影到漫畫,再到敘事視覺化(六)從漫畫到資料視覺化