Assignment - Storage Design

My contracts
Array

pragma solidity 0.7.5;
pragma abicoder v2;

contract Arraycost {
    
    address private owner; 
    uint x;
    
    constructor() {
        owner = msg.sender;
    }
    
    struct Entity{
        uint data;
        address _address;
    }
    
    Entity[] private entity;
    
    function addEntity() public  {
        x += 1;
        Entity memory newEntity;
        newEntity.data = x+1;
        newEntity._address = msg.sender;
        entity.push(newEntity);
    }
    
    function updateEntity(uint _number, uint _newData) public {
        entity[_number].data = _newData;
    }
    
    function viewEntity(uint _number) public view returns (Entity memory){
        return entity[_number];
    }
}

Mapping

pragma solidity 0.7.5;
pragma abicoder v2;

contract Mapcost {
    
    address private owner; 
    uint x;
    
    constructor() {
        owner = msg.sender;
    }
    
    struct Entity{
        uint data;
        address _address;
    }
    
    mapping(uint => Entity) entity;
    
    function addEntity() public  {
        x += 1;
        entity[x].data += x+1;
        entity[x]._address = msg.sender;
        
    }
    function updateEntity(uint _number, uint _newData) public {
        entity[_number].data = _newData;
    }
    
    function viewEntity(uint _number) public view returns (Entity memory){
        return entity[_number];
    }
}

When executing the addEntity function, which design consumes the most gas (execution cost)? Is it a significant difference? Why/why not?

Mapping consume fewer execution cost. In my case I have more lines of code for this function in the array contract and I suppose (i’m not sure) when i push a new data into the array we need some kind of extra code. (more code to execute more expensive)
Array
First Addentity
image
The others Addentity
image

Mapping
First Addentity
image
The others Addentity
image

Add 5 Entities into storage using the addEntity function and 5 different addresses. Then update the data of the fifth address you used. Do this for both contracts and take note of the gas consumption (execution cost). Which solution consumes more gas and why?
Array consume more, if you have more data more consume because the program need to look every data until find the result

Array
image

Mapping
image

1 Like

My Solution

Array Storage:

  • Deployment cost = 275918 gas

  • addEntity() cost = 62607 gas

  • updateEntity() cost = 42405 gas

Mapping Storage:

  • Deployment cost = 197438 gas

  • addEntity() cost = 208280 gas

  • updateEntity() cost = 28585 gas

Conclusion:

The arrayGasTest contract takes 1.45x the amount of the mappingGasTest contract.

array_assign.sol:

pragma solidity 0.8.3;

contract arrayGasTest {
    struct Entity {
        uint data;
        address _address;
    }
    
    Entity[] public entityStructs;
    
    function addEntity(uint data) public returns(bool success) {
        Entity memory addEntity;
        addEntity.data = data;
        addEntity._address = msg.sender;
        entityStructs.push(addEntity);
        return true;
    }
    
    function updateEntity(uint _index, uint _data) public returns(bool success) {
        require(entityStructs[_index]._address == msg.sender, "Only entity owner can access");
        
        entityStructs[_index].data = _data;
        return true;
    }
}```

**mapping_assign.sol:**

pragma solidity 0.8.3;

contract mappingGasTest {
struct Entity {
uint data;
address _address;
}

mapping(address => Entity) entityMap;

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

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

function getEntityMap() public view returns(uint, address){
    return(entityMap[msg.sender].data, entityMap[msg.sender]._address);
}

}```

1 Like

execution cost per data type:
mapping: add 41708
updates 5493

arrays: add 62544 (1st entry) / 47544 (2-5 entries)
updates 20920

When adding new entities to the data structures, the gas costs are roughly similar, though mapping is a little cheaper than pushing to an array.

The update costs are quite a bit different however with mapping being significantly cheaper. This would be because very little computational power is used when directly accessing a mapping. To update in the array a lot more computation is required to cycle through the array to find the correct entry.

pragma solidity 0.8.0;

contract mappingAssignment {
    
    struct Entity{
        uint data;
        address _address;
    }
    
    mapping(address => Entity) entityMap;
    
    function addEntity(uint _data, address __address) public {
        Entity memory newEntity = Entity(_data, __address);
        entityMap[msg.sender] = newEntity;
    }
    
    function updateEntity(uint _data) public {
        entityMap[msg.sender].data = _data;
    }
    
}

