4

See my smart contract below :

contract Test {

    struct MyBool {
        bool initialized; // /!\ if false then 'NA' else fetch value's property
        bool value;
    }

    struct Patient {
        uint8 age;
        uint8 bp;
        uint8 sg;
        int8 al;
        int8 su;
        MyBool rbc;
        MyBool pc;
        MyBool pcc;
        MyBool ba;
        uint16 bgr;
        uint8 bu;
        uint8 sc;
        uint16 sod;
        uint8 pot;
        uint8 hemo;
        uint8 pcv;
        uint8 wc;
        uint8 rc;
        MyBool htn;
        MyBool dm;
        MyBool cad;
        MyBool appet;
        MyBool pe;
        MyBool ane;
    }

    uint nextPatientId;
    mapping (uint256 => Patient) private patients;

    function Test() {
        // age, bp, sg, al, su, rbc, pc, pcc, ba, bgr, bu, sod
        addPatient(4, 0, 20, 1, 0, -1, 1, 0, 0, 99, 23, 145);
    }

    function setMyBool(int8 value) private returns (bool initialized, bool newValue) {
        if (value < -1  || value > 1) {
            throw;
        }
        // if different than 'NA'
        if (-1 != value) {
            initialized = true;
            newValue = (value==1) ? true : false;
        }
    }

    function getMyBool(MyBool patientField) private returns (int8) {
        if (patientField.initialized == true) {
            return (int8)((patientField.value) ? 1 : 0); 
        } else {
            return 127;
        }
    }

    function getNextPatientId() constant returns (uint) {
        return nextPatientId;
    }

    function addPatient(uint8 age, uint8 bp, uint8 sg, int8 al, int8 su,
                        int8 rbc, int8 pc, int8 pcc, int8 ba,
                        uint16 bgr, uint8 bu, uint16 sod) returns (uint id) {
        var patient = patients[nextPatientId];

        patient.age = age; patient.bp = bp; patient.sg = sg; patient.al = al; patient.su = su;
        (patient.rbc.initialized, patient.rbc.value) = setMyBool(rbc);
        (patient.pc.initialized, patient.pc.value) = setMyBool(pc);
        (patient.pcc.initialized, patient.pcc.value) = setMyBool(pcc);
        (patient.ba.initialized, patient.ba.value) = setMyBool(ba);
        patient.bgr = bgr; patient.bu = bu; patient.sod = sod;

        nextPatientId++;
        id = nextPatientId;
    }

    function getMyPatient(uint id) constant returns (uint8 age, uint8 bp, uint8 sg, int8 al, int8 su,
                        int8 rbc, int8 pc, int8 pcc, int8 ba,
                        uint16 bgr, uint8 bu, uint16 sod) {
        age = patients[id].age; bp = patients[id].bp; sg = patients[id].sg; al = patients[id].al; su = patients[id].su;
        rbc = getMyBool(patients[id].rbc); pc = getMyBool(patients[id].pc); pcc = getMyBool(patients[id].pcc); ba = getMyBool(patients[id].ba);
        bgr = patients[id].bgr; bu = patients[id].bu; sod = patients[id].sod;
    }

}

I read here and there that params of a function cannot exceed a constant a specific amount because of the "stack" behaviour.

As you can see my struct is pretty large and I wanted to have a getter and a setter of this.

It is not possible to return a struct but retrieve all value of a struct by calling multiple methods is fine for me. I just don't want this behaviour when setting one.

Is there a workaround for this ? I thought of having a constant array as params to decrease the number of variables but I'm not sure it is a proper way.

EDIT The code above works because I just keep as much as possible of params that the compiler allow me to have but what I really want is a complete setter of my struct like below for instance (which is not working)

