📜 [專欄新文章] Optimistic Rollup 就這樣用(2)
✍️ Juin Chiu
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
ERC721 的儲值、轉移與提領
TL;DR
本文會跳過 Optimistic Rollup 的介紹而直接實際演示,關於 Optimistic Rollup 的概念與設計原理筆者將在日後另撰文說明,有興趣的讀者可以先參考下列三篇文章(由淺入深):1. OVM Deep Dive 2. (Almost) Everything you need to know about Optimistic Rollup 3. How does Optimism’s Rollup really work?
本文將演示一個 Optimism Rollup 的 ERC721 範例,程式碼在這裡。
本演示大量參考了以下範例:Optimistic Rollup Example: ERC20。
本演示所使用的 ERC721 Gateway 合約來自這個提案,目前尚未成為官方標準。
環境設置
Git
Node.js
Yarn
Docker
Docker-compose
筆者沒有碰到環境相容問題,但是建議都升到最新版本, Node.js 使用 v16.1.0 或以上版本
Optimism 服務啟動
有關 Optimisim 的所有服務,都包裝在 Optimism 這個超大專案當中了,直接使用原始碼進行組建:
$ git clone git@github.com:ethereum-optimism/optimism.git$ cd optimism$ yarn$ yarn build
組建完成後,就可以在本機啟動服務了:
$ cd ops$ docker-compose build$ docker-compose up
這個指令會啟動數個服務,包括:
L1 Ethereum Node (EVM)
L2 Ethereum Node (OVM)
Batch Submitter
Data Transport Layer
Deployer
Relayer
Verifier
Deployer 服務中的一個參數要特別注意: FRAUD_PROOF_WINDOW_SECONDS,這個就是 OPtimistic Rollup 的挑戰期,代表使用者出金(Withdraw)需等候的時長。在本篇演示中預設為 0 秒。
如果有需要重啟,記得把整個 Docker Volume 也清乾淨,例如: docker-compose down -v
Optimism 整合測試
在繼續接下來的演示之前,我們需要先確認 Optimism 是否有順利啟動,特別是 Relayer 是否運作正常,因此我們需要先進行整合測試:
$ cd optimism/integration-tests$ yarn build:integration$ yarn test:integration
確保 L1 <--> L2 Communication 相關測試通過後再繼續執行接下來的演示內容。
啟動服務及部署合約需要花費一些時間,運行一段時間(約 120 秒)之後再執行測試,如果測試結果全部皆為 Fail,可能是 Optimism 尚未啟動完成,再等待一段時間即可。
ERC721 合約部署
Optimism 啟動成功並且完成整合測試後,接下來進行 ERC721 合約的部署。筆者已將合約及部署腳本放在 optimistic-rollup-example-erc721 這個專案中:
$ git clone git@github.com:ethereum-optimism/optimistic-rollup-example-erc721.git$ cd optimistic-rollup-example-erc721$ yarn install$ yarn compile
接下來我們需要部署以下合約:
ERC721,部署於 L1
L2DepositedEERC721,部署於 L2
OVM_L1ERC721Gateway,部署於 L1
OVM_L1ERC721Gateway 只部署在 L1 上,顧名思義它就是 L1 <=> L2 的「門戶」,提供 Deposit / Withdraw 兩個基本功能,使用者必須透過這個合約來進出 L2。
雖然 OVM_L1ERC20Gateway 是 Optimistic Rollup 官方提供的合約。但是開發者也可以依需求自行設計自己的「門戶」。
OVM_L1ERC20Gateway 目前沒有 Optimism 的官方實作,本演示所使用的 ERC721 Gateway 合約來自這個提案,目前尚未成為官方標準。
接下來,我們直接用腳本進行部署:
$ node ./deploy.jsDeploying L1 ERC721...L1 ERC2721 Contract Address: 0xFD471836031dc5108809D173A067e8486B9047A3Deploying L2 ERC721...L2 ERC721 Contract Address: 0x09635F643e140090A9A8Dcd712eD6285858ceBefDeploying L1 ERC721 Gateway...L1 ERC721 Gateway Contract Address: 0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547ccInitializing L2 ERC721...
ERC721 鑄造、儲值、轉移與提領
鑄造(L1)
初始狀態如下,所有帳戶皆尚未持有任何代幣:
接下來,我們將鑄造 2 個代幣以進行接下來的演示。首先,進入 ETH(L1) 的 Console:
$ npx hardhat console --network ethWelcome to Node.js v16.1.0.Type ".help" for more information.>
取得 Deployer / User 帳戶:
// In Hardhat ETH Console
> let accounts = await ethers.getSigners()
> let deployer = accounts[0]
> let user = accounts[1]
取得 ERC721 及 OVM_L1ERC721Gateway 合約物件,合約地址可以從部署訊息中取得:
// In Hardhat ETH Console
> let ERC721_abi = await artifacts.readArtifact("ExampleToken").then(c => c.abi)
> let ERC721 = new ethers.Contract("0xFD471836031dc5108809D173A067e8486B9047A3", ERC721_abi)
> let Gateway_abi = await artifacts.readArtifact("OVM_L1ERC721Gateway").then(c => c.abi)
> let Gateway = new ethers.Contract("0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc", Gateway_abi)
鑄造兩個 ERC721 代幣:
// In Hardhat ETH Console
> await ERC721.connect(deployer).mintToken(deployer.address, "foo")
{ hash: "...", ...}
> await ERC721.connect(deployer).mintToken(deployer.address, "bar")
{ hash: "...", ...}
只有合約的 Owner(deployer) 可以進行鑄造的操作。
確認 Deployer 餘額:
> await ERC721.connect(deployer).balanceOf(deployer.address)
BigNumber { _hex: '0x02', _isBigNumber: true } // 2
確認代幣的 TokenID 與 Owner:
> await ERC721.connect(deployer).ownerOf(1)
'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' // deployer
> await ERC721.connect(deployer).ownerOf(2)
'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' // deployer
儲值(L1 => L2)
完成以上步驟後,目前的狀態如下:
接下來,授權 OVM_L1ERC721Gateway使用 TokenID 為 2 的代幣:
// In Hardhat ETH Console
> await ERC721.connect(deployer).approve("0xcbEAF3BDe82155F56486Fb5a1072cb8baAf547cc", 2)
{ hash: "...", ...}
在 OVM_L1ERC721Gateway 合約呼叫 Deposit,儲值 TokenID 為 2 的代幣:
// In Hardhat ETH Console
> await Gateway.connect(deployer).deposit(2)
{ hash: "...", ...}
我們可以到 Optimism (L2) 的 Console 確認入金是否成功:
$ npx hardhat console --network optimismWelcome to Node.js v16.1.0.Type ".help" for more information.>
取得 Deployer / User 帳戶:
// In Hardhat Optimism Console
> let accounts = await ethers.getSigners()
> let deployer = accounts[0]
> let user = accounts[1]
取得 L2DepositedERC721 合約物件,合約地址可以從部署訊息中取得:
// In Hardhat Optimism Console
> let L2ERC721_abi = await artifacts.readArtifact("OVM_L2DepositedERC721").then(c => c.abi)
> let L2DepositedERC721 = new ethers.Contract("0x09635F643e140090A9A8Dcd712eD6285858ceBef", L2ERC721_abi)
確認入金是否成功:
// In Hardhat Optimism Console
> await L2DepositedERC721.connect(deployer).balanceOf(deployer.address)
BigNumber { _hex: '0x01', _isBigNumber: true } // 1
> await L2DepositedERC721.connect(deployer).ownerOf(2)
'0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' // deployer
ERC721 轉移(L2 <=> L2)
完成以上步驟後,目前的狀態如下:
接下來,我們在 L2 從 Deployer 轉移代幣給 User:
// In Hardhat Optimism Console
> await L2DepositedERC721.connect(user).balanceOf(user.address)
BigNumber { _hex: '0x00', _isBigNumber: true } // 0
> await L2DepositedERC721.connect(deployer).transferFrom(depoyer.address, user.address, 2)
{ hash: "..." ...}
> await L2DepositedERC721.connect(user).balanceOf(user.address)
BigNumber { _hex: '0x01', _isBigNumber: true } // 1
> await L2DepositedERC721.connect(user).ownerOf(2)
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8' // user
ERC721 提領(L2 => L1)
完成以上步驟後,目前的狀態如下:
接下來,我們用 User 帳戶提領資金,在 L2DepositedERC721 合約呼叫 Withdraw:
// In Hardhat Optimism Console
> await L2DepositedERC721.connect(user).withdraw(2)
{ hash: "..." ...}
> await L2DepositedERC721.connect(user).balanceOf(user.address)
BigNumber { _hex: '0x00', _isBigNumber: true }
最後,檢查在 L1 是否提領成功:
// In Hardhat ETH Console
> await ERC721.connect(user).balanceOf(user.address)
BigNumber { _hex: '0x01', _isBigNumber: true } // 1
> await ERC721.connect(deployer).balanceOf(deployer.address)
BigNumber { _hex: '0x01', _isBigNumber: true } // 1
> await ERC721.connect(user).ownerOf(2)
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8' // user
由於挑戰期為 0 秒,因此提領幾乎無需等待時間,頂多只需數秒鐘
做完上述所有操作,最終狀態應該如下:
總結
本文演示了:
Optimistic Rollup 相關服務的本機部署
ERC721 L1 => L2 的儲值(Deposit)
ERC721 L2 帳戶之間轉移(Transfer)
ERC721 L2 => L1 的提領(Withdraw)
筆者未來將繼續擴充此系列的教學內容,例如支援其他標準的合約如 ERC1155,以及如何運行 Optimistic Rollup 生態系中最重要的驗證者(Verifier),敬請期待。
參考資料
OVM Deep Dive
(Almost) Everything you need to know about Optimistic Rollup
How does Optimism’s Rollup really work?
Optimistic Rollup Official Documentation
Ethers Documentation (v5)
Optimistic Rollup Example: ERC20(Github)
Optimism (Github)
optimism-tutorial (Github)
l1-l2-deposit-withdrawal (Github)
Proof-of-concept ERC721 Bridge Implementation (Github)
Optimistic Rollup 就這樣用(2) was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
「withdraw三態」的推薦目錄:
- 關於withdraw三態 在 Taipei Ethereum Meetup Facebook 的最佳解答
- 關於withdraw三態 在 辣媽英文天后 林俐 Carol Facebook 的精選貼文
- 關於withdraw三態 在 Taipei Ethereum Meetup Facebook 的精選貼文
- 關於withdraw三態 在 withdraw三態在PTT/Dcard完整相關資訊 - 動漫二維世界 的評價
- 關於withdraw三態 在 withdraw三態在PTT/Dcard完整相關資訊 - 動漫二維世界 的評價
- 關於withdraw三態 在 withdraw三態在PTT/Dcard完整相關資訊| 數位感-2021年11月 的評價
- 關於withdraw三態 在 withdraw三態在PTT/Dcard完整相關資訊| 數位感-2021年11月 的評價
- 關於withdraw三態 在 know三態的推薦與評價,PTT、DCARD - 連鎖量販網紅推薦指南 的評價
- 關於withdraw三態 在 know三態的推薦與評價,PTT、DCARD - 連鎖量販網紅推薦指南 的評價
- 關於withdraw三態 在 多益英文 新多益13大情境必學單字片語系列 叮叮噹 的評價
withdraw三態 在 辣媽英文天后 林俐 Carol Facebook 的精選貼文
杜學長和俐媽都是Roger Federer的粉絲,
除了學習英文,
我們也會談談四大網球公開賽的消息,
這次Federer宣佈退出法網,
我們遺憾🥺但是尊重。
「退出」賽事的英文該怎麼說?
以下感謝杜學長的整理提供👍🏼👍🏼
——————————————————————-
🎾 俐媽新聞英文—網球篇:
*withdraw (v.) 撤退;退出
→ withdrawal (n.)
*seek to (ph.) 追求;力圖爭取
*operation (n.) 手術
*pull out of N. (ph.) 退出 (比賽/競選等)
*statement (n.) 聲明;敘述
*rehabilitation (n.) 復原;康復
*grand slam (n.) 大滿貫賽事 (網球)
*undergo (v.) 經歷;忍受(考驗/變化/檢修等)
*target (v.) 把…作為目標(at N)
*be thrilled to V. (ph.) 很激動/興奮去做某事
*tournament (n.) 錦標賽 (常簡寫tour)
*put up (ph.) 提供;建造
*quarterfinal (n.) 八強 (或稱半準決賽/四分之一決賽)
*reassess (v.) 再三考慮;再三評估
*curfew (n.) 宵禁
*stadium (n.) 體育場 (館)
*make N. debut (ph.) 首次亮相
*dominate (v.) 主宰;支配
*testament (n.) 確實的證明
*grueling (a.) 使人筋疲力盡的;艱辛的
*rule out (ph.) 排除;取消
*priority (n.) 優先
*singles title (n.) 單打冠軍
*Open era (n.) 公開化年代 (大寫為網壇專有名詞)
*serve (n.) 發球
*manage to V (ph.) 設法成功達成⋯
*unseeded (a.) 非種子(球員)的
*spectator (n.) 觀眾
cf. audience (n.) 聽眾(⚠️ 俐媽上課常提醒的不同「觀眾」,別搞混囉)
*session (n.) 場次
*revenue (n.) 利潤
*infrastructure (n.) 基礎設施
*turn out to be N. (ph.) 結果是…
*poignant (a.) 淒美的
*criticism (n.) 批評
*have an impact on N. (ph.) 對…造成影響/衝擊
*interest (n.) 利益;利潤
*involvement (n.) 涉及;介入;參與
*career (n.) 職業生涯
*devalue (v.) 貶低;降低…的價值
*walkover (n.) 輕易得勝
*sprain (v.) 扭傷
*adrenaline (n.) 腎上腺素
*demanding (a.) 要求高的;費力的
*inevitable (a.) 無可避免的
*exceptionally (adv.) 異常地;特殊地
*durable (a.) 持久的
*astonishingly (adv.) 令人驚訝地
*retire (v.) 退賽
*straight-sets (n.) 直落盤數
*sympathy (n.) 同情
*opponent (n.) 對手
*conserve (v.) 保存
*reassured (a.) 使放心的
*news conference (n.) 記者會
*fitness trainer (n.) 體能訓練師
*encounter (n.)(v.) 遭遇
*occasionally (adv.) 偶然地
*suggest (v.) 暗示
*on the cards (adv.) 可能
*sensible (a.) 明智的;合乎情理的
*make sense to V. (ph.) 對做某事是有道理的
*condition (n.) 條件;情況
*harbour (v.) 懷有 (心情/感覺)
🆙 harbour (v.) 為英式用法,harbor (v.) 則為美式
*agonizingly (adv.) 痛苦的;苦悶的
🆙 文中 agonisingly (adv.) 為英式用法
*convert (v.) 轉變;轉換
→ convert into N. (ph.) 轉變成…
🆙 常用於重大轉變,如信仰、意識形態、關鍵點 (俐媽上課常提點)
*sit out (ph.) 袖手旁觀 (文中衍伸為缺席的意思)
*successive (a.) 連續的;接連的
*edition (n.) 版次;集 (文中衍伸為屆次)
*semi-final (n.) 四強 (或稱準決賽/半決賽)
*appearance (n.) 出現;露面 (文中衍伸為出賽)
*stand (n.) 看臺
*eerily (adv.) 奇怪地;異常地
*restriction (n.) 限制
*farewell (n.) 告別;辭別
最後附上一篇由法網官方貼出關於Federer退賽的聲明!
—————————————————————————-
#你也是網球迷嗎
#俐媽新聞英文 #俐媽新聞英文網球篇
#台大明明助你銜接新聞英文
withdraw三態 在 Taipei Ethereum Meetup Facebook 的精選貼文
📜 [專欄新文章] [ZKP 讀書會] Zkopru
✍️ NIC Lin
📥 歡迎投稿: https://medium.com/taipei-ethereum-meetup #徵技術分享文 #使用心得 #教學文 #medium
Photo by Barth Bailey on Unsplash
Zkopru
Zkopru 這個名稱是由 zk-transaction + Optimistic Roll-Up 的字首組成,這個layer 2 的協議包含了使用零知識證明來保護交易的隱私( zk-transaction)、再搭配 Optimistic Rollup 來管理 layer 2 。
接下來會講到 Zk Rollup 和 Optimistic Rollup,如果讀者還不熟悉,可以先閱讀這篇ˊ指介紹。
它和 Zk Rollup 有什麼不同?
Zk Rollup 連同 layer 2 的鏈的 state transition 都是由零知識證明來處理,但缺點是目前零知識證明技術的成本較高,包含在鏈下產生證明和在鏈上驗證證明(鏈下產生證明耗費時間,鏈上驗證證明則耗費 gas)。
註:接下來提到的(零知識證明、circuit)的鏈下成本都是指時間多寡,而鏈上成本則都是指 gas 多寡)
另外目前的 Rollup 協議都是使用 merkle tree 來儲存當前的鏈的狀態(例如使用者的餘額、nonce 或是 UTXO) — 如果使用者要證明他有 $20,則他必須要提供 merkle proof ,而這個 merkle proof 的大小及 hash 次數也會因為選擇的 merkle tree 的高度而有不同。
而這個因素再搭配上 hash 的成本在 EVM 和 circuit 會有不同,導致協議如果使用在 EVM 成本較便宜的 hash function,則 circuit 的 hash 成本會較高;反之亦然。
目前還沒有安全的 hash function 是在 EVM 或 circuit 裡都是便宜的,所以協議設計者必須做出妥協。可想而知,Zk Rollup 便是使用在 circuit 便宜但是在 EVM 貴的 hash function,這導致當使用者要離開 layer 2 回到 layer 1 時(這個步驟在這裡稱作 withdraw),他成本會很高(因為要在 EVM 裡驗證他持有資產的擁有權,這可以是一個 merkle proof 或 zk proof)。
和 Optimistic Rollup 有什麼不同?
而這個成本相對的也反映了採用 Optimistic Rollup 的好處 — 只有在特殊情況下(例如協議裡的 Operator 作惡)才需要付出較高的成本,其他時間大家則享受極低成本的使用費。
但使用 Optimistic 的方式也有附帶的缺點: challenge period 。輕節點使用者需要等待 challenge period 來確保交易不會被推翻、withdraw 過程需要等待 challenge period(以下稱 withdraw period) 過了才能將錢提回到 layer 1。
所以使用哪種 Rollup 就要看協議設計者如何依照他們的使用需求去權衡。
那為什麼不使用 Optimistic Rollup 就好?
因為需要零知識證明來保護交易隱私!
前提
zkopru 使用和 Bitcoin 相同的 UTXO model
transfer 的付款方、收款方和金額都是被保護住、看不到的,但 zkopru 和其他隱私幣一樣,不需要付款方和收款方合作即可由付款方單獨完成 transfer。
但也和隱私幣一樣,收款方必須去監看鏈上每一筆交易並嘗試解密來得知是否有人 transfer 給自己
基本使用流程
Deposit
使用者將 ether 、ERC20 或 ERC721 代幣轉入 zkopru 位於 layer 1 的合約,觸發 event。協議的 Operator 會監看合約並搜集 deposit event,然後將這些 deposit 一起放入下一個(zkopru 的)區塊裡。
Transfer
如同 Bitcoin 的 UTXO,zkopru 裡使用者必須要證明其對某 UTXO 有擁有權才能花費該 UTXO。要被花費的 UTXO 會被放到 transaction 格式裡的 inputs 欄位, outputs 欄位的 UTXO 則是填入收款方的公鑰和收款金額(outputs 的 UTXO 就會是新產生的 UTXO)。
因為要保護交易的隱私,新的 UTXO 的資訊是不會洩露出去的,第三方只會看到該 UTXO 的 hash 值。那收款方要怎麼知道一個 UTXO 是不是他的呢?
sender 會利用自己的私鑰、收款方的公鑰及一個隨機值,透過密鑰交換協議來產生一個臨時的共享密鑰。 付款方用此共享密鑰加密收款方所需的資訊(包含 transfer 的代幣種類和金額),而收款方會監看每一筆交易並試著用自己的私鑰組出一個共享密鑰然後去解密,如果解密完的資料不是亂碼而是合理的,則可確認收到錢。
Withdraw使用者產生 withdraw 類別的交易,等待協議 Operator 收進區塊裡,然後再等待 withdraw period 過去,即可送出 merkle proof 來將錢提領回 layer 1。
註:提領回 layer 1 之後的收款方和金額都是公開透明的,隱私不再受保護。
零知識證明
zkopru 裡一共有三種類型的 merkle tree 來儲存所需的狀態,分別是 UTXO tree、Nullifier tree 以及 Withdrawal tree。
UTXO tree 紀錄所有產生過的 UTXO,包含新的和已經花掉的。
Nullifier tree 紀錄被花掉的 UTXO 的 nullifier 值。一個 UTXO 的 nullifer 由該 UTXO 的相關資訊算出,而且只能得出唯一一個 nullifier。這個 nullifier 能夠證明該 UTXO 已被花掉,但同時又不會洩露是哪個 UTXO 被花掉。聽起來很饒口,但這就是零知識證明的能力。
Withdrawal tree 紀錄 withdraw 類別的交易的資訊,使用者要提領回 layer 1 就需要這棵 merkle tree 的 merkle proof。也是就說,前面說的 Operator 會把 withdraw 交易放到這棵 merkle tree 裡,然後等待 withdrawal period 過後,再由使用者提供 merkle proof 來領走。
這裏以 transfer 為例來說明其中一部分的 circuit 在做什麼事
當使用者要產生一筆 transfer,他首先要證明 inputs 裡的 UTXO 都是合法的,這包含了證明:
他擁有這個 UTXO — 藉由提供簽章來證明
這個 UTXO 是真的存在的 — 藉由證明該 UTXO 的 hash 值存在 UTXO tree 裡
這個 UTXO 沒有被花過 — 藉由證明該 UTXO 的 nullifier 值不存在 Nullifier tree 裡
接者是 outputs,新產生的 UTXO 的 hash 值會被放進 UTXO tree 裡。
最後是比對 inputs 金額加總等於 outputs 金額加總再加上交易手續費。
而這些都在 circuit 裡完成,第三方沒辦法得知實際的 inputs、outputs 或 nullifiers 等等,第三方只能知道新的 UTXO 的 hash 值以及運算過程是正確的 — 也就是這些 tree 都被正確的更新了。
其他特色
Mass migration
原本每個使用者要把資產換到另外一個 layer 2 協議,他必須申請 withdraw 、等待 withdraw period ,然後把資產 deposit 到另外一個 layer 2 協議。
zkopru 支援使用者成批的搬移資產到另外一個 layer 2 協議 — 共享經濟。
Instant withdrawal
如果其他需要等待 withdraw period 的應用來說,withdraw period 是一個 UX 痛點。zkopru 的 instant withdrawal 提供急著 withdraw 的一方和不急著 withdraw 的一方一個管道能互惠。
急的一方提供一點手續費,對自己的 withdraw 交易做簽名並廣播出去。不急的一方在聽到這個簽名後,可以將這個簽名送到 zkopru 合約並附上 withdraw 金額(扣掉自己該收的手續費)。
這筆錢會直接轉給急的一方,然後急的一方的 withdraw 擁有權便會轉移到不急的一方手上,不急的一方再慢慢等到 withdraw period 過了再提領。
估計效能
目前在初版的效能估計中,一筆 transfer 平均耗費 8800 gas;而 TPS 則是 105。zkopru 還在積極更新迭代中,所以這個效能會在提升。
Reference:
https://ethresear.ch/t/zkopru-zk-optimistic-rollup-for-private-transactions/7717
https://docs.zkopru.network
https://www.chainnews.com/zh-hant/articles/443085023250.htm
[ZKP 讀書會] Zkopru was originally published in Taipei Ethereum Meetup on Medium, where people are continuing the conversation by highlighting and responding to this story.
👏 歡迎轉載分享鼓掌
withdraw三態 在 withdraw三態在PTT/Dcard完整相關資訊 - 動漫二維世界 的推薦與評價
字典- withdraw - 香港新浪網withdraw, 動詞三態. 現在式(Present Tense):withdraw 過去式(Past Tense): withdrew 過去分詞(Past Participle):withdrawn ...香港新浪網 ... ... <看更多>
withdraw三態 在 withdraw三態在PTT/Dcard完整相關資訊| 數位感-2021年11月 的推薦與評價
tw香港新浪網- 字典- withdrew - 漢英字典withdraw的過去式和過去分詞. 回頁首. withdraw, 動詞三態. 現在式(Present Tense) :withdraw 過去式(Past Tense):withdrew ... ... <看更多>
withdraw三態 在 withdraw三態在PTT/Dcard完整相關資訊 - 動漫二維世界 的推薦與評價
字典- withdraw - 香港新浪網withdraw, 動詞三態. 現在式(Present Tense):withdraw 過去式(Past Tense): withdrew 過去分詞(Past Participle):withdrawn ...香港新浪網 ... ... <看更多>