contract ArrayAssignment {
    
    struct Entity{
        uint data;
        address _address;
    }
    
    Entity[] entityArray;
    
    function addEntity(uint _data, address __address) public {
        Entity memory newEntity = Entity(_data, __address);
        entityArray.push(newEntity);
    }
    
    function updateEntity(uint _data) public {
        for (uint i = 0; i < entityArray.length; i++) {
            if (entityArray[i]._address == msg.sender) {
                entityArray[i].data = _data;
                break;
            }
        }
    }
}
1 Like

My two Solutions:

  1. Mapping:
pragma solidity 0.7.5;
pragma abicoder v2;
contract Mapping {
    
    struct Entity {
        uint data;
        address _address;
    }
    mapping(address => Entity) public entityMapping;
    
    function addEntity(uint _data, address Address) public returns(bool complete){
        entityMapping[msg.sender].data = _data;
        entityMapping[msg.sender]._address = Address;
        return true;
    }
    
    function updateEntity(uint entityData, address entityAddress) public returns(bool complete){
        entityMapping[entityAddress].data = entityData;
        return true;
    }
}
  1. Array:
pragma solidity 0.7.5;
pragma abicoder v2;
contract Array {
    
    struct Entity {
        uint data;
        address _address;
    }
    
    Entity[] public entityArray;
    
    function addEntity( uint _data, address Address) public returns(bool complete){
        Entity memory newEntity;
        newEntity.data = _data;
        newEntity._address = Address;
        entityArray.push(newEntity);
        return true;
    }
    
    function updateEntity( uint index, uint Data) public returns(bool complete){
        entityArray[index].data = Data;
        return true;
        
    }
}

Question 1:
addEntity()
Mapping gas cost = 41,923
Array gas cost = 62,852
40% difference in consumption

The Array solution costs more gas because we have to create a new array by copying the old (empty) array an assigning it a new name in memory, before we are able to push() a new array.
(if that makes sense, i could be wrong).

Question 2:
updateEntity()
Mapping gas cost = 5,918
Array gas cost = 6,692
12% difference in consumption

Using the Array to update the Entity is more costly because you have to iterate through the array to find the 5th value (at index 4) which requires more computing power to perform and subsequently more gas consumed. The mapping solution is able to directly point to the 5th value which is quicker and cheaper.

2 Likes

The first contract is using an array

pragma solidity 0.8.0;

contract StorageArray {
    struct EntityStruct{
        uint data;
        address _address;
    }
    
    EntityStruct[] public entityStructs;
    
    // addEntity(). Creates a new entity for msg.sender and adds it to the mapping/array.
    // updateEntity(). Updates the data in a saved entity for msg.sender
    
    function addEntity(uint _data) public {
        
        EntityStruct memory newEntity;
        newEntity._address = msg.sender;
        newEntity.data     = _data;
        entityStructs.push(newEntity);
    }
    
    function updateEntity(uint _data) public{
        for (uint i = 0; i < entityStructs.length; i++ ){
            if (entityStructs[i]._address == msg.sender){
                entityStructs[i].data = _data;
            }
        }
    }
   
}

The second contract is using mapping

pragma solidity 0.8.0;

contract StorageMapping {
    struct EntityStruct{
        uint data;
        address _address;
    }
    
    mapping (address => EntityStruct) public entityStructs;
    
    // addEntity(). Creates a new entity for msg.sender and adds it to the mapping/array.
    // updateEntity(). Updates the data in a saved entity for msg.sender
    
    function addEntity(uint _data) public {
        entityStructs[msg.sender] = EntityStruct(_data, msg.sender);
    }
    
    function updateEntity(uint _data) public{
        
        entityStructs[msg.sender].data = _data;
    }
   
}

StorageArray.addEntity(uint256)

  • transaction cost ==> 83872 gas
  • execution cost ==> 62408 gas

StorageArray.updateEntity(uint256)

  • transaction cost ==> 31464 gas
  • execution cost ==> 9936 gas

StorageMapping.addEntity(uint256)

  • transaction cost ==> 24514 gas
  • execution cost ==> 3050 gas

StorageMapping.updateEntity(uint256)

  • transaction cost ==> 27065 gas
  • execution cost ==> 5537 gas

An array is clearly using more GAS than mapping.

1 Like

Here is my solution

  1. Array structure
    addEntity() execution cost : 62384 gas
