Day 11: Erc-20 Smart Contract

Today I finished up Udemy Course #2!

Ud2: Module 95 – 115.

Even though I finished up the course, I feel like I need to go back and get clear of many areas that I glossed over because I get the ‘gist’ of what was going on.

Spent a lot of time going over ERC-20 smart contract.

//SPDX-License-Identifier: GPL-3.0
 
pragma solidity >=0.5.0 <0.9.0;
// ----------------------------------------------------------------------------
// EIP-20: ERC-20 Token Standard
// https://eips.ethereum.org/EIPS/eip-20
// -----------------------------------------
 
interface ERC20Interface {
    function totalSupply() external view returns (uint);
    function balanceOf(address tokenOwner) external view returns (uint balance);
    function transfer(address to, uint tokens) external returns (bool success);
    
    function allowance(address tokenOwner, address spender) external view returns (uint remaining);
    function approve(address spender, uint tokens) external returns (bool success);
    function transferFrom(address from, address to, uint tokens) external returns (bool success);
    
    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
 
 
contract Cryptos is ERC20Interface{
    string public name = "Cryptos";
    string public symbol = "CRPT";
    uint public decimals = 0; //18 is very common
    uint public override totalSupply;
    
    address public founder;
    mapping(address => uint) public balances;
    // balances[0x1111...] = 100;
    
    mapping(address => mapping(address => uint)) allowed;
    // allowed[0x111][0x222] = 100;
    
    
    constructor(){
        totalSupply = 1000000;
        founder = msg.sender;
        balances[founder] = totalSupply;
    }
    
    
    function balanceOf(address tokenOwner) public view override returns (uint balance){
        return balances[tokenOwner];
    }
    
    
    function transfer(address to, uint tokens) public override returns(bool success){
        require(balances[msg.sender] >= tokens);
        
        balances[to] += tokens;
        balances[msg.sender] -= tokens;
        emit Transfer(msg.sender, to, tokens);
        
        return true;
    }
    
    
    function allowance(address tokenOwner, address spender) view public override returns(uint){
        return allowed[tokenOwner][spender];
    }
    
    
    function approve(address spender, uint tokens) public override returns (bool success){
        require(balances[msg.sender] >= tokens);
        require(tokens > 0);
        
        allowed[msg.sender][spender] = tokens;
        
        emit Approval(msg.sender, spender, tokens);
        return true;
    }
    
    
    function transferFrom(address from, address to, uint tokens) public override returns (bool success){
         require(allowed[from][msg.sender] >= tokens);
         require(balances[from] >= tokens);
         
         balances[from] -= tokens;
         allowed[from][msg.sender] -= tokens;
         balances[to] += tokens;
 
         emit Transfer(from, to, tokens);
         
         return true;
     }
}

Also, even though I finished the course, I don’t feel as though I “know” Solidity. So, my next plan is to start a new course and also finish Course #1.

The next course I’m getting ready to start is on Youtube {https://www.youtube.com/watch?v=M576WGiDBdQ&t=315s}.

I’ll refer to this is as YT1.

It’s a 16-hour video. I’d like to have it completed with 4 days. However, in the beginning, I’ll be feeling it out to see if it’s worth going through completely. At this point, I can gauge pretty well is the instructor is doing a good job teaching the concepts.

Day 10: Crowdfunding Smart Contract

UD2: Module 78 – 95.

I spent a total of 10 hours of studying (thanks to a Covid-19 Mini-Vacation).

Here’s the code from the course that was studied.


// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.5;
 
contract CrowdFunding {
    mapping(address => uint) public contributors;
    address public admin;
    uint public noOfContributors;
    uint public minimumContribution;
    uint public deadline; //timestamp
    uint public goal;
    uint public raisedAmount;
    
  
    // Spending Request
    struct Request {
        string description;
        address payable recipient;
        uint value;
        bool completed;
        uint noOfVoters;
        mapping(address => bool) voters;
    }
    
    // mapping of spending requests
    // the key is the spending request number (index) - starts from zero
    // the value is a Request struct
    mapping(uint => Request) public requests;
    uint public numRequests;
    
    // events to emit
    event ContributeEvent(address _sender, uint _value);
    event CreateRequestEvent(string _description, address _recipient, uint _value);
    event MakePaymentEvent(address _recipient, uint _value);
    
    
    constructor(uint _goal, uint _deadline) {
        goal = _goal;
        deadline = block.timestamp + _deadline;
        admin = msg.sender;
        minimumContribution = 100 wei;
    }
    
   
    modifier onlyAdmin() {
        require(msg.sender == admin, "Only admin can execute this");
        _;
    }
    
    
    function contribute() public payable {
        require(block.timestamp < deadline, "The Deadline has passed!");
        require(msg.value >= minimumContribution, "The Minimum Contribution not met!");
        
        // incrementing the no. of contributors the first time when 
        // someone sends eth to the contract
        if(contributors[msg.sender] == 0) {
            noOfContributors++;
        }
        
        contributors[msg.sender] += msg.value;
        raisedAmount += msg.value;
        
        emit ContributeEvent(msg.sender, msg.value);
    }
    
 
    function getBalance() public view returns(uint) {
        return address(this).balance;
    }
    
    // a contributor can get a refund if goal was not reached within the deadline
    function getRefund() public {
        require(block.timestamp > deadline, "Deadline has not passed.");
        require(raisedAmount < goal, "The goal was met");
        require(contributors[msg.sender] > 0);
        
        address payable recipient = payable(msg.sender);
        uint value = contributors[msg.sender];
        
        // resetting the value sent by the contributor and transfering the value
        contributors[msg.sender] = 0;  
        recipient.transfer(value);
        // equivalent to:
        // payable(msg.sender).transfer(contributors[msg.sender]);
    }
    
    
    function createRequest(string calldata _description, address payable _recipient, uint _value) public onlyAdmin {
        //numRequests starts from zero
        Request storage newRequest = requests[numRequests];
        numRequests++;
        
        newRequest.description = _description;
        newRequest.recipient = _recipient;
        newRequest.value = _value;
        newRequest.completed = false;
        newRequest.noOfVoters = 0;
        
        emit CreateRequestEvent(_description, _recipient, _value);
    }
    
    
    function voteRequest(uint _requestNo) public {
        require(contributors[msg.sender] > 0, "You must be a contributor to vote!");
        
        Request storage thisRequest = requests[_requestNo];
        require(thisRequest.voters[msg.sender] == false, "You have already voted!");
        
        thisRequest.voters[msg.sender] = true;
        thisRequest.noOfVoters++;
    }
    
    
    function makePayment(uint _requestNo) public onlyAdmin {
        Request storage thisRequest = requests[_requestNo];
        require(thisRequest.completed == false, "The request has been already completed!");
        
        require(thisRequest.noOfVoters > noOfContributors / 2, "The request needs more than 50% of the contributors.");
        
        // setting thisRequest as being completed and transfering the money
        thisRequest.completed = true;
        thisRequest.recipient.transfer(thisRequest.value);
        
        emit MakePaymentEvent(thisRequest.recipient, thisRequest.value);
    }  
}

Day 9: Lottery Project

[UD2:49 – UD2:65]

Today I spent about six hours of studying the UD2 course (Module 46 through Module 65).

I probably would have a record day in terms of the amount of hours in one day studying if it weren’t for a storm that knocked the power out.

Anyway, today the instructor broke down the lines of code in two smart contracts – a lottery smart contract and an auction smart contract.

Below is the lottery smart contract.

You’ll see that in some of the comments that are bold notes (NOTE #1, NOTE #2, etc.). Those are key points where I would like to expand more about what I learned below the smart contract instead of putting it in the code.)



//SPDX-License-Identifier: GPL-3.0
 
pragma solidity >=0.5.0 <0.9.0;
 
contract Lottery{
    
    // declaring the state variables 
    address payable[] public players; // NOTE #1 - dynamic array of type address payable
    address public manager; 
    
    
    // declaring the constructor
    constructor(){
        // initializing the owner to the address that deploys the contract
        manager = msg.sender; 
    }
    
    // declaring the receive() function that is necessary to receive ETH
    receive () payable external{
        // each player sends exactly 0.1 ETH 
        require(msg.value == 0.1 ether);
        // appending the player to the players array
        players.push(payable(msg.sender));
    }
    
    // returning the contract's balance in wei
    function getBalance() public view returns(uint){
        // only the manager is allowed to call it
        require(msg.sender == manager);
        return address(this).balance;
    }
    
    // helper function that returns a big random integer
    function random() internal view returns(uint){
       return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp, players.length)));
    }
    
    
    // selecting the winner
    function pickWinner() public{
        // only the manager can pick a winner if there are at least 3 players in the lottery
        require(msg.sender == manager);
        require (players.length >= 3);
        
        uint r = random();
        address payable winner;
        
        // computing a random index of the array
        uint index = r % players.length;
    
        winner = players[index]; // this is the winner
        
        // transferring the entire contract's balance to the winner
        winner.transfer(getBalance());
        
        // resetting the lottery for the next round
        players = new address payable[](0);
    }
 
}

