Solidity Basics

Hi @InterstellarX,

The while-loop and for-loop examples in the video are just to demonstrate the syntax that is available to you in Solidity to perform loops (i.e. almost the same syntax as in JavaScript). You are right to suspect that there wouldn’t actually be any practical reason why you’d want to use a while-loop (or a for-loop for that matter), if all you wanted to achieve was to return an integer greater than the input by a certain amount. It would be inefficient and a waste of gas to use a loop to do this, and, as you have suggested, we would just use an addition operator instead e.g.

function addTen(int number) public pure returns(int){
    return number + 10;
}

So, no … it’s nothing to do with this. Defining the data type of the input parameter and the return value as an integer (or unsigned integer) with int or uint is enough to meet the stricter requirements of Solidity in terms of it being a statically-typed language.

Just let me know if you have any further questions :slight_smile:

1 Like

Thanks so much, @jon_m! Really appreciate the response…I’m more just trying to ask questions to learn :blush: Also totally see what you mean about making number an integer so that it knows that + 10 will add to the number value, and then return the integer itself.

1 Like

I have a question: when I create a setter function and add a return statement, when I deploy the contract it is not returning anything, although its declared to return an int value. Also the button for the function is orange not blue in remix. Anyone can explain why that is?

function setScore(int _score) public returns(int) {
    score = _score;
    return score;
}
1 Like

Hi @dcts,

It is returning the value, but you will only see it in the transaction receipt. In Remix, the transaction receipt is what appears in the Remix terminal below the text editor. It will have a green tick next to it if the transaction has been successfully mined and added to the blockchain. You need to open the transaction receipt by clicking on it, and then scroll down to the decoded output object, where you will see the returned value.

When you call a function which modifies the contract state (like your setter) from a Web3 client in the front-end (which is what you’re doing, here, from Remix) you are signing and broadcasting a transaction to the network. This costs gas, and on the mainnet it takes time for the transaction to be included in a block, for the block to be mined or validated, and for the block to be added to the blockchain. So, only the transaction hash will be returned to the Web3 client more or less immediately, and this is why you’re not seeing the value returned from your function next to the orange function-call button. You can see the transaction hash and the gas cost in the same transaction receipt that I mentioned above.

In the front-end we can use asynchronous web3.js code to return the transaction receipt, but this isn’t generated until the block containing the transaction has been added to the blockchain. And even then, we should wait for a certain number of block confirmations before any data in the transaction receipt regarding state changes can be relied upon with any confidence. It’s possible to use asynchronous web3.js code to listen out for these confirmation events as well, but I actually don’t think it’s possible for return values from a function which has changed the contract state to be returned to the Web3 client anyway. This may have changed, and I do need to check the finer details and perform some tests, but the usual way for a Web3 client to retrieve updates regarding changes to the contract state, as soon as they are confirmed on the blockchain, is by including events in our smart contract, which will emit and log the updates we want to track, and which we can then capture in the front-end using web3.js event listeners. You will learn about how to code events in Solidity later in this course.

Because of what I’ve explained above, a setter function would normally only need to return a value when the setter function is called from another function — either within the same smart contract, a derived smart contract or an external smart contract — and this other function needs to retrieve and further process an output from the setter function.

If the Web3 client only needs to retrieve data, and doesn’t need to modify the state of the smart contract, then we don’t need to spend gas on sending a transaction. We normally do this by marking the function with the view keyword, because the data we are retrieving normally involves reading the contract state (i.e. the data stored in the contract’s state variables or mappings).

If a Web3 client calls a function marked view (or pure), the return value(s) will be sent to it immediately. This is reflected in Remix, and why a view (or pure ) function will output its return value(s) below the blue function-call button, but an undefined function (orange button) or payable function (red button) will only show any return values as decoded output in the transaction receipt in the terminal.

Just to be clear, there are 4 function types (3 of which we define with specific keywords in the function header) as follows:

  1. pure (most restrictive)
    Cannot change or read the contract state.
  2. view
    Can read the contract state, but cannot change it.
  3. undefined (no type declared in the function header)
    Can read and change the contract state (but cannot receive ether)
  4. payable (least restrictive)
    Can read and change the contract state, and can also receive ether.
    (We will look at payable later in the course)