pragma solidity 0.7.4;

contract AssignmentArray {
    
    
    
   struct Entity{
       address entityAddress;
       uint data;
   }
    
    Entity[] public entities;
    
    
    
    function addEntity(address entityAddress, uint data) public returns(bool success){
        
        Entity memory newEntity;
        
        newEntity.entityAddress = msg.sender; 
        newEntity.data = data;
        entities.push(newEntity);
        
        return true;
    
    }
    
    function getIndex(address entityAddress) public view returns(uint index){
        for( uint i = 0; i < entities.length;i++){
            return index;
        }
    }
    
    
    function updateEntity(address entityAddress,uint data,uint index) public returns(bool success){
        
        require(entities.length != 0);
        require(entityAddress == msg.sender);
       
        entities[index].data = data;
        
        return true;
    
        
    }
    
}
  1. Mapping structure
    AddEntity() execution cost : 41435 gas
pragma solidity 0.7.4;


contract Assingment_Mapping {
    
    struct Entity{
      uint data;
      address entityAddress;
    }
    
    mapping (address => Entity) public entities;
    
    function addEntity (uint _data, address _entityAddress) public returns (bool success){
        entities[_entityAddress].data = _data;
        entities[_entityAddress].entityAddress= msg.sender;
        return true;
    }
    
    function updateEntity (uint _data,address _entityAddress) public returns (bool success){
        require(_entityAddress == msg.sender);
        entities[_entityAddress].data = _data;
        return true;
    }
    
    
}

So obviously the mapping consumes less gas.
I guess the reason for that is because in the array structure I created a whole new struct that was added to the array of entities, this means that whenever we are looking for a single element, we have to loop through the whole array. And looping is expensive :slight_smile:

  1. UpdateEntity()
    Execution cost on array : 7149 gas
    Execution cost on mapping : 20463 gas

Here the mapping cost more, but not sure why. Anyone?

1 Like

When executing the addEntity function, which design consumes the most gas (execution cost)? Is it a significant difference? Why/why not?
Add 5 Entities into storage using the addEntity function and 5 different addresses. Then update the data of the fifth address you used. Do this for both contracts and take note of the gas consumption (execution cost). Which solution consumes more gas and why?

The mapping costs less gas. It is quite a significant difference. When the array gets bigger and bigger the difference will only become bigger.

1 Like

Answers

contract Array{
    
    struct Entity{
    uint data;
    address _address;
    uint _index;
    }
    
    Entity[] public array;
    
    function addEntity(uint data) public{
        Entity memory newEntity;
        newEntity.data = data;
        newEntity._address = msg.sender;
        newEntity._index = array.length - 1;
        array.push(newEntity);
    }
    
    function updateEntity(uint data) public{
        Entity memory newEntity;
        array[newEntity._index].data = data;
    }
}

Add New Entity with Array - Gas Cost:

Schermata 2021-03-31 alle 12.00.17

contract Mapping{
    
    struct Entity{
    uint data;
    address _address;
    bool _isEntity;
    }
    
    mapping(address => Entity) public map;
    
    function addEntity(uint data) public{
        map[msg.sender].data = data;
        map[msg.sender]._isEntity = true;
    }
    
    function updateEntity(uint data) public{
        map[msg.sender].data = data;
    }
}

Add New Entity with Mapping - Gas Cost:

Schermata 2021-03-31 alle 12.00.38

There is a very significant difference between storing data into array vs mapping.
Mapping solution is cheaper by around 40% respect of the array solution.
This because in mapping we can add and store data in an easy way into key --> value form, instead of having a heavier struct of storing, such as an array box.

NB: as long as we add new data into array, the cost of execution and looping into the array itself will increase much more.

1 Like

Cool, workaround, thanks for sharing this. :+1:

Comparing the execution cost of mapping versus array:

Running addEntity function on mapping solution costs 41472 in gas (execution cost only)

Running addEntity function on array solution costs 62286 in gas (execution cost only)

So the mapping solution is definitely more cost effective, it’s about 66% of the cost of the other solution. This is because mappings take up less storage space than arrays, I think? Particularly given that we are creating an array of structs, I would imagine.

For updating the 5th address in the mapping contract, the execution cost was 5537.

For updating the 5th address in the array contract, the execution cost was 19437 (nearly 4x the updating cost in the mapping contract).

