TypeError: Data location must be "memory" for parameter in function, but none was given

  • I have created the contract below using the online IDE Remix. the smart contract was fine until late last night when i got the following error for all functions(targeting the string data types especially):

    • TypeError: Data location must be "memory" for parameter in function, but none was given

    . I have no idea why this happened and i have not found any sufficient information on how i can fix it and was hoping you can help me. Thank you in Advance.

    pragma solidity^0.5.0;
    
    contract project3{
    
    address owner;
    
    string location; uint quantity; string product; uint payment; 
    
    struct Users{
    string companyName; string role; string country; string city; uint phoneNo;
    string physicalAddress; 
    bool certified;}
    
    struct Product{
    address producer;    
    string name; uint quantity; string tag;
    string proddescription;}
    
    struct AssetTransfer{
    string shipmentlocation; string asset; address sender; 
    address receiver;
    string trackingNo;
    uint quantity;}
    
    constructor (uint _tokens)public{
    owner=msg.sender;
    accbalance[owner]=_tokens;    
    }
    
    event Message(string message);
    event Shipped(string _message, string trackingno, address _sender,string 
    location);
    
    modifier only_admin{
    require(msg.sender==owner);
    _;}
    
    mapping (string=>Product)products;
    
    mapping(address=>Users)users;
    
    mapping (address=>uint) accbalance;
    
    mapping(string=>AssetTransfer)assetTransfer;
    
    address[] private stakeholders;
    
    string[]private goods;
    
    function addUsers(address _address, string _companyName,string _role, string 
    _country,
    string _city, uint _phoneNo, string _physicalAddress)only_admin public 
    returns(bool) {
    
    var user=users[_address];
    //a user address can be added only once
    if(bytes(user.companyName).length==0 && bytes(_companyName).length!=0){
    user.companyName=_companyName;
    user.role=_role;
    user.country=_country;
    user.city=_city;
    user.phoneNo=_phoneNo;
    user.physicalAddress=_physicalAddress;
    stakeholders.push(_address);
    emit Message('user added succesfully');
    return true;}
    else{
    emit Message('user not added, enter different details');
    return false;}
    }
    
    function getUser(address _address)public view 
    returns(string,string,string,string,uint,string){
    return(users[_address].companyName,
    users[_address].role,users[_address].country,
    users[_address].city,users[_address].phoneNo,
    users[_address].physicalAddress);}
    
    function addProduct(address _address,string _name,uint _quantity,string 
    _tag,string _description)public returns(bool){
    var prod= products[_tag];
    if(bytes(prod.tag).length==0 && bytes(_tag).length!=0){
    prod.producer=_address;    
    prod.name=_name;
    prod.quantity=_quantity;
    prod.tag=_tag;
    prod.proddescription=_description;
    goods.push(_tag);
    emit Message('Product added succesfully');
    return true;}
    else{
    emit Message('Product cannot be added. duplicate serial number used');
    return false;    
    }}
    
    function getProduct(string _tag)public view returns 
    (address,string,uint,string,string){
    return(products[_tag].producer,products[_tag].name,
    products[_tag].quantity,products[_tag].tag,products[_tag].proddescription);}    
    
    function makepayment(address _from, address _to, uint _amount)public 
    returns(bool){
    if(_amount<=0 && accbalance[_from]<_amount){
    emit Message('cannot make payment,insufficient funds');    
    return false;}
    accbalance[_from]-=_amount; accbalance[_to]+=_amount;
    emit Message('payment made succesuccesfully');
    return true;}
    
    function sendShipment(string _asset,string trackingNo, string _destination,
    uint _quantity,address _reciever, address _sender)public returns(bool){
    assetTransfer[trackingNo].asset=_asset;
    assetTransfer[trackingNo].shipmentlocation=_destination;
    assetTransfer[trackingNo].trackingNo=trackingNo;
    assetTransfer[trackingNo].quantity=_quantity;
    assetTransfer[trackingNo].sender=_sender;
    assetTransfer[trackingNo].receiver=_reciever;
    emit Shipped("shipment sent", trackingNo, _sender, _destination);
    return true;}
    
    function checkBalance(address _accountHolder)public view returns(uint){
    return accbalance[_accountHolder];}
    
    function setconditions(string _location,uint _quantity,uint _payment,string 
    _asset,address _seller)public{
    location=_location; quantity=_quantity; payment=_payment; product=_asset;
    _seller=msg.sender; 
    emit Message('conditions are set'); }
    
    function getshipment(string _location,uint _quantity,string _asset,string 
    trackingNo)public returns(bool){
    if((assetTransfer[trackingNo].quantity)==_quantity && 
    keccak256(abi.encodePacked(assetTransfer[trackingNo].asset))== 
    keccak256(abi.encodePacked(_asset))){
    emit Shipped('Shipment recieved',trackingNo,msg.sender,_location);    
    if (keccak256(abi.encodePacked(location))== 
    keccak256(abi.encodePacked(_location))){
    makepayment(assetTransfer[trackingNo].receiver,
    assetTransfer[trackingNo].sender,payment);}
    else{
    emit Message('Payment not made');}    
    return true;}
    else{
    emit Message('wrong location/quantity/item');    
    return false;}
    }
    function showProvenance(string _trackingNo)public view 
    returns(string,string, address,address,string){
    return(assetTransfer[_trackingNo].asset,
    assetTransfer[_trackingNo].trackingNo, 
    assetTransfer[_trackingNo].sender,
    assetTransfer[_trackingNo].receiver,
    assetTransfer[_trackingNo].shipmentlocation);}
    }
    

    modify all input parameter "string" to "string memory". problem solved... but I don't know the reason

    changing solidity compiler older version, problem alo solved

    Thank you a lot, changing to "string memory" worked

  • From this:

    pragma solidity^0.5.0;
    
    contract Contract {
        string public name;
    
        function Contracts(string passedName) public {
            name = passedName;
        }
    
        function setName(string newName) public {
            name = newName;
    
        }
    
    }
    

    To This:

    pragma solidity^0.5.0;
    
    contract Contract {
        string public name;
    
        function Contracts(string memory passedName) public {
            name = passedName;
        }
    
        function setName(string memory newName) public {
            name = newName;
    
        }
    
    }
    

    Make sure to use "" to wrap text. Using '' will give you:

    transact to Contract.Contracts errored: Error encoding arguments: SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data

  • It states in the v0.5 breaking changes list that:

    Explicit data location for all variables of struct, array or mapping types is now mandatory. This is also applied to function parameters and return variables.

    The docs are implicit in stating that strings and bytes are included - as they are array implementations, rather than an error in the compiler.

    When they mention `array`, it is assumed for `bytes` & `string` too. Although it can be mentioned externally for convenience.

    @A.K. Good point. Being explicit would avoid situations like this haha

    Yes, exactly...

  • I know you have got the right answer, however just posting it with the code snippet that execute fine, after adding memory keyword - with solidity version 0.5.1: It is both setter and getter

    pragma solidity '0.5.1';
    
    contract MyFirstContract {
        uint productid;
        string public productname;
    
        function setname (string memory name1) public {
            productname = name1;
        }
    
        function getname () public view returns (string memory) {
            return productname;
        }
    }
    
  • pragma solidity '0.5.11';
    
    contract Hello {
    
        string public productname='Hello World';
    
    
        function setname (string memory name1) public {
            productname = name1;
        }
    
        function getname () public view returns (string memory) {
            return productname;
        }
    }
    
  • You need to make the return parameters explicitly memory:

    function addUsers(address _address, string _companyName, string _role,
    string _country, string _city, uint _phoneNo,
    string _physicalAddress) only_admin public returns(bool) {
    

    becomes:

    function addUsers(address _address, string _companyName, string _role,
    string _country, string _city, uint _phoneNo,
    string _physicalAddress) only_admin public returns(bool memory) {
    

    and:

    function getUser(address _address)public view 
    returns(string,string,string,string,uint,string){
    

    becomes:

    function getUser(address _address)public view 
    returns(string memory,string memory,string memory,string memory,
    uint memory,string memory){
    

    and so on....

    It's not necessary to add `memory` to uints, bools, etc. It's only required for struct, array and mapping

  • You can solve errors by selecting 0.4.25+commit.59dbf8f1.Emscripten.clang compiler version in remix IDE.

    It is better to use version 0.5.0 and use "string memory" instead of just "String"

    I agree with you

    They would also need to change the first line from `pragma solidity^0.5.0;` to `pragma solidity^0.4.25; `

  • It's turned the values from reference to value I believe. Just have to specify to use the local memory I think.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM

Tags used