Understanding Gas Consumption

Hi Daniele,

In the video, Filip’s remix did not show red error code like picture shown below, So i wonder why.

Cheers,

image

Hi @M.K

It is showing an error because you are using the push method in a memory array and that is not possibile.
Push is only available in storage.

Cheers,
Dani

1 Like

image

Hi Daniele,

What does this error message mean ?
I followed Filip’s code but got an error message.

Cheers,

Or did i follow the code wrongly ?

my code :

pragma solidity 0.7.5; 

contract simplearray { 
    
    struct entityStruct { 
     address entityAddress ;
     uint entityData;
        
    }
    
entityStruct []public entityStructs;

function newEntity ( address _entityAddress, uint _entityData) public returns (uint) {
entityStruct memory _newEntity;             
// declare a name of struct  

_newEntity.entityAddress = _entityAddress ; 
// let user input address to store in memory

_newEntity.entityData = _entityData ;      
// let user input data to store in memory 

return entityStructs.push(_newEntity)-1;    
// locate the id of the array entityStructs, -1 is because array starts from 0. 

}

function getEntityCount ()public returns (uint) {
    return entityStructs.length; 
    
}

    
}
1 Like

Hi guys and @filip, i’m doing a side project trying out some techniques from within this course and others and I was hoping someone could guide me in the right direction.

I’m looking at creating a function which will add a ranking system for items within an auction site based on likes, dislikes and comments.

I’ve learned so much from the academy so far and feel i’ve come a long way since I first started but i’m struggling on this. If anyone could advise any techniques or guide me to learning material on how to do this it would be so much appreciated.

Hey @M.K

This error has been fixed in Filip repository couple of months ago :slight_smile:
Take a look at his repo for the updated version.

Cheers,
Dani

Hi,

I think the codes suddenly became very difficult to understand from mapping_w_index.sol
I used to think that a beginner can learn how to make smart contract because this is a structured course. But starting from Storage Design Patterns part , it has became exponentially difficult for beginners. I was able to follow until this part of the course.

Can someone can help me a little on below code ?

pragma solidity 0.8.0;