As well as the issues of (i) gas cost, and (ii) the ease of receiving return data in the front-end, choosing the right function type is also important to (iii) reduce security risk by only permitting each function to access and change what it needs to.

I hope this clarifies things. Just let me know if you have any further questions.

And by the way, it’s good to see you back here in the forum after a while … I hope you’re enjoying the course so far :slight_smile:

1 Like

Wow that is a killer explenation! So glad I asked and thanks so much for the deep dive. I know it might be early in the course but how you explained it now makes so much sense to me! I totally get now why we classify functions in those 4 types (which was confusing at first) :slight_smile:

Thanks for taking the time @jon_m, really appreciate it a lot!

1 Like

Hey Thomas,

That’s great if my explanation made sense, because there was a lot of detail in there :sweat_smile: but I couldn’t really answer your questions properly without giving you a much more detailed picture of how the front-end Web3 client interacts with the EVM/smart-contract/blockchain back-end.

Keep asking the great questions, and you are sure to make great progress on this course, and with Solidity in general :muscle:

can anyone advise, I’m not able to compile the below contract for the mappings exercise, not sure what the error is,

pragma solidity 0.7.5;

contract Bank {

    mapping (address => uint) balance;

    function addBalance(uint _toAdd) public returns (uint) {

        balance[msg.sender] += _toAdd;

        return balance[msg.sender];

    }

   

    function getBalance () public view returns (uint) {

        return balance = [msg.sender];

    }

    }

Hi @Andre_Mark,

Good to see you back again after a while :slight_smile:

Your error is in the return statement in your getBalance() function…

You need to remove the assignment operator =  so that it’s referencing the balance of msg.sender in the balance mapping (exactly the same as in the return statement in your addBalance function)…

1 Like

Ran into this problem on the 8th lesson:

Followed along and typed the code out verbatim. However when I deploy the contract on the left toolbar, there is no lower section like on the video where I can input a number. All it shows me under “deployed contract” heading is this message: “Currently you have no contract instances to interact with”.

Is there something I might be missing?

Also when I view the terminal below it shows “creation of HelloWorld pending”

Hi @Liquidbaker89,

Are you still having this problem deploying your contract?

It could be caused by a number of issues …

If the terminal continues to show this, without any transaction receipt with a green tick confirming successful deployment, then this is something which can happen now and again with Remix, and is usually resolved by closing it in the browser, and then reopening it. I’m not sure why it happens, but it can get “stuck” once in a while.

If you still have any compiler errors in your contract code, then this will also prevent deployment. If you have Auto Compile turned on (under Compiler Configuration in the Solidity Compiler panel) then the compiler will highlight any compiler errors while you’re writing your code. It’s often easier to debug and correct errors as and when they arise, instead of waiting until you’ve finished and then clicking compile. Either way, you need to make sure that you have compiled your contract, and resolved any errors, before you deploy it.

Once your contract is successfully compiled, you need to make sure that the name of the contract you want to deploy is showing in the Contract field (just above the orange Deploy button in the Deploy & Run Transactions panel). Then you can click the orange Deploy button, the contract should deploy, and you should see it, together with the address it’s been deployed at, below Deployed Contracts. You then need to click on it to access all of the function-call buttons.

Let me know if you’re still having any problems. If you are, then post a copy of the code you’re trying to deploy as well, so I can test it in Remix myself. If you’ve already resolved this on your own, then hopefully some of the tips I’ve given you will still prove useful :slight_smile:

Hey guys, I made a drawing to help visualize visibility (or tried to with my poor skills on Evernote). I just started so let me know if it’s wrong, but that’s what I understood from the video.

1 Like

Hi @seybastiens,

This is a really good attempt at a visual representation of visibility for functions and state variables in Solidity — well done! :muscle:

I think there is only one thing missing, and one inaccuracy …

  • To complete the picture, I think you should add an “external front-end service” (i.e. a web3 client) e.g. Remix or the front-end of a dapp.
    Only functions with public or external visibility can be called from a web3 client. But it is important to recognise that external functions can be called from a web3 client as well as from external smart contracts.
    Unlike functions, state variables cannot have external visibility. So, only public state variables are directly accessible from a web3 client (via a getter which is automatically created by Solidity).

  • External smart contracts (i.e. other non-derived smart contracts) can call functions with public or external visibility, but they can’t call functions with internal visibility. The only “other” contracts which can call internal functions are derived contracts, because they are inherited by the derived contract and effectively act as its own private functions. This should become clearer and make more sense when you cover inheritance later in this course.