The array update takes so much more gas because you have to use a for loop and go through all of the other entities you’ve created to get to the 5th one - it’s iterating through this loop that is consuming the extra gas. In the mapping solution you don’t have to iterate - the key for the entity allows you to update it directly.

1 Like

Mapping

pragma solidity 0.8.0;

contract storageDesignAssignmentMapping {

    struct Entity {
        uint data;
        address _address;
    }
    mapping (address => Entity) entityMap;


    function isEntity() private view returns(bool) {
        return entityMap[msg.sender]._address == msg.sender;
    }
    
    function updateEntity(uint entData) public returns(bool done) {
        if(!isEntity()) revert();
        entityMap[msg.sender].data = entData;
        return true;
    }
    function addEntity(uint entData) public returns(bool done) {
        if(isEntity()) revert(); 
        entityMap[msg.sender].data = entData;
        entityMap[msg.sender]._address = msg.sender;
        return true;
    }
}

Array

pragma solidity 0.8.0;
contract storageDesignAssignmentArray{

    struct Entity {
        uint data;
        address _address;
    }
    Entity[] public entArray;

    function isEntity() private view returns(bool) {
        bool entExists=false;
        for(uint i=0; i < entArray.length; i++){
            if(entArray[i]._address==msg.sender){
                entExists=true;
                break;
            }
        }
        return entExists;
    }
    
    function updateEntity(uint entData) public returns(bool success) {
        //checks if entity exists in the loop already.  no need to do isEntity check
        bool updated=false;
        for(uint i=0; i < entArray.length; i++){
            if(entArray[i]._address==msg.sender){
                entArray[i].data=entData;
                updated=true;
                break;
            }
        }
        return updated;
    }
    function addEntity(uint entData) public returns(bool success) {
        //require(!isEntity(),"Entity Already Exists");
        entArray.push(Entity(entData, msg.sender));
        return true;
    }
}

I tested both versions with isEntity checks and without to see if it made much of a difference. Looping through on the isEntity check for Arrays made the gas inconsistent because I included a “break” to reduce the gas where possible.

The Array used about 20% more gas when adding a value and about 4x the gas when updating.
Adding the first value of the array seemed to be higher than adding the following values.

Results:
Mapping gas usage (execution cost )
1) with isEntity check:

  •      addFunction - 42659
    
  •      add 5 Entities + update #5
    
  •          add 5 = 42659 * 5
    
  •          update = 6717
    
    1. without isEntity check
  •      addFunction - 41656
    
  •      add 5 Entities + update #5
    
  •          add 5 = 41656* 5
    
  •          Update = 5717
    

Array gas usage
1) with isEntity check (loop including a break)

  •     addFunction - 63393
    
  •     add 5 Entities + update #5
    
  •         add = 63393,51150,53907,56664,59421
    
  •         update = 20188
    
    1. without isEntity check
  •     addFunction - 62485
    
  •     add 5 Entities + update #5       
    
  •         add = 62485, 47485, 47485, 47485, 47485
    
  •         update = 20188
1 Like

Array contract

pragma solidity 0.7.5;

contract MappingContract {
    
    struct Entity {
       uint data;
       address Address;
    }
    
    Entity[] public entityList;
    
    function addEntity(address _address, uint _data) public {
        Entity memory newEntity;
        require(msg.sender == _address);
        newEntity.Address = _address;
        newEntity.data = _data;
        entityList.push(newEntity);
        
    }
    
    function updateEntity(address _address, uint _data) public returns(uint,address) {
        require(msg.sender == _address, "not allow to update this account");
        Entity memory entity;
        address entityAddress;
        entity.Address = entityAddress;
        Entity[] storage Entities = entityList;
        bool Bool = false;
        uint i;
    
          for(i = 0; i < entityList.length; i++){
              if(Entities[i].Address == entityAddress) Bool = true;
                entity.data = _data;
                Entities[i] = entity;
                return (Entities[i].data, Entities[i].Address) ;
        }
           
       
    }   
}

Cost per transaction Transaction cost Execution cost
Add Entry 70194 47322
Update Entry 32899 10027

Mapping contract


pragma solidity 0.7.5;

