0

I am designing / developing a smart contract in which we have 2 types of object : moving object and non moving object. Both types state is changed time to time. ex. in case of moving object its location can be changed, but in non moving object we do not have location change, but also ex. we have object's owner change. So, I defined a struct as follows:

struct Object{
    byte[] nonMoveState;
    byte[] MoveState;
  }
  mapping(address => Object) state;

And I also defined an event as follows to keep history of changes to show it in the transaction hash:

event changeAction(address indexed objectAdd, byte actionType, byte actionValue);

Now, I need to record all changes, ex. in case of moving object, its place is changed from Paris to London. Then, if I do it as follows:

function setAction(address indexed objectAdd, byte actionType, byte actionValue) public returns (bool) {

    state[objectAdd].MoveState[].push("actionValue");
    emit changeAction(address indexed objectAdd, byte actionType, byte actionValue);

    return true;
  }

And invoking function :

setAction(0xE07b6e5a2026CC916A4E2Beb03767ae0ED6af773, "change place", "Paris");

setAction(0xE07b6e5a2026CC916A4E2Beb03767ae0ED6af773, "change place", "London");

Is there something wrong?

***Additional Information : In fact, in case of moving object, the new "action" is read/written by RFID/NFC and then new state is stored in the blockchain.

1 Answer 1

1

You can use arrays (and mapping and struct) nested inside structs. I wouldn't do it quite like that.

byte[] is an array of single-byte. A natural way to work with that is when you want to consume or append one byte at a time. It wouldn't be my first choice for a chunk like "Paris".

You mention a need to record all changes. You did not say for whose consumption. This is important because there is a cheap and natural way to do it, based on the assumption that the contract will always be interested in the current state. That is, the contract doesn't need access to history, but observers do. Use events for that.

Using an address for a key is natural if the topic is a user or a contract. I might suggest using a meaningless bytes32 in other cases.

Here is a general-purpose pattern adapted for your example. See Are there well-solved and simple storage patterns for Solidity?

pragma solidity 0.4.19; 

contract Object {

    struct ObjectStruct {
        bytes32 location;
        address owner; // caution about using "owner" because it has a de facto meaning in standard contracts. Landlord, titleHolder ... 
        bool isObject;
    }

    mapping(bytes32 => ObjectStruct) public objectStructs;
    bytes32[] public objectList;

    event LogNewObject(address sender, bytes32 uid, bytes32 location, address owner);
    event LogChangeObjectLocation(address sender, bytes32 uid, bytes32 newLocation);
    event LogChangeObjectOwner(address sender, bytes32 uid, address newOwner);

    function isObject(bytes32 _uid) public view returns(bool isIndeed) {
        return objectStructs[_uid].isObject;
    }

    function getObjectCount() public view returns(uint count) {
        return objectList.length;
    }

    function newObject(bytes32 _uid, bytes32 _location, address _owner) public returns(bool success) {
        require(!isObject(_uid));
        objectStructs[_uid].location = _location;
        objectStructs[_uid].owner = _owner;
        objectStructs[_uid].isObject = true;
        objectList.push(_uid);
        LogNewObject(msg.sender, _uid, _location, _owner);
        return true;
    }

    function changeObjectLocation(bytes32 _uid, bytes32 _newLocation) public returns(bool success) {
        require(isObject(_uid));
        objectStructs[_uid].location = _newLocation;
        LogChangeObjectLocation(msg.sender, _uid, _newLocation);
        return true;
    }

    function changeObjectOwner(bytes32 _uid, address _newOwner) public returns(bool success) {
        require(isObject(_uid));
        objectStructs[_uid].owner = _newOwner;
        LogChangeObjectOwner(msg.sender, _uid, _newOwner);
        return true;
    }

}

Hope it helps.

3
  • For sure, it helps too much. Thanks. Just I had a question: "when" do we need to change the object owner address (with function changeObjectOwner) ? in fact, in which situation ? Could you please mention an example ? Thanks. Meanwhile, I add some additional information in my question.
    – Questioner
    May 4, 2018 at 8:49
  • I would have also another question: If we want to generalize "bytes32 location;" in struct, such that its name would be "state" which includes several sub_state ex. "location" , "price" , "sold" etc, How we can define such a "state" in our struct ? Thanks again.
    – Questioner
    May 4, 2018 at 9:23
  • I explained my question in more details here: ethereum.stackexchange.com/questions/47529/… Thank you for your help.
    – Questioner
    May 4, 2018 at 9:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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