It won’t be easy to adjust your illustration for these additional points, but I hope you’re up for the challenge!

Let me know if anything is unclear, or if you have any questions :slight_smile:

Hey Jon, thanks for your reply.
I didn’t know about your first point so I just editted the representation accordingly.
Regarding the second point, this is why I wrote in yellow “inheritance”, because some external contracts get pointed to with yellow arrows (by inheritance). And these external contracts are the ones who have the functions in internal, that’s why they are circled in purple too. I also added a grey color to differenciate derived smarts contracts from non-derived ones.
Hopefully I understood it clearly now.

1 Like

Hey Seb,

That’s looking good for the external service, because it shows it has access to both public and external functions :ok_hand:


I have interpreted your diagram as showing where functions and state variables can be accessed from depending on their visibility.

So, the blue box shows that public functions and state variables can be accessed from anywhere: an external service, both external (non-derived) and derived smart contracts, and from within the same smart contract :white_check_mark:

The green box shows that private functions and state variables can only be accessed from within the same smart contract :white_check_mark:

The purple boxes show that internal functions can be accessed from within the same smart contract and any derived contracts :white_check_mark: but that internal state variables can only be accessed from within the same contract. However, as with internal functions, internal state variables can also be accessed from within derived contracts, so I think your original diagram was more accurate here (without the dotted blue line to exclude internal state variables).

Finally, I interpret the pink/brown border in the latest version of your diagram as showing that external functions can be accessed from an external service :white_check_mark: from external (non-derived) contracts :white_check_mark: but also from within any derived contracts i.e. from within any other contract. This last part isn’t true. When a derived contract is compiled, all of the inherited functionality from its base/parent contract is included within one set of byte code, which is then deployed as a single contract at a single Ethereum address. So, when the derived contract is deployed, any external functions inherited from its parent contract will behave as if they are its own. And as a contract’s own external functions cannot be accessed from within itself, neither can a derived contract access any external functions which it inherits.

So, I think the derived contracts in your diagram shouldn’t be included within the pink/brown border, so that it only encloses the external service and external (non-derived) contracts, because these are the only places where external functions can be called from.

A couple of points to clarify here …

  • If our smart contract is inherited, then the contracts which inherit it are its derived contracts, but not its external contracts. Our smart contract’s external contracts will be those that are deployed at separate addresses and with which no inheritance relationship exists.
  • The way I understand and make sense of your diagram is that any dark-blue boxes within “other contracts” (derived or external) need to indicate whether functions/state variables with a certain visibility can be accessed by that contract, and not functions/state variables defined within that contract itself.

As I mentioned before, I think this level of detail regarding internal and external visibility will become clearer, and make more sense to you, when you reach the inheritance section of the course. So, you may want to come back and make the modifications later on.

At this early stage, though, you’ve done a great job! :muscle:

Just let me know if you have any more questions :slightly_smiling_face:

Thanks a lot for helping me improve it.
Yes this is exactly the purpose of the diagram, you said it very nicely & clearly :

I didn’t know about this part. How is that ? I don’t get it.

“Access within itself” means that the function is part of the smart contract, but its type switched from external to private ?

And also you mean that when the smart contract is “derived”, all its functions (which are external, public, private or internal) will become private on the derived smart contract. Right ?
So we cannot access (copy or/and just see what is inside) the private functions of a smart contract that is not ours, correct?

I tried to readapt it again from what I understood from this.!

1 Like

Hi @seybastiens,

Sorry for the delay in getting back to you on this!

No … it means that if a contract contains a function with external visibility, then it cannot be called from within any other function within that same contract e.g.

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.5;

contract Example {

    string public message;
    
    function inputMessage(string memory _message) external {
        setMessage_A(_message);  // COMPILER ERROR
        setMessage_B(_message);  
    }

    // EXTERNAL visibility, so CANNOT be accessed/called by inputMessage()
    function setMessage_A(string memory _message) external {
        message = _message;
    }

    // PRIVATE visibility, so CAN be accessed/called by inputMessage()
    function setMessage_B(string memory _message) private {
        message = _message;
    }

}

A function with external visibility also cannot be called from within any functions in a derived contract e.g.

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.5;