contract MappedStructsWithIndex {

  struct EntityStruct {
    uint entityData;
    bool isEntity;
  }

  mapping(address => EntityStruct) public entityStructs;
  address[] public entityList;
  
  function newEntity(address entityAddress, uint entityData) public returns(uint rowNumber) {
    if(isEntity(entityAddress)) revert();
    entityStructs[entityAddress].entityData = entityData;
    entityStructs[entityAddress].isEntity = true;
    return entityList.push(entityAddress) - 1;
  }

What does this code mean ?
if(isEntity(entityAddress)) revert();

Hi Dan,

Can you explain the below function for me too?

function addEntity(uint _data) public returns(bool success) {
EntityMap[msg.sender].data = _data;
EntityMap[msg.sender]._address = msg.sender;
return true;
}

  1. what is returns (bool success )
  2. what does it mean to return true ?
  3. what does < EntityMap[msg.sender]._address = msg.sender;> do ?

Thanks

I copied and pasted the below code from Filip’s simple_array.sol

I deployed it and it showed below error
Or Is the contract just for explaining the concept or is actually able to be deployed ?

image

Im writng this small post just to try summarise the main takeaways of this section in a concise mannor and also for my own learning to make sure i understand and remember the infromation. So the two most important thing sin this section were obviously data storage and gas costs etc. So recall the two main types of of data storage

Storage:
Global permenant storage in our contract

Memory:
local tempoary storage (usually used in functions)

these two types of storage have different effects especially in terms of gas cost when we assign data between variables of different storage locations.We can assign by copy and assign by reference.

Assign by copy:
Copy the data from one variable into another. In solidity the way to know if we are making a variable copy is

//Storage -> memory = COPY
//Memory -> storage = COPY

Assign by reference:
Assign variables by reference is slightly different. This is when we assign data like a pointer to something. modifying a pointer array that points at a our storage array will also change the storage array. The pointer array just serves as an extra reference to our original storage array which can be useful. Another way to think about pointers is that they point to a memory address or location in our computers memory. we recognize a copy by reference in solidity by:

//Memory -> memory = REFRANCE
//storage -> local storage = REFERANCE

Using these cheat sheets if you will is a good way to know how we are storing our variables and it is good to write these down at first if you cant remember.

PUBLIC vs EXTERNAL:
The other important topic of this section is the difference between public and external functions in terms of gas cost and to know when to use each. (Dont confuse external/ public functions with public/external contracts)

external functions are much cheaper than public functions. With external functions we can use the calldata data location which is cheaper than memory storage. calldata is where data from external calls to functions is stored it is a special data location that contains the function arguments, only available for external function call parameters

calldata does not write our arguments to memory. They are only read from the function call. However this also means that we can not modify our input as its read only. So this is something to consider

if our function does not write, read or modify a state variable (a var declared outside function). then we can have it as a pure function. Pure functions do not cost anything so should be used when necessary

public contract on the other hand cost much more gas and are expensive because public contracts require us to have our input arguments in memory which is more expensive that calldata. Since our arguments are in memory though we do have the ability to read write and modify so it comes down to what our needs are for our specific application

writing data to memory is still expensive but not as expensive as storage. view functions are functions that do not modify a state variable they only read it. having functions as view or pure are in a lot of cases free to execute. They can be run without making a transaction on the block chain which can be incredibly useful in certain scenarios.

So in summary the main difference between public and external functions is that we can call public functions from anywhere in our contacts both internally and externally. However external contracts can only be called from outside our contract

3 Likes

Hey guys,

I was playing around with code on coyping and referencing a bit and ran into a snag. Here’s the code:

uint[] storageArray;
 
function f(uint[] memory memoryArray) public returns(uint[] memory) {
    storageArray = memoryArray;
    uint[] storage pointerArray = storageArray;
    pointerArray.push(7);
    memoryArray = storageArray;
    return memoryArray;
}

function get() public view returns(uint[] memory) {
    return storageArray;
}

Both functions don’t seem to work. The first one throws an error and the second doesn’t even seem to register (returns an empty array). I tried initialising function f() with “1,2,3,4” and thus expected the return value to be “1,2,3,4,7”. What am I missing here? (there are no compiling errors)

Take care
Em

Hi,

Did I understand it correctly that “referencing” is cheaper than “copying”?

Greetz
Em

1 Like

Hey @Emmerich

Can you please explain what was your goal with this function?

function f(uint[] memory memoryArray) public returns(uint[] memory) {
    storageArray = memoryArray;
    uint[] storage pointerArray = storageArray;
    pointerArray.push(7);
    memoryArray = storageArray;
    return memoryArray;
}

Regarding the get function, that one is correct.
It does return an empty array because the array itself is empty.

pragma solidity 0.8.0;

contract TestArray {
    
    uint [] thisIsAnArray;
    
    function set (uint _x, uint _y) public {
            thisIsAnArray.push(_x);
            thisIsAnArray.push(_y);
    }
    
    function get () public view returns (uint [] memory) {
        return thisIsAnArray;
    }
}

Cheers,
Dani

Hi Dani,

The point of the function is to test what I’ve just learnt by passing data from one array to the other and then printing out the final result. I’ve written the code down again with comments to show you what I think should happen.

function f(uint[] memory memoryArray) public returns(uint[] memory) {
    storageArray = memoryArray;    //whatever I initialised memoryArray with, when I called the function, is copied into storageArray (let's say I initialised it with [1,2,3])
    uint[] storage pointerArray = storageArray;     //pointerArray is created and now points to storageArray
    pointerArray.push(7);         //pointerArray adds an element, which means the same element is added to storageArray (so storageArray should be [1,2,3,7])
    memoryArray = storageArray;   //now memoryArray is set as a copy of storageArray and should therefore also be [1,2,3,7]
    return memoryArray;           //Here I would like to return the values of memoryArray, but it doesn't. Why?
}

Regards
Emmerich

Hey @Emmerich

Uhm it seems working correctly

pragma solidity 0.8.0;

contract TestArray {
    
    uint [] public thisIsAnArray;
    
    function f(uint[] memory memoryArray) public returns(uint[] memory) {
        thisIsAnArray = memoryArray;    //whatever I initialised memoryArray with, when I called the function, is copied into storageArray (let's say I initialised it with [1,2,3])
        uint[] storage pointerArray = thisIsAnArray;  
        pointerArray.push(7); 
        memoryArray = pointerArray;
        return memoryArray;
    }
}

Screenshot 2021-05-07 at 10.40.49

Dear Dani,

You’re right it does. I stand corrected. I don’t know what I did wrong.

1 Like

Hi @M.K, I have reached that point of the SC 201 course yet. However, I can answer two of the three questions. In the referenced code you have a public function called ‘addEntity’ that returns a boolean data type labeled ‘success’. Boolean data types have one of two possible values (true or false) intended to represent the truth in logic. So after successful completion of the lines of code within this function, it should return a boolean value of ‘true’.

hi all,
I’ve created the same contract with the same arguments as Filip in Public vs External and I had much bigger execution gas cost. Between the public and external function was little differents.

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.7.5;
pragma abicoder v2;


contract SaveGas {
    
    function testExternal(uint[10] calldata numbers) external returns (uint) {
        return numbers[0];
    }
    function testPublic(uint[10] memory numbers) public returns (uint) {
        return numbers[0];
    }    

}

testExternal execution cost was 23036gas.

testPublic execution cost was 25691gas.

Why it was like that?

Best wishes,
Kacper Pajak

Fantastic breakdown! Tank you :star_struck:

1 Like

Hi @filip, thank you for the clarifications.
While watching the View & Pure functions lesson you at some point say “if you don’t want to modify the state, why should you pay gas?” and I can’t figure out what do you mean.
Since gas is used to utilize people’s cpus inside the EVM sandbox, it would make sense to pay gas for the act of using the cpu itself, which is involved in reading operation too.
To not ask for gas makes me question “whose cpu is busy for free?”.
With this in mind I just wrote a simple function in remix

function testDdos() external pure
    {
      while(true){}
    }

and with my great surprise it just literally crashed the IDE.
I’m quite sure this isn’t how ethereum actually works, so I would ask you some clarification about this topic. More specific:

  • who actually (in reality) run the code when a external/view function is called from the outside?
  • what does prevent to just code cpu intensive calculations inside a external/view functions and query them for free from the outside?
  • if this is a surface that can be attacked, how is ethereum protected from ddos attacks involving this kind of logic? (delegate cpu intensive jobs to the network and just get the result back)

Thank you for your time and your lessons :slightly_smiling_face: