Solidity Gas – How to Call a Constant Function Without Spending Gas in Transactions

gassolidity

I have a sorted linked list that contains around 1000 items. When I receive a new item my goal is to push the item to the list keeping the sorted order. So if I receive very small value, I am required to iterate all the list to find the tail of the list.

Constant function's goal is to return the index location for transaction function to push into.

Iteration(iterateListToFindPushIndex()) might look like this:

struct Interval { 
  uint32 num;  //contained value.
  uint32 next; //points to next node on the linkedlist.
}

prevNode     = self.list[self.head]; //head of the list, largest value.
currentNode  = self.list[prevNode.next];
while( true ) {
  if( s > currentNode.num ){ 
    //self.list.push(Interval( { num: s, next: prevNode.next }) );
    //prevNode.next = uint32(self.list.length - 1);
    return prevNode.next; 
//returned indexed would be use in transaction function to insert intem into the correct location.
  }
  prevNode         = currentNode;
  currentNode      = self.list[currentNode.next];
}

As we know when we call a constant function, it does not cost any gas and its free to use. So when I find the index location via a constant function, it won't cost me any gas.

function iterateListToFindPushIndex() constant returns(uint index){}
function func(intervalNode storage self) { 
  index = iterateListToFindPushIndex();
  self.list.push(Interval( { num: s, next: index }) )
}

Inside a transaction function, when I iterate through my list even though I don't change any memory storage, it cost me additional gas.

So is it possible to call a constant function without spending any gas inside a transaction function.

Thank you for your valuable time and help.

Best Answer

Calling a constant function inside a transaction costs just as much as calling a non-constant function inside a transaction. What constant means is that since it doesn't alter the state, your local node can run it and tell you the result without needing a transaction. This doesn't cost gas because only your node has to run the calculation.

You may be able to use this to save gas in a transaction by first running the constant function from your JavaScript code to get a result, then passing that result as a parameter to the transaction. However, unless your contract trusts the person sending it, you still need to verify it inside the transaction. This may still be useful: If you have a sorted list and you want to know where to put an item, it may be useful to check it on the client side and find the index x, pass in the index x as a transaction parameter, then let the smart contract code in the transaction verify that the item at x-1 comes before what you're adding, and the item at x+1 comes after it.

One pitfall is that the data may change between reading a result and sending a call containing it to the blockchain in a transaction, in which case your transaction will fail and you will have to send it again.

Related Topic