0

Suppose I have a product with a specific id for sale(so I am the owner) and someone wants to buy the product from me. When he pays the price he will become the new owner of that product.

How can I record multiple owners for one specific asset?

I want to have a result like this (get all the addresses with the id)

56 => [0xcc6Bfe0C579416A6cC8532e984af0e6a, 0xcc6Bfe0C579416A12C8532e984th0e6a,...]

This is the way I did it which is not working as it should.

I summarized it to make it easier to understand.

Thanks in advance.

contract transfer{

  mapping(uint => address[]) public owners;

  function createAsset(string name, uint price) public
  {
      uint id = getRandom(); //I use a random generator function for id

      Asset memory newAsset = Asset(name, price); //struct to create a new product

      owners[id].push(msg.sender);

    }

  function transferProduct(uint id) public payable {
    owners[id].push(address((msg.sender)));

  }
}
  • 1
    "which is not working as it should" Please be more specific. Does the code not compile? Do you get an error when you try to use it? Does it do something different from what you expected? (If so, what?) – smarx Jun 1 at 4:28
  • You're right. I might say it bad. I mean it does not the job. I have this code to map id to an array of address but only the last address is recorded not all the previous ones. – Prstoo Jun 1 at 6:14
  • "only the last address is recorded" <-- That's not true. Your existing code records all the addresses of accounts that call createAsset or transferProduct. – smarx Jun 1 at 6:26
0

I want to answer it with another answer, my previous answer is half correct, because if you want to save the array you must use .push with +size, your sample code is wrong. below is my sample code, you can try it and change it yourself:

pragma solidity >=0.4.22 <0.6.0;
contract example{
    uint lastcount; //define data input couter on global
    struct fileDetail{ //define struct for asset on global
        string name;
        uint price;
    }

    mapping (uint => address[]) fileOwner; //define mapping for fileOwner on id
    mapping (uint => fileDetail) fileDetails; //define mapping for file asset detail on id
    uint[] saveId; //save all generated id here

    function getFileDetails(uint id) view public returns(string memory, uint){ //this function for return struct fileDetail
        fileDetail storage up = fileDetails[id]; //read data from id in fileDetails
        return(up.name, up.price); //get data from fileDetails and return as struct
    }

    function getAllSavedID() view public returns(uint[] memory){ //this function for get all saved id and return list of uint[] or it will appear all saved id
        return saveId; //get data saveId and return as uint[]
    }

    function getOwners(uint id) view public returns(address[] memory){ //this function for return list of address[] or it will appear all owner
        return fileOwner[id]; //get data fileOwner and return as address[]
    }

    function getOwnersSize(uint id) view public returns(uint){ //this function will get address[] size from mapping (this is a counter for owner)
        return fileOwner[id].length; //get fileOwner[id] length for address[]
    }

    function createAsset(string memory name, uint price) public{
        uint id = now + lastcount;  //now will generate some number based time and plus latest count data input

        fileDetail storage up = fileDetails[id]; //call struct fileDetail, and used for save data to fileDetails with based id
        up.name = name; //set name for item id based
        up.price = price; //set price for item id based

        saveId.push(id) -1; // save id to saveId, it will use for view all saved id

        fileOwner[id].push(msg.sender); //save first owner for id

        lastcount = lastcount + 1; //count latest data input for next input
    }

    function addNewOwner(uint id) public{
        uint size = getOwnersSize(id); //call function for count owners
        fileOwner[id].push(msg.sender)+size; //add new array for address[], you need define size because it is important
    }
}

and below is a screenshot of the result you want :

enter image description here

-1

Just at + in your transferProduct(), but you need some counter for your mapping, because length not work on mapping. I think code will like this :

contract transfer{

  uint lenghtcounter;
  mapping(uint => address[]) public owners;

  function createAsset(string name, uint price) public
  {
      uint id = getRandom(); //I use a random generator function for id

      Asset memory newAsset = Asset(name, price); //struct to create a new product

      owners[id].push(msg.sender);
    }

  function transferProduct(uint id) public payable {
    uint temp = lenghtcounter + 1;
    owners[id].push(msg.sender)+temp ;
    lenghtcounter = temp;
  }
}
-1

Fistly, how did you implement that getRandom(). Every code running under EVM needs to be fully deterministic it means randomness is not allowed. Besides that your code looks correct.

The only assumption I can make for this error to happen is that when you are calling getRandom() returns a uint (uint256), which is a BigInteger, and then when you can transferProduct() you are not passing a uint32 as argument which is automatically converted and it does not hit the same index. Therefore I would recommend you to do the following:

contract transfer{

  uint nextItemId;
  mapping(uint32 => address[]) public owners;

  function createAsset(string name, uint256 price) public
  {
      Asset memory newAsset = Asset(name, price); //struct to create a new product
      owners[nextItemId].push(msg.sender);
      nextItemId = nextItemId + 1;
    }

  function transferProduct(uint32 id) public payable {
    owners[id].push(address((msg.sender)));

  }
}

Remember that in Solidity EVM execution txs are being executed iteratively.

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.