Contract-Invocation
以數組為輸入的 Solidity“呼叫”函式
例如,我在契約 A 上有一個功能:
uint256[] values; function set(uint256[] _arrayToSet){ values = _arrayToSet; }
直接呼叫時效果很好,但我想從合約 B 呼叫它,所以在 BI 中有類似的東西:
function set(address _contract, uint256[] _values){ bool d = _contract.call.gas(50764)( bytes4(sha3("set(uint256[])")),_values); }
但是,這並沒有設置值,有沒有辦法將 .call() 與數組一起用作輸入?提前致謝。
這裡的問題是 Solidity 呼叫編碼器在編碼動態數組時遇到了麻煩。下面是說明這一點的範例,假設您在 web3.eth 中有第一個合約的實例:
console.log(settingContract.set.getData([10])); 0x6ea9bfc5 0000000000000000000000000000000000000000000000000000000000000020 0000000000000000000000000000000000000000000000000000000000000001 000000000000000000000000000000000000000000000000000000000000000a
這是 set 函式呼叫的正確編碼。在這裡您可以看到函式簽名
0x6ea9bfc5
,指向數組長度的指針0x20
(在這種情況下,指針本身的大小為 32 字節),數組長度0x1
為 1(單個 32 字節字),0xa
以及第一個元素的值 10。現在讓我們看看call
假設相同的輸入會產生什麼:Debug(bytes data); function () { Debug(data); } function setIt(uint256[] _values) returns(bool) { return address(this).call(bytes4(sha3("set(uint256[])")), _values); } // Data of Debug event log from receipt of calling contract.setIt([10]); 0x6ea9bfc5 000000000000000000000000000000000000000000000000000000000000000a
這是不正確的編碼,Solidity 將其編碼為固定大小的 uint256
$$ 1 $$大批。 為了克服這個問題,您可以自己放置動態數組前綴:
function setIt(uint256[] _values) returns(bool) { return address(this).call( bytes4(sha3("set(uint256[])")), uint256(32), // pointer to the length of the array uint256(_values.length), // length of the array _values // array itself ); }
現在它將按預期工作。不過我認為這是一個編譯器錯誤,所以我會報告它。
在 ABI 規範中查看更多詳細資訊和範例:http: //solidity.readthedocs.io/en/develop/abi-spec.html#use-of-dynamic-types。