送出/揭示如何解決搶先交易?
我試圖確保我理解正確,所以我會提出解決方案的問題。
問題:
假設
commit
已被呼叫。在此之後,我們呼叫reveal
. 攻擊者監聽commit
交易,並稱其commit
為自己的前鋒。然後,攻擊者監聽reveal
交易。攻擊者現在所做的是,一旦他發現reveal
池中有一筆新交易,他就會抓取參數(這些是雜湊是如何派生的參數),對它們進行雜湊處理,如果它與已經儲存在他自己地址上的匹配當他呼叫 時commit
,攻擊者也會搶先reveal
交易。解決方案:
我認為上述問題的唯一解決方案是我們
msg.sender
在獲取承諾雜湊時包含。這樣,即使攻擊者偵聽reveal
交易並預先執行它,也不夠,因為msg.sender
攻擊者會有所不同,並且不會產生與承諾相同的雜湊。問題1:你怎麼看?我對上面的解決方案是正確的嗎?
問題 2:我看到了一些
msg.sender
在派生承諾散列時未包含的實現。這意味著front-run仍然存在,這意味著攻擊者front-runscommit
,然後front-runsreveal
。如果有很多交易發生,當然,這種預先執行對攻擊者沒有任何意義,但如果我們將其用於使用者送出解決方案並獲得的智能合約,我認為commit-reveal
方案無法解決預先執行quiz
獎勵,因為攻擊者可以再次收聽commit
並且很可能無論誰送出,很可能是贏家,因此攻擊者還將等待reveal
來自同一使用者commit
的再次呼叫並搶先執行。你怎麼看待這件事 ?對我來說,對於測驗系統,commit/reveal
似乎不是解決搶先交易的好方法。你能舉一些真正有用的例子嗎?**注意:**我知道這commit/reveal
是一個很好的方案,但我需要一些例子來解決前端執行問題並且也不會msg.sender
在散列中使用。
問題1:你怎麼看?我對上面的解決方案是正確的嗎?
同意。為了防止搶先,請使用
msg.sender
雜湊函式中的一個因子,這樣搶先者可以知道秘密,但仍然無法使用該知識。例如,考慮一個存錢罐,其中包含一個可以釋放錢的秘密單詞。如果提款功能使用(偽)
hash(secret)
,那麼領跑者可以學習密語並嘗試先提款。如果函式使用hash(msg.sender, secret)
,則防止搶先執行 - 必須從某個地址發送秘密 - 兩個因素而不是一個因素。您還應該考慮契約如何執行獎勵的授予。考慮
msg.sender.transfer()
與rightPerson.transfer()
. 您要確保效果是只有正確的帳戶才能真正獲勝。對於某些應用程序,您可能希望任何人都可以支付 gas 費用以將資金推送給合適的人。假設 Alice 沒有理由想留下她的資金,而 Bob 想成為英雄並支付她的燃料費。只要契約確定資金的去向,這種方法就可以奏效。
mapping(bytes32 => unit) public pendingPayments; function beAHero(address receiver, bytes32 secret) public { bytes32 key = keccak256(abi.encodePacked(receiver, secret)); uint amount = pendingPayments[key]; if(amount > 0) { pendingPayments[key] = 0; receiver.transfer(amount); // emit ... } }
愛麗絲可以把她的秘密告訴鮑勃,而鮑勃所能做的就是支付汽油費,如果他願意的話。無論如何,愛麗絲都能拿到錢。如果
receiver.transfer()
是,msg.sender.transfer()
那麼任何知道秘密的人都可以拿走 Alice 的錢,包括監聽未決交易的領跑者。(只是一個塗鴉,所以請原諒我的錯別字)。
希望能幫助到你。