Gnosis-Safe

safeTxGas 總是以 0 結束,這會導致多發送合約內部恢復

  • March 17, 2022

由於建議發布完整的程式碼片段,因此製作了一個後續執行緒:“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無關)。

我希望它能提供更好的錯誤消息,但如果您看到此錯誤消息,那麼專注於氣體可能會導致錯誤的樹。最好對您的預期交易進行故障排除。

引用自:https://ethereum.stackexchange.com/questions/118024