Solidity

呼叫非視圖函式時如何獲取返回值?

  • January 27, 2022

我在下面寫了一個簡單的契約,其中儲存了每個 ID 的所有問卷結果。

contract answer{
 mapping(address => mapping(string => bool)) voters;

 struct qList {
   uint count; //The number of respondents
   mapping(address => mapping(uint => uint)) answer;
 }

 mapping(string => qList) questionnaires;

 function vote(string ID, uint qNum, uint ans) returns (bool) {
   if(voters[msg.sender][ID]) throw;
   voters[msg.sender][ID] = true;
   questionnaires[ID].count += 1;
   questionnaires[ID].answer[msg.sender][qNum] = ans;
   return true;
 }

 function getNumResult(string ID) constant returns (uint res) {
   return questionnaires[ID].count;
 }
}

該函式vote可以被成功呼叫和探勘,但是我無法獲取vote.

如果有人會建議導致此問題的原因和解決方案以獲取帶參數的函式的返回值,我們將不勝感激。

概括

當我通過geth控制台執行程式碼時,您的程式碼會按預期執行。如果它對您不起作用,請嘗試增加您在交易中發送的氣體。

正如@Taylor Gerring他在回答中所說,您可能無法從您的vote()函式中獲得結果,但您的程式碼似乎可以正常工作。

如果你想要你的vote()函式的結果,在你的例子中是檢查一個人之前是否投票過,你的數據中已經有了這個voters數據。


細節

我已經獲取了您的原始碼,只是將類名從更改answerAnswer,並將您的評論從//更改為/*...*/

contract Answer {
 mapping(address => mapping(string => bool)) voters;

 struct qList {
   uint count; /* The number of respondents */
   mapping(address => mapping(uint => uint)) answer;
 }

 mapping(string => qList) questionnaires;

 function vote(string ID, uint qNum, uint ans) returns (bool) {
   if (voters[msg.sender][ID]) throw;
   voters[msg.sender][ID] = true;
   questionnaires[ID].count += 1;
   questionnaires[ID].answer[msg.sender][qNum] = ans;
   return true;
 }

 function getNumResult(string ID) constant returns (uint res) {
   return questionnaires[ID].count;
 }
}

我已經從程式碼中刪除了 CR-LF 並折疊了空格,並在中執行了以下語句geth

> var answerSource='contract Answer { mapping(address => mapping(string => bool)) voters; struct qList { uint count; /* The number of respondents */ mapping(address => mapping(uint => uint)) answer; } mapping(string => qList) questionnaires; function vote(string ID, uint qNum, uint ans) returns (bool) { if(voters[msg.sender][ID]) throw; voters[msg.sender][ID] = true; questionnaires[ID].count += 1; questionnaires[ID].answer[msg.sender][qNum] = ans; return true; } function getNumResult(string ID) constant returns (uint res) { return questionnaires[ID].count; }}'
undefined

然後我編譯了您的程式碼並將其插入到我的開發區塊鏈中:

> var answerCompiled = web3.eth.compile.solidity(answerSource);
undefined

> var answerContract = web3.eth.contract(answerCompiled.Answer.info.abiDefinition);
undefined 

> var answer = answerContract.new({
   from:web3.eth.accounts[0], 
   data: answerCompiled.Answer.code, gas: 2000000}, 
   function(e, contract) {
     if (!e) {
       if(!contract.address) {
         console.log("Contract transaction send: TransactionHash: " 
           + contract.transactionHash + " waiting to be mined...");
       } else {
         console.log("Contract mined! Address: " + contract.address);
         console.log(contract);
       }
   }
})

Contract transaction send: TransactionHash: 0x5b5eb3c6d2a4b43eff4444b71b762911ddc72e239d1d495b6bec7b2e6a738df0 waiting to be mined...

我等待合約被探勘並收到以下消息:

Contract mined! Address: 0xe51ac93e4c28206f0f0296e5b6d66daf0a917bc3
[object Object]

檢查getNumResult()

> answer.getNumResult("idOne")
0

投票:

> answer.vote("idOne", 1, 1, eth.accounts[0], {
 from:web3.eth.accounts[0], 
 data: answerCompiled.Answer.code,
 gas: 1000000
});
"0xfcbf47472733c0922552aa617fc7cb1226c346edc022fbe09ea521dfb75f7699"

等待交易被探勘並檢查交易:

> eth.getTransaction("0xfcbf47472733c0922552aa617fc7cb1226c346edc022fbe09ea521dfb75f7699")
{
 ...
 blockNumber: 6567,
 ...
}

檢查getNumResult()

> answer.getNumResult("idOne")
1

使用不同的 ID 發送另一個投票:

> answer.vote("idTwo", 2, 1, eth.accounts[0], {
 from:web3.eth.accounts[0], 
 data: answerCompiled.Answer.code,
 gas: 1000000
});

檢查結果:

> answer.getNumResult("idTwo")
1

用相同的 ID 從同一個帳戶發送另一個投票:

> answer.vote("idOne", 2, 1, eth.accounts[0], {
 from:web3.eth.accounts[0], 
 data: answerCompiled.Answer.code,
 gas: 1000000
});
"0xbbf9db6eb7c02571948002f56e3a7c56b6c7f55c2a4bbc70a244bb2afbf44e1f"

我注意到以下錯誤:

PC 00000366: JUMP GAS: 976744 COST: 8 ERROR: invalid jump destination (PUSH1) 2

throw如果同一個ID是從同一個賬戶投票的,那麼上面的錯誤肯定是由你程式碼中的語句產生的:

if (voters[msg.sender][ID]) throw;

然後,我從我的第二個帳戶發送了另一票:

> answer.vote("idOne", 2, 1, eth.accounts[1], {
 from:web3.eth.accounts[1], 
 data: answerCompiled.Answer.code,
 gas: 1000000
});

結果按預期更新:

> answer.getNumResult("idOne")
2

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