function addPatient(uint8 age, uint8 bp, uint8 sg, int8 al, int8 su,
            int8 rbc, int8 pc, int8 pcc, int8 ba,
            uint16 bgr, uint8 bu, uint16 sod, 
            uint8 pot, uint8 hemo, uint8 pcv, uint8 wc, uint8 rc,
            int8 htn, int8 dm, int8 cad, int8 appet, int8 pe, int8 ane) returns (uint id) {
    var patient = patients[nextPatientId];

    patient.age = age; patient.bp = bp; patient.sg = sg; patient.al = al; patient.su = su;
    (patient.rbc.initialized, patient.rbc.value) = setMyBool(rbc);
    (patient.pc.initialized, patient.pc.value) = setMyBool(pc);
    (patient.pcc.initialized, patient.pcc.value) = setMyBool(pcc);
    (patient.ba.initialized, patient.ba.value) = setMyBool(ba);
    patient.bgr = bgr; patient.bu = bu; patient.sod = sod;

    patient.pot = pot; patient.hemo = hemo; patient.pcv = pcv; patient.wc = wc; patient.rc = rc;
    (patient.htn.initialized, patient.htn.value) = setMyBool(htn);
    (patient.dm.initialized, patient.dm.value) = setMyBool(dm);
    (patient.cad.initialized, patient.cad.value) = setMyBool(cad);
    (patient.appet.initialized, patient.appet.value) = setMyBool(appet);
    (patient.pe.initialized, patient.pe.value) = setMyBool(pe);
    (patient.ane.initialized, patient.ane.value) = setMyBool(ane);


    nextPatientId++;
    id = nextPatientId;
}
  • This contract compiled and ran in browser solidity. I was able to add a patient by passed 24x1 ... 1,1,1,1,1,1 ... Details about how you're compiling and deploying, steps to reproduce the error might help pinpoint the problem. – Rob Hitchens - B9lab Jan 3 '17 at 20:34
  • I also run this in browser solidity. I'm sorry I was not clear but indeed the contract works, but it works only because I keep the signature of addPatient to only fews params params instead of what I just edit here. – onepix Jan 3 '17 at 21:06
  • Data storage is pretty tricky and there's a lot going on here that makes me go "hmmm ...." The solution you are considering looks like a valid approach for the immediate issue. Example: function testIO(uint8[24] patientData) returns(bool success) {} – Rob Hitchens - B9lab Jan 3 '17 at 21:36
  • Well, I'll do that for the moment as a quick fix, thanks. – onepix Jan 4 '17 at 9:26
2

After trying the other approach which consist to use a static array where each index value represent a variable previously related to a variable of my 'Patient' struct, I can confirm that it works great and also makes the code clearer (to read at least).

The only thing I recommend is to have a proper doc which explain your array like this :

/* uint16[25] kidneyData;
 *
 * -------------------------------------------------------------------------------------------------------------------------------------------------
 * |                   DECIMAL VALUE                     |      FLOAT VALUE     |               NOMINAL VALUE                             | RESULT |
 * -------------------------------------------------------------------------------------------------------------------------------------------------
 * |  0  | 1  | 2  | 3  | 4  | 5   | 6  | 7   | 8   | 9  | 10 | 11 | 12  | 13   | 14  | 15 | 16  | 17 | 18  | 19 | 20  | 21    | 22 | 23  |   24   |
 * | age | bp | sg | al | su | bgr | bu | sod | pcv | wc | rc | sc | pot | hemo | rbc | pc | pcc | ba | htn | dm | cad | appet | pe | ane |   res  |
 * -------------------------------------------------------------------------------------------------------------------------------------------------
 *
 * EXEMPLE :
 *                   | age | bp | sg | al | su | bgr | bu | sod | pcv | wc | rc | sc | pot | hemo | rbc | pc | pcc | ba | htn | dm | cad | appet | pe | ane |
 * caduceus.addPatient([60,  80,  25,   0,   0,   131,  10, 146,  41, 10700, 510, 50,  500,  1450,   1,   1,   0,    0,   0,    0,   0,     1,     0,   0]);
 *
 */

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.