contract Base {

    string public message;

    // EXTERNAL visibility, so CANNOT be accessed/called by inputMessage()
    function setMessage_A(string memory _message) external {
        message = _message;
    }

    // PRIVATE visibility, so CANNOT be accessed/called by inputMessage()
    function setMessage_B(string memory _message) private {
        message = _message;
    }

    // INTERNAL visibility, so CAN be accessed/called by inputMessage()
    function setMessage_C(string memory _message) internal {
        message = _message;
    }

}

contract Derived is Base {
    
    function inputMessage(string memory _message) external {
        setMessage_A(_message); // COMPILER ERROR
        setMessage_B(_message); // COMPILER ERROR     
        setMessage_C(_message); 
    }

}

If we use this 2nd example to illustrate what I meant in my previous post, then when we deploy Derived…

  • It will inherit from Base: the public state variable message , and the external and internal functions setMessage_A and setMessage_C
  • It won’t inherit from Base: the private function setMessage_B

So, we are only deploying one contract (Derived) which contains one set of compiled bytecode representing the whole of Derived and the functionality inherited from Base i.e.

  • the state variable message; and
  • the functions inputMessage , setMessage_A and setMessage_C

In other words, the functionality of the external function setMessage_A , although written in Base, will be included within the bytecode deployed as Derived. But in this case, whether you think of this function as being in Derived or in Base, it’s accessibility is the same: it can be called from an external service, or from an external (separately deployed) contract, but NOT from within a function in the same contract deployed as Derived.

So, no, I didn’t mean this. The visibility of any contract’s functions doesn’t change. Hopefully, my additional explanation above has now made this clearer, and explains this better.

Yes … this is essentially correct. But rather than thinking in terms of “we” and “our” etc., you need to think of accessibility in terms of “where from” …

A) Externally (from outside the deployed contract)
  1. From an external service.
  2. From within a function in an external contract (a contract which has been separately deployed).

B) Internally (from inside the same deployed contract)
  1. From a function written in the same contract as the state variable being accessed or the function being called.
  2. From a function written in a derived contract which inherits the state variable being accessed or the function being called.

Functions and state variables with public visibility can be accessed from anywhere (A1, A2, B1 and B2).
Functions and state variables with private visibility can only be accessed from B1.
Functions with external visibility can be accessed from anywhere outside the deployed contract (A1 and A2).
Functions and state variables with internal visibility can be accessed from anywhere inside the same deployed contract (B1 and B2).

So, in terms of your diagram …

If, as I think you’ve confirmed, the thick, coloured boxes/borders indicate where the functions and state variables in OurSC can be called/accessed from, then all of these now enclose the correct locations …

  • Functions and state variables with public visibility can be accessed from anywhere (blue box).

  • Functions and state variables with private visibility can only be accessed from inside the same deployed contract AND where they are also written in that same contract and not inherited (green box).

  • Functions with external visibility can be accessed from anywhere outside a deployed contract, whether the deployed contract is a derived contract or not (red border).

  • Functions and state variables with internal visibility can be accessed from anywhere inside the same deployed contract, whether the deployed contract is a derived contract or not (purple border).


I think the only things you now need to correct are …

  1. The note in yellow because, as well as functions and state variables with public and internal visibility being inherited by derived contracts, external functions (red) are also inherited. However, only the inherited public and internal functions and state variables from the base contract are accessible from within the derived contract’s functions. So you could change this note to something like …

  Inherited functions/state variables accessible from within the derived contract itself

  1. The note in grey, because contracts cannot be described as internal (only functions and state variables as having internal visibility). So, you should change this note to just…

  Derived smart contracts

  1. I would probably remove the external (red) and public (blue) functions from your external contracts because this is confusing. Otherwise, you will need to clarify what this means with another note e.g.

  Functions which can be called externally (from an external service or contract)

    … but this is already shown by the the blue and red borders.


Wow! That was a long post! :sweat_smile:

But I hope it’s been helpful, and I’ve answered your questions. Let me know if you have any more :muscle:

Amazing thanks for your time Jon,

