Solidity

契約適用於 Remix,但不適用於松露

  • December 4, 2017

我有一個簡單的認證契約,可以將認證發送到區塊鏈。這是完整的契約:

   pragma solidity ^0.4.2;

/// @title Sending and storing certifications to the blockchain
contract CertificationStore {

struct Certification {
   string firstName;
   string lastName;
   string certName;
   string institution;
   string description;
   uint year;
   // address account;
   uint month;
   uint day;
}

mapping (address => Certification) public certifications;

Certification[] public certArray;
address[] public addressIdx;

uint numCerts;

event Send(address indexed _from);
event logIdx(address indexed _from, string location, uint idxToLog);
event logString(address indexed _from, string location, string msg);

function CertificationStore() {
   numCerts = 0;
}

function getCertArrayLength() constant returns(uint) {
   return certArray.length;
}

function getAddressIdxLength() constant returns(uint) {
   return addressIdx.length;
}

function getNumberOfCerts() constant returns(uint) {
   return numCerts;
}

function sendCert(address acct, string fn, string ln, string cn, 
   string ins, string desc, uint yy, uint mm, uint dd) returns(uint) {

   certifications[acct] = Certification({
           firstName: fn,
           lastName: ln,
           institution: ins,
           description: desc,
           certName: cn,
           year: yy,
           month: mm,
           day: dd
       });


   numCerts++;

   addressIdx.push(acct);
   certArray.push(Certification({
           firstName: fn,
           lastName: ln,
           institution: ins,
           description: desc,
           certName: cn,
           year: yy,
           month: mm,
           day: dd
       }));
   logString(acct, "in Send Cert", "pushed to both arrays");
   logIdx(acct, "in Send Cert. numCerts ", numCerts);
   Send(acct);

   return numCerts;
}

function getFirstName(address _from) constant returns(string) {

   for (uint i = 0; i < certArray.length; i++) {
       Certification cert = certArray[i];
       string name = cert.firstName;
       logIdx(_from, "at index in getFirstName", i);
       address acct = addressIdx[i];
       if(acct == _from) {
           return name;
       }
   }

   return ("no name found");
}
}

用松露,我發送契約是這樣的:

sendCert: function() {
var self = this;
this.setStatus("Initiating certification... (Please wait)");

var meta;
var myEvent;

CertificationStore.deployed().then(function(instance) {
 meta = instance;
 var firstName = document.getElementById("first").value;
 var lastName = document.getElementById("last").value;
 var certName = document.getElementById("cert_name").value;
 var date = document.getElementById("date").value;
 var description = document.getElementById("description").value;
 var institution = document.getElementById("institution").value;

 var tempDate = new Date(date);

 return meta.sendCert(account, firstName, lastName, certName, institution, description, tempDate.getFullYear(), tempDate.getMonth()+1, tempDate.getDay(), {from: account});
}).then(function(result) {
 // on success
 alert("Your certification was successfully sent for account: " + account);
 console.log("result of your deployment ", result);
 self.setStatus("Sent your certification successfully for account: " + account);
}).catch(function(e) {
 // on error set status
 console.log(e);
 self.setStatus("Error sending certification; see log.");
});
}, 

我希望結果是我設置的 numCerts 變數,它會隨著添加的契約而增加。但是它返回了完整的交易結果,但沒關係。我的問題是,在 Remix 上,它返回了這個交易結果:

tx 混音

請注意它如何儲存我在該事務中的日誌。

當我使用上面的程式碼在本地添加認證時,這是我得到的結果:

tx 本地部署

因此,當我在 Remix 上部署此合約並執行“getCertArrayLength”和“getNumCert”函式時,它會返回正確的值:每次添加合約時它都會遞增。然而,在本地,這些值仍然為 0,即使我從 truffle 得到的結果表明我的合約已成功部署在區塊鏈上。

我對此有兩個主要困惑

1)我的本地開發日誌數組每次都是空的,有什麼原因嗎?

  1. remix 如何呼叫合約的函式和我如何在javascript中呼叫它有區別嗎?

預先感謝您的幫助

Q1。只是程式碼太多。

Q2。是的,有區別。

這一行:

return meta.sendCert(account, firstName, lastName, certName, institution, description, tempDate.getFullYear(), tempDate.getMonth()+1, tempDate.getDay(), {from: account});
}).then(function(result) {

這個世界可能更有意義:

then(function(txn) { ...

當您發送交易時,您沒有得到結果,而是得到了交易

如果您想要 Remix 顯示的響應,請添加.call()

meta.sendCert.call(...

這將返回鏈的本地副本上的本地計算結果。有一個問題。這是一個只讀事務排練。它不會改變狀態,但您會看到響應。

因此,我們要麼更改狀態並看到事務但看不到結果,要麼我們可以看到響應但它沒有粘住,下次我們檢查時它就不存在了。尷尬的。

有不止一種方法可以解決這個問題。Remix 先做.call,然後再做。效仿這種做法可能並不明智。當多個交易正在進行時,實際結果不一定是預演預測的結果。這就是為什麼我的偏好通常是發送一個事務,然後檢查 getter(用於測試)或偵聽事務日誌以發現結果(用於客戶端)。

希望能幫助到你。

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