As you can see, the code has a lot of descriptive comments. I’ll provide

Key Takeaways:

>> address payable[] public players; // NOTE #1 – dynamic array of type address payable. This allows lottery players to have their addresses payable in the event that they win.

>> There are two types of addresses. (1) Payable – ETH can be sent from the smart contract to the address. (2) Non-payable – ETH can not be sent.

(( I actually took lots of screen shot notes. At some point, I might post them in the post. ))

I feel great because I’m at a point where I can understand 95% or more of the code.

I now realize that it’s a good idea when you’re just starting out to just ‘get the gist’ of what’s going on and trust that everything will become more clear as you move on with the lessons.

Another thing: I’ve started to focus more on UD2. At first I was going back and forth between UD1 and UD2, but with UD2, I like Andrei’s teaching style a little bit better. Mainly because he explains things better. He breaks down the code.

Even though, he can be a little hard to understand at times, I’m enjoying his course a lot.

Also, we went over part of an auction smart contract today. I’ll post below what was covered.


//SPDX-License-Identifier: GPL-3.0
 
pragma solidity >=0.5.0 <0.9.0;
 
 
contract Auction{
    address payable public owner;
    uint public startBlock;
    uint public endBlock;
    string public ipfsHash;
 
    
    enum State {Started, Running, Ended, Canceled}
    State public auctionState;
    
    uint public highestBindingBid;
    
    
    address payable public highestBidder;
    mapping(address => uint) public bids;
    uint bidIncrement;

**************

NOTE: this is just the first 21 lines of code of a smart contract that is 139 lines.



Day 8: public, private, internal or external

As you can have noticed, I posted pretty regularly from Day 1 to Day 7.

Even thought there is a 10 day gap between Day 7 and Day 8, there were a few days in between where I studied a little bit…just not enough to make a blog post.

As far as today, I spent a lot of time on Module 49 (Udemy Course 2 – Andrei Dumitrescu). I watched this video very slowly and took notes by hand (as you see below) along the way. In this video, he discussed in great detail the difference between labelling a variable as public, private, internal or external.

I had been seeing these terms since Day 1. And even though I had a vague understanding, I didn’t feel like I knew the terms completely and thought it made sense to MAKE SURE I reeeeeally understood it.

Let’s looking at the following program.

//SPDX-License-Identifier: GPL-3.0
 
pragma solidity >=0.5.0 <0.9.0;
 
contract A{
    int public x = 10;
    int y = 20; // internal by default

function get_y() public view returns(int){
    return y;
}

function f1() private view returns(int){
    return x;
}

function f2() public view returns(int){
    int a;
    a = f1();
    return a;
}

function f3() internal view returns(int){
    return x;
}

function f4() external view returns(int){
    return x;
}

function f5() public pure returns(int){
    int b;
    // b = f4(); //f4() is external
    // Even though f4() wasn’t external it wouldn’t be possible to be called 
    // from within f5() because f5() is pure (it can not read nor write to the blockchain)

    return b;


 }
}
 
contract B is A{
    int public xx = f3();
    // int public yy = f1(); -> f1() is private and cannot be called from derived contracts
}
 
contract C{
    A public contract_a = new A();
    int public xx = contract_a.f4();
    // int public y = contract_a.f1();
    // int public yy = contract_a.f3();
}

I will say the above page is pretty readable, but the second page of notes (below) isn’t. So, I’ll write out the key parts, N1, N2, N3 and N4.

N1 = See NOTES (N4) at the bottom of the page. A contract that deploys another can not call its internal variables, BUT a contract that is derived from another can call its internal variables.

N2 = external variables can’t be called from the contract it was declared. It can only be called from outside contracts and applications. External functions care more efficient in terms of gas consumption.

N3 = This [line of code represents] a contact that deploys another contract

N4 = f4 could be called, but not f1 (because it’s private) and f3 can’t be called (because it’s internal….meaning it can’t be called by other contracts)

Day 7

Major breakthrough today.

One thing that I don’t think I mentioned is that for the past 3 days I’ve been hunting like a mad man for just ONE screenshot software that would allow me to capture a part of the video so that I could take notes directly on the image.
That’s all I wanted to do. I didn’t think I was asking for a lot. 🙂

You see, if I were to attempt to do a screenshot of a Youtube video, it works great.

Solidity Tutorial Video (http://freecodecamp.org)

However, if I were to try that with a video from a Udemy course, something interesting happens. Basically, the moment the screen capture tool is prepared to capture the screen, the Udemy’s video screen just instantly turns black.
Suuuuuper frustrating!

I spent 3 or 4 days trying to find just ONE screen capture tool that would allow me to capture the screen without it going blank and no luck. After the 7th free tool, I considered a paid one, until I just assumed that Udemy’s video technology just doesn’t allow for screen captures.

As an avid note taker, it was beyond frustrating. But, I gave up and just decided to write things down on paper.

I did this for a day.

Then, the next day it hit me! It was like a huge ‘duh’ moment. I figured, I’ll use my Galaxy Tablet to take a picture of the computer screen.

I’m not going lie, there was a brief moment when I thought the Udemy screen would go blank seconds before I took a physical picture.

But it didn’t. And since the tablet has a stylus, I could just write the notes on picture that I took. And even though it’s not as clean as a screen capture, it’s good enough. And that’s what I done. See the beautiful work for yourself below.


Also, I abandoned the plan of buying 2-3 extra courses as I mentioned earlier.

After the second one, doing two courses at once – along with tutorialspoint.com seem to be perfect!

At this point, I feel like I should be pretty proficient in Solidity by August 30th (that’s the new Goal!)

(https://www.udemy.com/course/blockchain-developer)