13

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);}
}
  • 4
    modify all input parameter "string" to "string memory". problem solved... but I don't know the reason – TLHBM Nov 23 '18 at 11:02
  • 3
    changing solidity compiler older version, problem alo solved – TLHBM Nov 23 '18 at 11:05
  • 2
    Thank you a lot, changing to "string memory" worked – Lonwabo Zaula Nov 23 '18 at 11:39
19

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.

  • 2
    When they mention array, it is assumed for bytes & string too. Although it can be mentioned externally for convenience. – Aniket Nov 26 '18 at 7:54
  • @A.K. Good point. Being explicit would avoid situations like this haha – alsco77 Nov 26 '18 at 8:00
  • Yes, exactly... – Aniket Nov 26 '18 at 8:02
16

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

4

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;
    }
}
2

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....

  • 1
    It's not necessary to add memory to uints, bools, etc. It's only required for struct, array and mapping – David Mihal Jan 23 at 5:28
1

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

  • 1
    It is better to use version 0.5.0 and use "string memory" instead of just "String" – Yogesh - EtherAuthority.io Nov 27 '18 at 14:29
  • 1
    I agree with you – Mahesh Rajput Nov 28 '18 at 4:36
  • They would also need to change the first line from pragma solidity^0.5.0; to pragma solidity^0.4.25; – David Mihal Jan 23 at 5:30
1
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;
    }
}
0

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

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.