Contract-Design
使用事件返回結構數組?
我不想讓我的函式吐出一組結構。我知道這不是直接可能的。對我來說最好的方法是什麼?我是否應該在我的函式中循環遍歷我的數組並每次觸發一個事件以分別返回每個結構的參數?我是否應該通過循環遍歷我的數組並將其作為字元串吐出來創建一個大型 json 對象?有沒有更直接的方法來做到這一點?
我將建議一種更像乙太坊的方法。
您可能可以使用實驗性 ABI 編碼器來做到這一點。除了穩定性問題外,整體方法也存在嚴重問題。**操作的gas成本將隨著數組的大小而增加。**如果數組變得太大,這將使其不切實際或無法使用。
在大多數情況下,返回整個數組是浪費和多餘的。您可以並且應該為每個狀態更改發出事件。這意味著觀察者、客戶端和伺服器無需詢問即可知道陣列的狀態。在大多數情況下,它減少了返回整個數組的需要。
在某些情況下,客戶或契約想要知道元素的內容。一個元素可以在具有 O(1) 複雜性和任何規模的一致 gas 成本的函式中返回,所以這就是我們應該做的。
客戶可能希望迭代(無論出於何種原因)。然而,迭代的苦差事通常可以外部化。讓客戶端根據需要多次呼叫 O(1) 函式。請記住,區塊鍊是事實的來源和數據完整性的證據。它不是通用計算平台,處理成本很高。
穩定的 ABI 可以在內部而不是外部將結構傳入/傳出函式。在外部,我們將結構分解為成員。
儲存組織是一個挑戰,因此這可能會有所幫助:Solidity 是否存在解決良好且簡單的儲存模式?
使用最簡單的數組思想,我想出了這個表達建議方法的小例子。
pragma solidity 0.5.1; contract ArrayOfStructs { // just an arbitrary struct layout struct Thing { uint a; bool b; } // an array of structs Thing[] public things; event LogAppendThing(address sender, uint a, bool b); // set function append(uint _a, bool _b) public { Thing memory t = Thing({ a: _a, b: _b }); things.push(t); // emit an event emit LogAppendThing(msg.sender, _a, _b); } // "public" in line 14 gives a "free" getter, like /* function things(uint index) public view returns(uint, bool) { return (things[index].a, things[index].b); } */ // it can be helpful to give a client a count, so it can know the boundary. function thingCount() public view returns(uint count) { return things.length; } }
希望能幫助到你。