safeTxGas 總是以 0 結束,這會導致多發送合約內部恢復
由於建議發布完整的程式碼片段,因此製作了一個後續執行緒:“Out of gas” revert inside the multisend contract
我們仍然在多發送合約中遇到恢復問題,並且已將其隔離為由 safeTxGas 參數引起的,以某種方式總是最終為 0(甚至嘗試使用一些花哨的傳播運算符工作將其硬編碼為非零值,但仍然為 0) .
我們查看了https://github.com/gnosis/safe-contracts/blob/a6504a9afdeac186a8cdb29ad68b189523c80eda/docs/safe_tx_gas.md上的文件並看到了意外行為。
這是其中一個失敗交易的範例:https ://rinkeby.etherscan.io/tx/0x076124dd128c3ce347c8f60c2bf984e505b0b926a95f04fe8de0b5702708dbdb
上面的文件提到“這意味著如果 safeTxGas 設置為 0,則安全合約在執行內部安全交易時會發送所有可用的氣體。” 但是在https://rinkeby.etherscan.io/tx/0x076124dd128c3ce347c8f60c2bf984e505b0b926a95f04fe8de0b5702708dbdb#internal我們可以看到,Gas Limit 設置為 0 而不是轉發剩餘的 gas,這會導致 Out of Gas 恢復。我們看到它失敗了,因為它沒有氣體,不像這個論壇上的其他問題,有人試圖發送比他們擁有的更多的乙太幣或類似的東西。
完整的程式碼片段發佈在下面:
const { default: EthersSafe, EthersAdapter } = require("@gnosis.pm/safe-core-sdk"); const ethers = require("ethers"); const ERC20Contract = require("../artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json"); const erc20Interface = new ethers.utils.Interface(ERC20Contract.abi); // Address constants const safeAddress = "0x7328285B4435dbc51897DC2d900D21707d14253e"; const BATERC20Rinkeby = "0xbF7A7169562078c96f0eC1A8aFD6aE50f12e5A99"; const zrxERC20Rinkeby = "0xddea378A6dDC8AfeC82C36E9b0078826bf9e68B6"; const recipient1 = "0x6c25c43856df0fcb79b151c9c2f9a9dcc2eb46be"; async function main() { const provider = ethers.getDefaultProvider(process.env.INFURA_RINKEBY_URL); const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider); const ethAdapter = new EthersAdapter({ ethers, signer }); const safeSdk = await EthersSafe.create({ ethAdapter: ethAdapter, safeAddress: safeAddress, }); // Create Transaction const multiSendTx = [ { to: zrxERC20Rinkeby, data: erc20Interface.encodeFunctionData("transfer", [ recipient1, ethers.BigNumber.from(10).pow(18).mul(1), ]), value: "0", }, { to: BATERC20Rinkeby, data: erc20Interface.encodeFunctionData("transfer", [ recipient1, ethers.BigNumber.from(10).pow(18).mul(1), ]), value: "0", } ]; const txOptions = { safeTxGas: 2300, baseGas: 112000, refundReceiver: signer.address, gasPrice: 3500000000 //gasPrice: 2500000000, //gasToken: "0x0000000000000000000000000000000000000000" }; const safeTransaction = await safeSdk.createTransaction(multiSendTx, txOptions); console.log(safeTransaction); // Execute Transaction const execOptions = { gasLimit: 350000 }; //const executeTxResponse = await safeSdk.executeTransaction(safeTransaction, execOptions); //const receipt = await executeTxResponse.transactionResponse?.wait(); //console.log(receipt.transactionHash); } main() .then(() => process.exit(0)) .catch((error) => { console.error(error); process.exit(1); });
謝謝參觀!
在您連結的 Rinkeby 交易中,您
gasPrice
為 SafeTransaction 設置了一個。在這種情況下,
safeTxGas
發送指定的 gas 是為了避免中繼器使用比預期更多的 gas,從而增加退款。with gas refund
您連結的文件部分中提到了這一點。正如您連結的另一個問題中所述,這似乎是 sdk 中的一個錯誤,
safeTxGas
在您的範例中未應用。我建議在 Safe core sdk 上打開一個問題。
清單項目我只想分享給其他可能會在這裡結束的人:
通過反複試驗,我確定由於某種原因,Gnosis 在預測交易將失敗的任何時候都會拋出這個錯誤+路障,它與 gas 無關 - 它只是試圖保護你並拒絕讓你嘗試通過限制你的氣體。
我(例如)正在嘗試通過我的 gnosis multisig 部署契約(目前在 rinkeby 上)。這適用於週五的三個範例合約。然而,使用最新版本的合約 initcode,它不會。
我認為這是我的錯,我錯誤地使用了 Web 界面。唯一的錯誤是,在嘗試執行交易時,我會看到與該使用者相同的錯誤消息——“交易可能會失敗”,嘗試手動添加氣體,看到 metamask 抱怨,safetxgas 為 0。只是無法強制它通過。後來,通過溫柔的使用,我能夠弄清楚實際的錯誤是什麼(與gas無關)。
我希望它能提供更好的錯誤消息,但如果您看到此錯誤消息,那麼專注於氣體可能會導致錯誤的樹。最好對您的預期交易進行故障排除。