Gnosis-Safe

GS026:直接呼叫 checkNsignatures 成功,但通過 execTransaction 失敗

  • October 14, 2022

我有一個直接與之互動的 gnosis 保險箱(這裡沒有 sdk)。它有 2 個和 3 個簽名者的門檻值。我正在嘗試通過execTransaction()直接呼叫來執行 txn。它因簽名格式不正確的 GS026 錯誤而失敗,但是當我checkNsignatures直接使用相同的輸入呼叫時,它不會失敗。

我的腳本是使用 web3 和 apeWorx 的組合用 python 編寫的

首先,我得到了txn_hash

txn_hash = my_safe_master_abi.getTransactionHash(
   to,
   value,
   calldata.data,
   operation,
   safeTxGas,
   baseGas,
   gasPrice,
   gasToken,
   refundReceiver,
   nonce
)

然後我簽署 txn 雜湊並按照gnosis 文件中的描述轉換簽名

from web3.auto import w3
from eth_account.messages import encode_defunct

encoded_hash = encode_defunct(txn_hash)
signed_message1 = w3.eth.account.sign_message(encoded_hash, private_key=owner1.private_key)
ecdsa_signature1 = hex(signed_message1.r) + hex(signed_message1.s)[2:] + hex(signed_message1.v + 4)[2:]

我與其他 2 個所有者重複此過程以創建 3 個簽名。

ecdsa_signature2 = hex(signed_message2.r) + hex(signed_message2.s)[2:] + hex(signed_message2.v + 4)[2:]
ecdsa_signature3 = hex(signed_message3.r) + hex(signed_message3.s)[2:] + hex(signed_message3.v + 4)[2:]

為了測試單個簽名是否有效,我checkNsignatures將門檻值設置為 1 進行呼叫。這樣我可以在連接之前測試簽名是否單獨正確格式化。my_safe_master_abi.checkNSignatures(txnHash, datahash, ecdsa_signature1, threshold)

奇怪的是,checkNsignatures簽名 1 和 3 的成功執行,但不是 2

我繼續使用簽名 1 和 3 並將它們連接起來,同樣根據文件,檢查它們是否按升序排列:並成功signatures = ecda_signature1 + ecda_signature3[2:]呼叫checkNsignatures

然後當我my_safe_master_abi.execTransaction()使用相同的signatures變數呼叫時,它會失敗並拋出錯誤 GS026,該錯誤位於checkNsignatures直接呼叫時傳遞的函式內部

非常感謝關於為什麼簽名 2 與 1 和 3 分開失敗以及為什麼checkNsignatures在內部呼叫時失敗的幫助execTransaction

完整的原始碼(注意:帶有 eth 主網分支的本地安全帽鏈)。並不是真正將其稱為腳本,而是在猿控制台中逐行執行以找出我哪裡出錯了

txn_hash = my_safe_master_abi.getTransactionHash(
   to,
   value,
   calldata.data,
   operation,
   safeTxGas,
   baseGas,
   gasPrice,
   gasToken,
   refundReceiver,
   nonce
)

from web3.auto import w3
from eth_account.messages import encode_defunct

encoded_hash = encode_defunct(txn_hash)
signed_message1 = w3.eth.account.sign_message(encoded_hash, private_key=owner1.private_key)
signed_message2 = w3.eth.account.sign_message(encoded_hash, private_key=owner2.private_key)
signed_message3 = w3.eth.account.sign_message(encoded_hash, private_key=owner3.private_key)

## signatures1 is working
## >>> '0xf4f681475a9a03ef457c2fcf85e82f52872fc3c7ad10dd74245e6e898ad0c8d84c441b7adea575f5e10ccf3d25d80fa7efc878078ded98995ca1fa7be70a8e9720'
ecdsa_signature1 = hex(signed_message1.r) + hex(signed_message1.s)[2:] + hex(signed_message1.v + 4)[2:]
## signatures2 is not working
## >>> 0x15c81d3a62b1635e4dedb594e2b009e6943498d83cf38a89c3efaf819fc855e7a8f8cd3a13968de8ed8718c05af49e26c9b871c42325e91bb0d344b3cfdeb341f
ecdsa_signature2 = hex(signed_message2.r) + hex(signed_message2.s)[2:] + hex(signed_message2.v + 4)[2:]
## signature3 is working
## >>> 0x1183ab034b94fb9ff69e3a81abc057e23485bd2b8766491d639526367ac19a4727dd0235c6b948cd9fd3d35b436b06358f8d2e1d481c4fd544ae5f20b510fb6b20
ecdsa_signature3 = hex(signed_message3.r) + hex(signed_message3.s)[2:] + hex(signed_message3.v + 4)[2:]

## >>>'0xf4f681475a9a03ef457c2fcf85e82f52872fc3c7ad10dd74245e6e898ad0c8d84c441b7adea575f5e10ccf3d25d80fa7efc878078ded98995ca1fa7be70a8e97201183ab034b94fb9ff69e3a81abc057e23485bd2b8766491d639526367ac19a4727dd0235c6b948cd9fd3d35b436b06358f8d2e1d481c4fd544ae5f20b510fb6b20'
signatures = ecdsa_signature1 + ecdsa_signature3[2:]

## Check signature with checkN signatures
## need encoded dat
datahash = my_safe_master_abi.encodeTransactionData(
   to,
   value,
   calldata.data,
   operation,
   safeTxGas,
   baseGas,
   gasPrice,
   gasToken,
   refundReceiver,
   nonce
)

## need hashed data
txnHash = my_safe_master_abi.getTransactionHash(
   to,
   value,
   calldata.data,
   operation,
   safeTxGas,
   baseGas,
   gasPrice,
   gasToken,
   refundReceiver,
   nonce
)

## Set threshold to 1 to check individual signatures
threshold = 1

## check signature, works with signature 1, 3, & 1+3
my_safe_master_abi.checkNSignatures(txnHash, datahash, ecdsa_signature1, threshold)

theshold = 2
my_safe_master_abi.checkNSignatures(txnHash, datahash, signatures, threshold)


## try to execute a transaction
my_safe_master_abi.execTransaction(
   to,
   value,
   calldata.data,
   operation,
   safeTxGas,
   baseGas,
   gasPrice,
   gasToken,
   refundReceiver,
   signatures,
   sender = owner1
)

如果checkNSignature有效,但execTransaction無效,可能只有一個原因:交易雜湊與您計算和簽名的不同。確保您將正確的隨機數傳遞給getTransactionHash.

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