Contract-Invocation

以數組為輸入的 Solidity“呼叫”函式

  • March 12, 2018

例如,我在契約 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

引用自:https://ethereum.stackexchange.com/questions/16144