contract MappingContract {
    
    struct Entity {
       uint data;
       address Address;
    }
    
    mapping(address => Entity) public entityMap;
    
    function addEntity(address _address, uint _data) public returns(uint, address) {
        Entity memory newEntity;
        require(msg.sender == _address);
        newEntity.Address = _address;
        newEntity.data = _data;
        entityMap[_address];
        return (newEntity.data,newEntity.Address);
    }
    
    function updateEntity(address _address, uint _data) public returns(uint, address) {
        require(msg.sender == _address);
        Entity memory updatedEntity;
        entityMap[_address] = updatedEntity;
        updatedEntity.data = _data;
        return (updatedEntity.data, updatedEntity.Address);
    }
    
}
Cost per transaction Transaction cost Execution cost
Add Entry 23575 703
Update Entry 25999 3127

Add entry cost differences (mapping vs array)

  • Transaction cost: 67% less to add an entry with mapping compared to array - likely because there is no sorting required with mapping
  • Execution cost: execution cost with mapping represents only 1.48% of the cost of array contract

Update entry cost differences (mapping vs array)

  • Transaction cost: mapping cost is equivalent to 79% of array cost
  • Execution cost: execution cost with mapping represents only 31.18% of the cost to do it using array
1 Like

I added a view function to the array contract to check on myself, but I understand it is free to use anyway so please ignore.

pragma solidity 0.7.5;
pragma abicoder v2;

contract storageDesignArrayAssignment{
    
    
    struct Entity{
        uint data;
        address _address;
    }
    
    Entity[] entities;
    
    
    function addEntity(uint data , address _address )public {
        entities.push(Entity(data , _address));
    }
    
    function updateEntity(uint data , address _address , uint _id)public{
        require(_address == msg.sender);
        entities[_id] = Entity(data , _address);
    }
    
    function getEntity(uint _id)public view returns(Entity []memory){
        return entities;
    }
}
pragma solidity 0.7.5;
pragma abicoder v2;

