1

I'm not sure what changed, but with the original contract, I could not change the values of the variables. Originally, I had tested storing values using the setSample() function a second time... then retrieving them resulted in the second storage being ignored (the variables were the same as the first time I stored them). Now, when I store different variables under the same index (stackID) and retrieve them, it seems that I can overwrite them. Maybe I'm missing some basic fundamental like [for example], maybe immutability doesn't apply to uints, but only addresses. My goal here is to make sure that the values can't be overwritten, per the index (stackID) when stored via the EVM.

Below is the contract. Also appreciate any suggestions if there's anything else I'm doing wrong, not related to this issue.

pragma solidity ^0.4.24;

contract StackSample {

    struct Sample {
        uint48 tm;
        uint56 tdn;
        uint56 ash;
        uint56 ndf;
        uint56 adf;
        uint56 cp;
        uint48 nitr;
        uint64 rfv;
        uint64 rfq;
        uint48 nel;
        uint40 grower;
    }

    mapping(uint56 => Sample) public samples;

    address public owner;

    constructor() public {
        owner = msg.sender;
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    function setSample(uint56 _stackID, uint48 _tm, uint56 _tdn, uint56 _ash, uint56 _ndf, uint56 _adf, uint56 _cp, uint48 _nitr, uint64 _rfv, uint64 _rfq, uint48 _nel, uint40 _grower) onlyOwner public {

        Sample storage sample = samples[_stackID];

        sample.tm = _tm;
        sample.tdn = _tdn;
        sample.ash = _ash;
        sample.ndf = _ndf;
        sample.adf = _adf;
        sample.cp = _cp;
        sample.nitr = _nitr;
        sample.rfv = _rfv;
        sample.rfq = _rfq;
        sample.nel = _nel;
        sample.grower = _grower;
    }

    function getSample(uint56 _stackID) view public returns (uint48, uint56, uint56, uint56, uint56, uint56, uint48, uint64, uint64, uint48, uint40) {

        Sample storage sample = samples[_stackID];

        return (sample.tm, sample.tdn, sample.ash, sample.ndf, sample.adf, sample.cp, sample.nitr, sample.rfv, sample.rfq, sample.nel, sample.grower);
    }
}
  • Both answers are correct in that... Rob helped me to understand what is and is not immutable; and Tjaden helped me with alternatives to solve my issue. I'm on the fence as to who gets the correct answer; I'll be back to make a decision once I'm sure I'm finished with the discussion (good chance I'm not done with the thread yet as I still have some questions regarding this, but want to organize them). – tim92109 Aug 22 '18 at 20:06
  • So, could I use web3.js to deploy a new contract (created dynamically) for every set of values, using state variables or a struct to store those values? Or would that just be a nightmare trying to create byte codes 'on the fly'? – tim92109 Aug 22 '18 at 20:45
2

No values in solidity are immutable if your contract's logic chooses to change them. To protect against overwriting, you need to use a flag of some sort to mark an ID as used.

If one of your variables, say tm, is guaranteed to be nonzero once it is set, then you can do a check like

require(sample.tm == 0)

before setting the other variables.

If none of your variables are guaranteed to be nonzer0 then you can make a bool field in sample, like sample.set and set it to true on first write

| improve this answer | |
  • They could be zero... but the bool would work. – tim92109 Aug 22 '18 at 20:03
  • On the other hand, the bool is mutable in this case too, right? Maybe the tx hash could be used to verify the data hasn't changed somehow? – tim92109 Aug 22 '18 at 20:29
  • If there's no logic that can change the value, then it is for all intents and purposes "immutable". – Tjaden Hess Aug 23 '18 at 21:49
  • You have a very good point. Especially if I add something to make the setSample function fail if the index already exists. – tim92109 Aug 27 '18 at 15:01
1

@Tjaden is right. In case it is of practical assistance ...

From your description, there was something wrong with your first implementation. The result was misleading. You can certainly overwrite your variables if you want to, as this contract demonstrates.

What remains immutable is the contract code, the transaction that deployed the contract, the transaction that set the first values and the transaction(s) that came later and wrote over previous states. The history can't be undone.

Hope it helps.

| improve this answer | |
  • Very strange that the first implementation actually worked. And you did help me a lot to understand what is and is not immutable. – tim92109 Aug 22 '18 at 20:00

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.