為什麼乙太坊在執行合約查詢時將使用者餘額設置為 MaxBig256?
執行合約呼叫時,使用者錢包餘額有一個奇怪的行為(應該沒有成本)。餘額是正確的(預期值),直到請求對合約進行免費呼叫。通過調試錢包餘額發現,錢包餘額總是在這一刻變成最大值。
乙太坊程式碼有一條可疑的線,這種奇怪的行為似乎來自:
eth\api_backend.go(135): state.SetBalance(msg.From(), math.MaxBig256)
它屬於 GetEVM() 函式:
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header) (*vm.EVM, func() error, error) { ======> state.SetBalance(msg.From(), math.MaxBig256) vmError := func() error { return nil } context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil) return vm.NewEVM(context, state, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil }
這個平衡設置有什麼解釋嗎?它是協議的一部分嗎?有什麼提示嗎?多謝!
我閱讀了為什麼函式 GetEVM 將地址的餘額設置為 MaxBig256?
這是一個臨時的平衡設置,但我仍然不明白這種奇怪行為背後的邏輯。在我看來,呼叫合約時避免資金不足問題的程式碼很亂,對吧?
在乙太坊中,在 EVM 中執行操作需要消耗 gas。可以通過進行交易來改變區塊鏈中的任何狀態。在這種情況下,您將被收取乙太幣。為了進行交易,我們有一些像SendTransaction裡面的api
internal/ethapi/api.go
當您發送交易時,您可以設置 Gas 限制和 Gas 價格。您的餘額將根據進行更改所需的操作收取。
另外裡面還有一個api doCall
internal/ethapi/api.go
可以在任何方法上呼叫此 api。doCall和SendTransaction之間的區別是 - 在 doCall 的情況下,區塊鏈中不會保留任何修改。如果您的solidity 函式返回一個值,您可以通過呼叫該函式而不是進行事務來檢索該值。
所以現在來到問題的重點。當一個函式呼叫doCall api 時,雖然它不會在區塊鏈中持久化任何更改,但它需要 gas 來臨時執行記憶體中的更改。因此,它呼叫GetEVM從(內部)獲取 EVM
internal/ethapi/backend.go
由於該doCall將在 EVM 中執行操作,因此它暫時需要呼叫****doCall操作的帳戶中的餘額。因此,為from帳戶臨時設置了最大整數值,以便它可以執行操作而不管其餘額如何。
另一件事在這裡很重要,當在裡面呼叫SetBalance api時
core/state/statedb.go
它只是保存記憶體中的更改。它不會保留區塊鏈狀態中的餘額變化。通過內部呼叫Commit函式送出保存在記憶體中的更改,將塊插入鏈中時,更改將持久保存在區塊鏈中
core/state/statedb.go
在使用WriteBlockWithState api 在鏈中插入塊時
core/blockchain.go
因此,得出的結論是 - SetBalance 不會持續鏈中的餘額變化。與 doCall 的情況一樣,它沒有事務效果。所以平衡的變化永遠不會在鏈中被送出。
希望它可以幫助您理解基本概念。