7

I am testing out solidity in remix ide using simple contracts. This is the contract that I wrote:

 contract mortal {

address owner;

function mortal() {
    owner = msg.sender;
}

function kill(){
    if(msg.sender == owner){
        selfdestruct(owner);
    }
   }
}

contract Hello is mortal
{

string public message;

function Hello(){
    message = 'This is the initial Message';
    }

function getMessage() public constant returns(string){
    return message;
    }

function setNewMessage(string newMessage) public payable {
    message = newMessage;   
    }
} 

On looking at details I am getting infinite gas estimates for each of these functions.

{
"Creation": {
    "codeDepositCost": "243200",
    "executionCost": "infinite",
    "totalCost": "infinite"
},
"External": {
    "getMessage()": "infinite",
    "kill()": "30636",
    "message()": "infinite",
    "setNewMessage(string)": "infinite"
}
}

Please elaborate why am I getting infinite gasEstimates for these functions and how can I avoid this mistake ?

Ahsan Jamal
  • 173
  • 1
  • 1
  • 6

3 Answers3

8

I suspect this is because the cost of those functions is indeed unbounded. Strings can be of any length, so setNewMessage() needs to store an unbounded amount of data, and getMessage() needs to read an unbounded amount of data.

If you want to avoid that warning, you'd have to use a data type with a fixed upper bound on its size.

user19510
  • 27,999
  • 2
  • 30
  • 48
3

The contract compiles just fine:

pragma solidity ^0.4.15;

contract mortal {
    address owner;

    function mortal() public {
        owner = msg.sender;
    }

    function kill() public {
        if (msg.sender == owner) {
            selfdestruct(owner);
        }
    }
}

contract Hello is mortal {
    string public message;

    function Hello() public {
        message = 'This is the initial Message';
    }

    function getMessage() public constant returns(string) {
        return message;
    }

    function setNewMessage(string newMessage) public payable {
        message = newMessage;   
    }
} 

but then the warnings appear...

enter image description here

but it submits/confirms on Ropsten just fine..

enter image description here

and the method calls work fine too..

enter image description here

This may just be a bug in the compiler's static analysis.

Shomari
  • 625
  • 4
  • 17
  • I see it is executing, it maybe a bug in remix as you pointed out. Thankyou :) – Ahsan Jamal Dec 29 '17 at 13:09
  • 2
    The warning is just that. It doesn't mean that the contract won't work; it just means that the gas usage is potentially unbounded. I think that the warning is correct. – user19510 Dec 29 '17 at 14:15
  • @smarx, yes I see your point, as the string type appears to be unbound – Shomari Jan 01 '18 at 01:24
  • @smarx So if string is unbounded, what is the best alternative for storing string data ? – Ahsan Jamal Jan 01 '18 at 07:47
  • I'm not sure I understand the question. What's wrong with just using string? If you want to limit the length of the string users can supply, you could check the length. (E.g. require(newMessage.length <= 20);) – user19510 Jan 01 '18 at 10:56
  • 1
    @AhsanJamal You can use bytes32 or any number of bytes in place of string. Just make sure that the bytes can support necessary information. You can then easily convert the bytes to string easily. https://ethereum.stackexchange.com/questions/2519/how-to-convert-a-bytes32-to-string – Bhoomtawath Plinsut Oct 07 '18 at 10:43
1

It is because you are using string which does not has a particular size i.e., it is unbound data type. You can use bytes32 in place of string to limit the cost of gas on execution code because solidity considers it a 32 bit literal.

Yash Attal
  • 11
  • 4
  • That said, is it true people should avoid using string at any cost, since it will always return infinite gas usage. – Maxareo Mar 25 '21 at 03:19