交易不會被探勘/交易簽名失敗
我正在嘗試發送一個在乙太坊(kovan)上寫一些東西的交易,但似乎我的交易沒有被探勘,甚至可能沒有發送到網路?我對乙太坊的所有視圖請求都有效,所以我的猜測是我的交易簽名有問題?觸發我的腳本後,我收到一個 txHash,但在 kovan.etherscan.io 上找不到該 txHash。我想我可能會設置一個太低的 gas 價格並且我的交易被卡在了礦池中,但是我什至無法在礦池中找到我的交易,所以我猜我的腳本甚至沒有正確發送它?
const Web3 = require('web3'); var Tx = require('ethereumjs-tx').Transaction const web3 = new Web3(new Web3.providers.HttpProvider("https://kovan.infura.io/v3/-XXX-")); var contractAddress = "0x07026847C635D66d243971838E69365c9675Cd68"; var abi = -XXX-; var contract = new web3.eth.Contract(abi, contractAddress); var account = "-XXX-"; const privateKey = Buffer.from('-XXX-', 'hex'); const data = contract.methods.createLocation("test-location7").encodeABI() contract.methods.viewNewestComment().call().then(console.log); web3.eth.getTransactionCount(account, (err, txCount) => { console.log(txCount); const txObject = { nonce: web3.utils.toHex(txCount), gasLimit: web3.utils.toHex(200000), gasPrice: web3.utils.toHex(web3.utils.toWei('9', 'gwei')), to: contractAddress, data: data } const tx = new Tx(txObject) tx.sign(privateKey) const serializedTx = tx.serialize() const raw = '0x' + serializedTx.toString('hex') web3.eth.sendSignedTransaction(raw, (err, txHash) => { console.log('err:', err, 'txHash:', txHash) }) })
所以我的腳本在觸發後應該做的是:使用 createLocation 方法並在區塊鏈上“寫入”一個新的位置名稱,簽署交易,最後給我 txHash。但即使我得到一個 txHash,我也不認為交易是成功的。750 秒後,我在控制台中收到以下錯誤消息:“錯誤:交易未在 750 秒內開採,請確保您的交易已正確發送。”
我使用 remix.ethereum.org 部署了我的契約。當我在 remix 中使用 createLocation 方法時,它可以工作!Metamask 要求我簽署交易,然後我可以在 etherscan 上找到我的交易。
pragma solidity ^0.5.12; contract NewContract { struct Location { string JSON; uint time; string comment; } Location[] locations; function createLocation(string memory _json) public { locations.push(Location(_json, now, 'no comment')); } function addComment(string memory _comment, uint _id) public { locations[_id].comment = _comment; } function addCommentToNewest(string memory _comment) public { uint _id = locations.length - 1; locations[_id].comment = _comment; } function viewLocation(uint _id) public view returns(string memory) { string memory result = locations[_id].JSON; return result; } function viewTimestamp(uint _id) public view returns(uint) { uint result = locations[_id].time; return result; } function viewComment(uint _id) public view returns(string memory) { string memory result = locations[_id].comment; return result; } function viewEverything(uint _id) public view returns(string memory, uint, string memory) { string memory result1 = locations[_id].JSON; uint result2 = locations[_id].time; string memory result3 = locations[_id].comment; return (result1, result2, result3); } function viewNewestLocation() public view returns(string memory) { uint _id = locations.length - 1; string memory result = locations[_id].JSON; return result; } function viewNewestTimestamp() public view returns(uint) { uint _id = locations.length - 1; uint result = locations[_id].time; return result; } function viewNewestComment() public view returns(string memory) { uint _id = locations.length - 1; string memory result = locations[_id].comment; return result; } function viewNewestEverything() public view returns(string memory, uint, string memory) { uint _id = locations.length - 1; string memory result1 = locations[_id].JSON; uint result2 = locations[_id].time; string memory result3 = locations[_id].comment; return (result1, result2, result3); } }
這是我的智能合約。我實際上想將新的位置名稱創建為字元串,並希望在創建後添加註釋。
我希望你能幫幫我 :)
我實際上通過閱讀 ethereumjs-tx 的文件解決了這個問題,它說:當使用 2.0.0 版本的包 ethereumjs-tx 時,如果我們不指定參數鏈,它將使用主網,所以如果你想要在其他網路上使用,您應該添加此參數鏈來指定。
因此,如果您將交易指定給 kovan ({‘chain’:‘kovan’}) 或 ropsten,它實際上可以工作:)
該錯誤僅表明您的交易尚未被探勘,而不是它有任何問題:
Transaction was not mined within 750 seconds, please make sure your transaction was properly sent
此外,它甚至會告訴您確保它已被發送(儘管“探勘”在這裡可能更合適)。
您可以通過檢查您發送交易的賬戶或您發送交易的目的地地址的交易列表來做到這一點。
在任何情況下,這種情況(我什至不會稱其為“錯誤”)通常發生在您的 gas 價格不夠高時,因為它越低 - 您的交易完成所需的時間就越長。
通過增加此值,您可以將執行時間減少到 750 秒以下並避免這種情況。
更新:
我注意到你使用了一個恆定的 gas-limit 值,而沒有考慮完成特定交易所需的實際金額。
該參數與上述參數(gas-price)一起決定了您的交易將由一位礦工執行的速度。
與隨著平均執行時間的增長而增加平均執行時間的gas-price相比,gas-limit隨著增長而減少平均執行時間。
因此,理想情況下,您應該傳遞執行交易所需的確切金額。
您可以這樣做:
const transaction = contract.methods.createLocation("test-location7") web3.eth.getTransactionCount(account, (err, txCount) => { transaction.estimateGas({from: account}).then(gas => { console.log(txCount, gas); const txObject = { nonce: web3.utils.toHex(txCount), gasLimit: web3.utils.toHex(gas), // instead of 200000 gasPrice: web3.utils.toHex(web3.utils.toWei('9', 'gwei')), to: contractAddress, data: transaction.encodeABI() } ... }) }