contract storageDesignMapping{
    
    struct Entity{
        uint data;
        address _address;
    }
    
    mapping(address=>Entity) public entities;
    
    function addEntity(uint data, address _address)public{
        entities[_address].data = data;
        
    }
    
    function updateEntity(address _address , uint _data)public{
        require(_address==msg.sender);
        entities[_address].data += _data;
     
    }

The addEntity()function in design array is much more expensive. The execution costs in design mapping is only a third of the cost in design array.

Execution cost /addEntity/ array = 62553
Execution cost/addEntity/ mapping = 20760

To update the fifth entity also consumes more in the array design.

Execution cost/updateEntity/ array = 8445
Execution cost/updateEntity/mapping = 5716

Arrays have more features than mappings (ie chronological order and methods (.lengths , push(), pop())
I guess that’s why they consume more Gas.

2 Likes

Array only solution
Since it was not specified to check for duplicate, and only being able to use arrays, in order to check for duplicates we must always iterate the array, which makes the time complexity grow linearly. If we only appended to the end of the array without checks, the performance might have been better than mappings.

pragma solidity 0.8.0;

contract GasTest{

    struct Entity{
        uint data;
        address _address;
    }
    
    // storage array for Entity struct
    
    Entity[] entities;
    
    // "add" functionality
    function addEntity(uint _data) public{
        // since we use array only, we need to iterate all elements to check for duplicates
        for(uint i = 0; i<entities.length; i++){
            require(msg.sender != entities[i]._address, "Address already registered");
        }
        entities.push(Entity({data:_data, _address:msg.sender}));
    }
    
    // "update" functionality
    function updateEntity(uint _data) public {
        // iterate array and if we find sender, we update
        // if the array is iterated and msg.sender is not found, do nothing
        // optionally an event could be logged alerting that the address is not registered (not implemented for gas performance)
        for(uint i = 0; i<entities.length; i++){
            if (entities[i]._address == msg.sender){
                entities[i].data = _data;
                break;
            }
        }        
    }
    
    function entitiesGetter() view external returns (Entity[] memory) {
        return entities;
    }
    
}

Mapping only solution

pragma solidity 0.8.0;

contract GasTest{

    struct Entity{
        uint data;
        address _address;
    }
    
    // storage array for Entity struct
    
    mapping (address => Entity) entities;
    
    // "add" functionality
    function addEntity(uint _data) public{
        // trick: uninitialized addresses in structs alwayss points to the 0th address
        require(entities[msg.sender]._address == 0x0000000000000000000000000000000000000000, "Already registered");
        entities[msg.sender] = Entity({data:_data, _address:msg.sender});
    }
    
    // "update" functionality
    function updateEntity(uint _data) public {
        require(entities[msg.sender]._address == msg.sender, "Not found in registry");
        
        entities[msg.sender].data = _data;
    
    }
    
    function getEntity() public view returns (address){
        return entities[msg.sender]._address;
    }
    
}

We expect mapping execution costs to be constant no matter the size, whereas arrays should be higher and grow as the array grows:

Mapping:

Add costs:
42416
42416
42416
42416
42416

Modify last:
6480

Array
Add costs:
63126
50883
53640
56397
59154

Modify last:
20964

2 Likes

I keep getting an error on my array contract transact to ArrayAssignment.updateEntity errored: Error encoding arguments: Error: invalid BigNumber string (argument=“value”, value="", code=INVALID_ARGUMENT, version=bignumber/5.0.8) GFrom what I understand this is an error with the compiler. Despite the error I can tell that the Array is more expensive. I guessed as much because I figured using the mapping would mean that the data has a more direct route to be called and edited so it would be a bit cheaper than an array which requires the cpu to look for entries

pragma solidity 0.8.3;
contract ArrayAssignment{

    struct Entity{
        uint data;
        address _address;
    }
    
    Entity [] Entities;
    
    function addEntity(uint _data) public {
        Entity memory newEntity= Entity(_data, msg.sender);           // I think there is a way to do this without creating a memory variable
        Entities.push (newEntity);
    }
    
    function getEntity() public view returns(Entity [] memory){
        return Entities;
    }
    
    function updateEntity(uint _index, uint _data) public {
        Entities[_index].data=_data;
            }
}

pragma solidity 0.8.0;
contract MappinAssignment{
mapping (address => Entity) Entities;

  struct Entity{
        uint data;
        address _address;
    }
    
    function addEntity(uint _data) public{
        Entity memory newEntity;
        newEntity.data=_data;
        newEntity._address=msg.sender;
        Entities[msg.sender]=newEntity;
    }

    function updateEntity(uint _data) public {
        Entities [msg.sender].data=_data;
    }
     function getEntity() public view returns(Entity memory){
        return Entities[msg.sender];
     }

}

1 Like

Hey, everyone, I seem to have troubles in deploying this contract and the console says

creation of onlyArray errored: Cannot convert undefined or null to object

Anyway, I’m here to turn in my assignment for the code part only. I can’t confirm the gas fees yet cause it doesn’t run. Thanks for the help

pragma solidity 0.8.0;

contract onlyArray {
    
    struct Entity {
        uint data;
        address _address;
    }
    
    Entity[] entityList;
    
    function addEntity(uint _data) public returns(Entity memory){
        Entity memory newEntity;
        newEntity.data = _data;
        newEntity._address = msg.sender;
        entityList.push(newEntity);
        return entityList[entityList.length - 1];
    }
    
    function updateEntity(uint _id, uint _data) public returns(bool updated){
        require(entityList[_id]._address == msg.sender);
        entityList[_id].data = _data;
        return true;
    }
}

contract onlyMapping {
    
    struct Entity {
        uint data;
        address _address;
    }
    
    mapping (address => Entity) public entMap;
    
    function addEntity(uint _data) public {
        Entity memory newEntity;
        newEntity._address = msg.sender;
        newEntity.data = _data;
        entMap[msg.sender] = newEntity;
        
    }
    
    function updateEntity(uint _data) public returns(bool updated){
        entMap[msg.sender].data = _data;
        return true;
    }
}
1 Like

Hi @CryptoXyz

Are you deploying with Truffle?
If yes post your truffle version and node version.

1 Like

Yo Xyz!! I’ve had this problem before with the Remix IDE. If you’re using Remix, back up your code to a text file (or download all the files on the Remix start page, which I recommend doing anyway), then just reload the Remix webpage

Took me forever to find the answer, hopefully this info gets to you before you feel too frustrated!

1 Like

Hi @dan-i,

I’m using remix, I haven’t started the part of this course on using truffle and Openzeppelin yet.
Thank you for the response

1 Like

Hey man!! Thanks for the advice!

After I downloaded all files from Remix, should I create a new workspace for this? reloading the webpage sends the same error again. Anyway, I’ll figure this out, thank you for the advice on downloading all files from Remix.

Btw, I sleep before I get too frustrated :rofl: Have fun learning @Hudson

1 Like