深入了解區塊鏈(三) - 用Ganache來模擬任意地址的身分

2023/05/16閱讀時間約 8 分鐘

前言

很高興能再次與您見面,感謝您支持這系列的文章。在前幾篇的文章中。有和各位分享了使用Ganache來模擬一個以太坊主網進行交易,也嘗試使用了web3.py來開發區塊鏈互動程式。相信對您而言,一定有更深入探索區塊鏈交易的需求。本篇想和各位介紹一個Ganache的神奇功能:解鎖任意帳號

解鎖任意帳號?

不知各位是否記得在上一篇文章,我們在寫交易程式過程中,有對交易的內容以私鑰進行簽名。這步驟對於區塊鏈的安全性而言非常重要,這步驟可以讓礦工們驗證這則交易是否由本人所發出,他人是沒有辦法偽造這筆交易的。
但是在模擬的環境中,若我們想要模擬某個帳號的行為,或是以特定身分來取得特定智能合約的權限,這是否能夠做到的呢?Ganache能為我們達成這項需求。
接下來我們會設定一個情境來說明這項功能

跟幣安借點錢花花

在區塊鏈世界裡,相信各位對幣安(Binance)都不陌生。我們是否有辦法在我們的模擬網路中,透過幣安的帳號從它的池子裡分一些Token給我們使用?
PS. 此模擬情境不會真正的讓幣安轉錢給你,僅會在你的模擬網路中曇花一現
這樣的實驗主要是為了探討合約的安全性,若在您的實驗中有發現任何的合約漏洞,不妨將這個漏洞資訊提供給合約擁有者,為區塊鏈安全盡一份心力!
首先我們先找到其中一個幣安所使用的帳號,我們將使用它進行範例
合約地址:0x28C6c06298d514Db089934071355E5743bf21d60
  • 為了解鎖特定帳號,需要在Ganache啟動時加入以下參數(wallet.unlockedAccounts)
ganache --fork.network mainnet \
--chain.networkId 1 \
--accounts 10 \
--wallet.seed 1337 \
--port 8545 \
--wallet.unlockedAccounts 0x28C6c06298d514Db089934071355E5743bf21d60
Ganache僅能在啟動時解鎖特定帳號,現沒法在執行過程中動態解鎖帳號,有些可惜。
  • 首先做一些初始化
from web3 import HTTPProvider, Web3
import json
import time

#連線到剛啟動的Ganache RPC Server
web3 = Web3(HTTPProvider('http://127.0.0.1:8545'))
  • 假如我們想要從幣安的這個帳號轉1,000USDT到我們的測試帳號,我們需要先拿到USDT合約的ABI (方式同上一篇文章所述),您一樣可以從etherscan.io得知
#設定相關地址,userAcc和userKey為您Ganache生成的測試地址
userAcc = web3.toChecksumAddress('0xC459cc3AC9f8462Be2EF00aAD02fAc7af2e97b14')
userKey = '0xda09f8cdec20b7c8334ce05b27e6797bef01c1ad79c59381666467552c5012e3'

#USDT合約地址
USDT_ADDR = web3.toChecksumAddress('0xdac17f958d2ee523a2206206994597c13d831ec7')
#幣安錢包地址
BINANCE_ADDR = Web3.toChecksumAddress('0x28C6c06298d514Db089934071355E5743bf21d60')
  • 我們可以來開始建立交易了。在ERC20的規範中,若要進行Token的轉移,您需要先approve(允許)特定金額的轉移後,才能進行transfer(轉移)。
  • 首先先來導入ABI與實例化合約
#USDT合約的ABI內容請自行複製並貼到usdt.json檔案中,透過檔案內容來讀取JSON
abi = json.load(open('usdt.json'))
usdt_contract = web3.eth.contract(address=USDT_ADDR, abi=abi)
  • 進行approve動作
approve = usdt_contract.functions.approve(
    BINANCE_ADDR, #允許哪個帳號可以進行轉移
    1000 * 1000000 #允許多少
)
#我們使用幣安身分來做為FROM
txn = approve.buildTransaction({
    'from': web3.toChecksumAddress(BINANCE_ADDR),
    'value': web3.toWei(0,'ether'),
    'gasPrice': web3.toWei('30','gwei'),
    "gas": 3000000,
    'nonce': web3.eth.get_transaction_count(BINANCE_ADDR)
})
#因為幣安的帳號已經被解鎖,所以可以不用對交易進行簽名,直接發送交易即可
web3.eth.send_transaction(txn)
  • 進行transfer動作
transfer = usdt_contract.functions.transfer(
    userAcc, #轉給誰
    1000 * 1000000 #轉多少
)
#一樣使用幣安身分來做為FROM
txn = transfer.buildTransaction({
    'from': web3.toChecksumAddress(BINANCE_ADDR),
    'value': web3.toWei(0,'ether'),
    'gasPrice': web3.toWei('30','gwei'),
    "gas": 3000000,
    'nonce': web3.eth.get_transaction_count(BINANCE_ADDR)
})
#因為幣安的帳號已經被解鎖,所以可以不用對交易進行簽名,直接發送交易即可
web3.eth.send_transaction(txn)
  • 交易成功,我們可以回到Metamask中察看交易結果是不是符合預期呢?
成功從幣安帳號轉來的USDT

後記

從上面的例子可以看到,經解鎖後的帳號,Ganache都不會要求交易的FROM地址進行簽名驗證了。代表我們可以對任意的地址取得任意的權限,例如:
  • 某個NFT只有Owner可以進行mint,我們可以解鎖該Owner的帳號來發起mint
  • 執行任意合約使用msg.sender進行權限控管的功能
  • 對任意地址進行Peer to peer的ETH交易
  • ...
充滿無限想像的可玩性,就待您慢慢發掘與研究。這功能對於研究某些鏈上合約的弱點非常有幫助,尤其在您沒有該合約的擁有權時。
感謝您閱讀到本系列的第三篇文章,希望這期帶來的內容對您而言也是有趣的。預計下一篇內容會針對交易於EVM中的行為做更進一步的了解,期待與您再一次的相見。

作者Steve目前任職於趨勢科技區塊鏈安全研究小組,專注於區塊鏈合約安全與與相關技術,如果喜歡我的文章,或是想獲得更多區塊鏈詐騙事件懶人包,歡迎關注我的帳號
另外,我已經加入由趨勢科技防詐達人所成立的方格子專題-《區塊鏈生存守則》,在那裡我會跟其他優質的創作者一起帶大家深入瞭解區塊鏈,並隨時向大家更新區塊鏈資安事件
> 追蹤《區塊鏈生存守則》學習如何在區塊鏈的世界保護自己
> 關注防詐達人獲得其他最新詐騙情報
27會員
176內容數
我們整理了web3相關的熱門資安問題,包含加密貨幣投資詐騙、盜版NFT、空投釣魚和區塊鏈重大資安事件懶人包等等,並提供最完整的辨識方法教學,讓大家從0到1學習如何保護自己
留言0
查看全部
發表第一個留言支持創作者!