圖書館如何改變狀態?
我有關於圖書館的非常有趣的案例。
情況1:
我在官方的 Solidity 文件中閱讀了以下內容:
如果庫函式不修改狀態(即如果它們是視圖或純函式),則只能直接呼叫庫函式(即不使用 DELEGATECALL),因為假定庫是無狀態的
我確信他們的意思是使用
.call
地址上的 來呼叫庫,他們說這只有在庫的功能是pure/view
. 讓我在a), b), c)
我不明白的地方重新表述。**a)**在複製的句子中,它說:
if they do not modify the state
。我不確定圖書館是如何改變狀態的。它沒有自己的,它所能做的就是改變傳遞變數的值。**b)**我嘗試將它與 一起使用
addr.call
,但我沒有指定函式 aspure/view
並且它仍然讓我這樣做。有趣的是為什麼它讓我在文件中說它應該恢復。**c)**為什麼我想用 呼叫庫
.call
?這只是違背了圖書館的全部目的。**D) ** 似乎如果我
internal
在庫上使用函式,庫程式碼最終會出現在合約的編譯版本中。這有什麼好處?如果是這樣,我會使用另一個契約而不是圖書館。案例二:
在文件中,它如何傳遞引用類型確實是一個糟糕的例子。假設我有一個圖書館:
// Let's say this was written by third-party and it's put on github. library libraryContract { function libraryTest(){ } } // I can import the above here. // import "libraryContract.sol"; contract myContract { function contractTest(){ // I call it. This will work. Now, let's say in this contract, I // have a variable called `uint x = 0;`. and what libraryContract // should be doing is change the value of the passed argument. // If I pass `x` here directly, and change the argument in //`libraryTest`, It still doesn't work since it's not passed by //reference or something. Another case is What If I want my library //to be changing the struct's properties, but library doesn't see //the definiton of struct. libraryContract.test(); } }
a)在複製的句子中,它說:如果他們不修改狀態。我不確定圖書館是如何改變狀態的。它沒有自己的,它所能做的就是改變傳遞變數的值。
庫可以通過委託呼叫更改呼叫合約的狀態。在這種情況下,函式的執行就像它是直接寫在呼叫合約中一樣。這意味著它理論上可以修改呼叫合約狀態的任何部分,只要相應的變數已在庫中聲明(但未初始化,因為庫沒有自己的狀態)。文件的意思是,如果您嘗試直接呼叫這樣的函式,它將失敗,因為它不打算更改/修改自己的儲存(因為不存在這樣的儲存),而是呼叫合約上的相應儲存.
b) I tried using it with addr.call, but I didn't specify functions as pure/view and it still let me do this. It's interesting why it let me since in the docs, it says it should revert.
將函式標記為
pure
/view
不是強制性的,因此只要函式實際上不嘗試修改狀態,事務就不會恢復。c) Why would I ever want to call libraries with the .call ? This just defeats the whole purpose of libraries.
庫可用於修改呼叫合約的狀態(通過
delegatecall
),但它也可以表現得像具有靜態方法的類。例如,假設您總是發現自己在合約中需要一些熟悉的常量或方法(uint pi
、uint days_in_year
function n_squared(uint n)
等)。您可以將它們分解到庫中,以避免必須將它們包含在您編寫的每個契約中。然後它們只在區塊鏈上儲存一次,其他合約call
在需要時只儲存它們。
似乎如果我在庫上使用內部函式,庫程式碼最終會出現在合約的編譯版本中
一個應用程序是可重用程式碼。例如SafeMath使用內部函式。這樣,當你這樣做時
a.add(b)
,它會在不使用delegatecall
. 如果delegatecall
要使用 a,計算最終將非常昂貴。然而,在未來,由於免費功能,這種對庫的使用可能會變得不那麼普遍。
“狀態問題”的一個簡單範例是:
library L { function f() external { assembly { sstore(0, 1) } } }
因此,如果沒有呼叫保護,那麼您將寫入庫的狀態。