I think that now everything is clear is my head and on the diagram too.
Here is the last version with the corrections.
So derived contracts will inherite public, internal and external functions / state variables (blue, purple and red dots), but they can only access the public and internal ones from the deployed smart contract (so only within the blue and purple thick lines.

1 Like

I would like to know how to add uint values with commas.
For example: if I want to add the weight of a person inside a data type “person”, Id like to be able to enter manually “90,5” (as in 90kilos and 500 grams)

what type of data type do I have to choose, is unit correct? and when I enter its value on remix, how can I make remix understand that the comma I add belongs to the number of 90,5 and is not defining another value type (because commas are used to separate value types )

1 Like

Great question @JPLaclau!

… and it’s good to see you back here in the forum :slight_smile:

Basically, you’re asking if we can write numbers with decimal places in Solidity…

It depends on the country whether a decimal point (full stop or period character) or a decimal comma is used to separate the “whole” part of the number (integer) from its decimal places (fractional part) e.g. the decimal point is used in the UK and the US, whereas the decimal comma is used in Spain and France.

However, Solidity doesn’t allow us to express numbers with decimal places (fractional parts), so we can’t use a decimal point or comma. All numbers must be integers (whole numbers): either unsigned (uint) or signed (int). Unsigned integers can only be positive (including 0), whereas signed integers can be positive or negative.

When we code a smart contract using Solidity, if we need to express number values of things like currencies, weights, measurements etc., which use a hierarchy of units (e.g. kilometer, meter, centimeter, millimeter), then this isn’t actually a problem, as long as we represent, calculate, manipulate, process and store all of these numbers in units which avoid having to use decimal places.

So, if the smallest unit of weight your smart contract needs to handle is grams (not milligrams), then the best solution here would probably be to work with these number values in grams e.g.

90500  // 90,5 kg (or 90.5 kg)
100000 // 100 kg
64375  // 64,375 kg (or 64.375 kg)

If you want these values to be displayed to, and input by, the end user in kilograms, with the grams expressed as decimal places (fractions of a kilogram), then you can perform the to/from conversions, together with the appropriate formatting with commas, full stops, “kg” etc., in your frontend code using JavaScript.


As Wei is the smallest unit of the Ethereum network’s native cryptocurrency, Ether, when working with Ether values in our smart-contract Solidity code, we express these values in units of Wei e.g.

4500000000000000000
// 4500000000000000000 Wei  =  4500000000 Gwei  =  4.5 Ether

5750000000000000
// 5750000000000000 Wei  =  5750000 Gwei  =  0.00575 Ether

333225
// 333225 Wei  =  0.000333225 Gwei  =  0.000000000000333225 Ether

1
// 1 Wei  =  0.000000001 Gwei  =  0.000000000000000001 Ether

However, Solidity syntax does also include the suffixes ether and gwei, which provide us with a useful shorthand, and do allow numbers to be written with fractional parts using a decimal point (but not a decimal comma). For example, 1 Ether can be expressed using the following 3 alternatives…

1000000000000000000
1000000000 gwei  // gwei keyword equivalent to:  * 1000000000           (9 zeros)
1 ether         // ether keyword equivalent to:  * 1000000000000000000 (18 zeros)

… and the previous examples could also be written in Solidity as follows …

 4500000000000000000       // or 
          4500000000 gwei  // or
                 4.5 ether        

    5750000000000000       // or
             5750000 gwei  // or
             0.00575 ether

              333225       // or
         0.000333225 gwei  // or
0.000000000000333225 ether

The suffix wei is also available, but this would only seem to be worth using in situations where there could be a risk of confusion, because, for example, the following 2 alternatives are both valid Solidity code for 0.05 Gwei …

50000000 wei  // or
50000000

Here is a link to the relevant section in the Solidity documentation about these keywords …
https://docs.soliditylang.org/en/latest/units-and-global-variables.html#ether-units


In terms of your other questions …

Number values in our Solidity code which represent Ether values need to be defined as unsigned integers (uint data type). In fact, you would only want to use signed integers (int data type) for other units of currency, weight, measurement etc. (such as your kilograms/grams) when you need to be able to represent, process and store negative values within your smart contract.

So, in Remix, when you want to call a function with a number argument …

  • A uint function parameter will only accept an unsigned integer (a whole number comprising only of digits, with no other character types, such as full stops, or commas).

  • An int function parameter will only accept either a positive or negative integer (a whole number comprising only of digits, with a single, optional minus sign being the only other character allowed to precede it.

Let me know if anything is unclear, or if you have any further questions :slight_smile:

1 Like