使用 ethers js 估算 ERC20 代幣的傳輸氣體,無需代幣
我試圖能夠準確估計使用 Ethers js 發送 ERC20 令牌所需的氣體,而無需首先需要該令牌。目前,我能夠得到一個估計,儘管它似乎不是非常準確。我的程式碼是:
const {ethers} = require("ethers"); const provider = new ethers.providers.EtherscanProvider('homestead', 'API_KEY'); const sendGas = async (to, tokenAddress, amount) => { const abi = [ // Some details about the token "function name() view returns (string)", "function symbol() view returns (string)", // Get the account balance "function balanceOf(address) view returns (uint)", // Send some of your tokens to someone else "function transfer(address to, uint amount)", // An event triggered whenever anyone transfers to someone else "event Transfer(address indexed from, address indexed to, uint amount)" ]; const signer = new ethers.Wallet('PRIVATE_KEY'); const account = signer.connect(provider); const contract = new ethers.Contract( tokenAddress, abi, account ); const gasCost = await contract.estimateGas.transfer(to, amount) console.log(parseInt(gasCost, 10)); return gasCost; } sendGas('PUBLIC_KEY', '0xa36085F69e2889c224210F603D836748e7dC0088', '0');
當我在給定正確輸入的情況下執行程式碼時,它似乎按預期工作。除了實際使用的氣體和估計的數量可能會有很大差異。首先,為了讓函式正確執行,我需要將金額作為 0 傳遞,因為我希望能夠估計我還沒有的代幣的氣體。如果我嘗試使用非零餘額獲取我沒有的代幣,我會收到餘額不足的錯誤。我的問題是我需要氣體精確到幾千氣體,但它目前到處都是。例如,我嘗試在 kovan 上轉移一枚硬幣,估計需要 21560 個 gas,然而,它最終使用 35322 個 gas 進行實際交易(我發現甚至有很大的差異)。這是由於發送金額為0造成的嗎?如果是這樣的話,
不太重要,但如果有人有見識,我將不勝感激,我如何確定令牌的轉移 abi?我目前使用的只是 ethers js 文件中提供的標準。這適用於所有代幣嗎?如果沒有,有沒有辦法讓 abi 轉移任何代幣?
TLDR;並非所有 ERC20 轉賬的成本都相同。影響 gas 成本的 ERC20 轉賬主要有四種情況。大多數情況下,您最好為
gasLimit
. 但是,如果您真的想將其最小化,則可以盡力弄清楚情況。首先,為了讓函式正確執行,我需要將金額作為 0 傳遞,因為我希望能夠估計我還沒有的代幣的氣體
如果你傳入 0,你可能會得到一個估計值,它可能與實際的 gas 消耗量不同,因為 EVM gas 的定價方式。
假設轉賬金額非零,有四種情況:
- 使用者正在轉移到一個已經擁有一些代幣的帳戶(由於 SSTORE 5000 定價,這會便宜一些)
- 使用者正在轉移到一個沒有餘額的帳戶(由於 SSTORE 20000 定價,這將是昂貴的)
- 使用者正在轉移他們所有的代幣(這將在清空插槽時產生 15000 的退款,這使得 tx 更便宜,但此退款已被使用 gas 代幣利用,EIP3298建議刪除此退款)
- 使用者正在轉移他們的一些代幣(由於插槽未清空,因此不會退款)。
ERC20 Transfer tx的gas消耗可以分解為:
gas = intrinsic + computation intrinsic = 21000 + calldata cost data ~= 560 (in case of ERC20 transfer) computation ~= balanceof SLOAD + updatebalance SSTORE x 2 + event emit
例如,我嘗試在 kovan 上轉移一枚硬幣,並得到 21560 gas 的估計
您很可能將 tx 發送到沒有任何字節碼的地址。這不會使您的交易失敗。估計/消耗的氣體將只是內在成本。
如何確定代幣的轉賬 abi?我目前使用的只是 ethers js 文件中提供的標準。這適用於所有代幣嗎?
ABI 由 ERC20 標准定義。它應該適用於所有“ERC20”代幣。如果某些令牌具有不同的標準(如 ERC777),它可能無法正常工作,您必須使用正確的 ABI。