0

I have a simple certifications contract that sends a certification to the blockchain. This is the full contract:

    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");
}
}

With truffle, I am sending the contract like so:

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.");
});
 }, 

I expected result to be the numCerts variable I set, which increments per added contracts. However it returned the full transaction result but thats fine. My issue is that on Remix, it returns this transaction result:

tx on remix

Note how it stores the logs that I have in that transaction as well.

When i use the code above to add certifications locally, this is the result I get back:

tx local deployment

consequently, when I deploy this contract on Remix, and i run the "getCertArrayLength" and "getNumCert" functions, it returns the correct value: it increments every time a contract is added. Locally however, these values remain 0 even though I am getting a result back from truffle saying my contract was deployed successfully on the block chain.

I have two main confusions with this

1) is there a reason why my logs array on local development is empty every time?

2) is there a difference in how remix calls the functions of the contract and how I am calling it in javascript?

thank you in advance for your help

1

Q1. Just too much code.

Q2. Yes, there's a difference.

This line:

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

The world may make more sense with this:

then(function(txn) { ...

When you send a transaction, you don't get the result, you get the transaction.

If you want the response like Remix shows, add .call()

meta.sendCert.call(...

This will return the result of a local computation on the local copy of the chain. There's a catch. It's a read-only transaction rehearsal. It doesn't change state, but you'll see the response.

So, we either change the state and see the transaction but not the result, or we can see the response but it doesn't stick and it's not there next time we check. Awkward.

There's more than one way to approach this. Remix does a .call first and then does it for real. It might not be wise to emulate that. When multiple transactions are in flight the actual result won't necessarily be what the rehearsal predicted. This is why my preference is usually to send a transaction and then inspect getters (for tests) or listen to the transaction logs to discover results (for clients).

Hope it helps.

  • Thank you for your advice! When i inspected using the getters above, getNumberOfCerts and such, they all returned 0 suggesting that the number of certifications was not getting updated (even though the certification was being sent, and the chain updated apparently). This is strange to me since they are getting updated on Remix and returning the correct value. I am using .call on those methods since this is read-only as well. – Karan Dec 4 '17 at 5:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.