cyfuer

Jul 03, 2022

学习笔记:《Full Stack Blockchain Lesson 4:Remix Fund Me》

 
 
 

Introduction

Create smart contract fill that request:
  • Get funds from users
  • Withdraw funds
  • Set a minimum funding value in USD

Sending ETH Through a Function & Reverts

Operation

  1. create file FundMe.sol and program the code
    1. // SPDX-License-Identifier: MIT pragma solidity ^0.8.8; contract FundMe { function fund() public payable { require(msg.value > 1e18, "Don't send enough!"); } }
      notion image
  1. Complie FundMe.sol
  1. Deploy FundMe.sol
    1. notion image
  1. Set value at least 1 eth, and call fund function
    1. notion image
 

Fields in a Transaction

An Ethereum transaction refers to an action initiated by an externally-owned account.
notion image
A submitted transaction includes the following information:
  • recipient – the receiving address (if an externally-owned account, the transaction will transfer value. If a contract account, the transaction will execute the contract code)
  • signature – the identifier of the sender. This is generated when the sender's private key signs the transaction and confirms the sender has authorized this transaction
  • nonce - a sequencially incrementing counter which indicate the transaction number from the account
  • value – amount of ETH to transfer from sender to recipient (in WEI, a denomination of ETH)
  • data – optional field to include arbitrary data
  • gasLimit – the maximum amount of gas units that can be consumed by the transaction. Units of gas represent computational steps
  • maxPriorityFeePerGas - the maximum amount of gas to be included as a tip to the validator
  • maxFeePerGas - the maximum amount of gas willing to be paid for the transaction (inclusive of baseFeePerGas and maxPriorityFeePerGas)

More on v,r,s

notion image
vrs are the values for the transaction's signature. They can be used as in Get public key of any ethereum account
A little more information, r and s are outputs of an ECDSA signature, and v is the recovery id.
 
notion image
notion image
 

payable

make a function payable with ethereum or any other need of blockchain currency.

msg.value & Other global keywords

msg.value (uint): number of wei sent with the message

require

require basically means to demand something before availing the service to the users.

revert

REVERT will still undo all state changes, but it will be handled differently than an “invalid opcode” in two ways:
  1. It will allow you to return a value.
  1. It will refund any remaining gas to the caller.

Chainlink & Oracles

What is a blockchain oracle?

Blockchain oracles are entities that connect blockchains to external systems, thereby enabling smart contracts to execute based upon inputs and outputs from the real world.
 

What is the oracle problem?

The oracle problem revolves around a very simple limitation—blockchains cannot pull in data from or push data out to any external system as built-in functionality.
notion image
 

Chainlink

notion image
 
 

Chainlink Price Feeds (Data Feeds)

notion image
notion image
 

Chainlink VRF

chainlink verifiable random function(vrf) is a way to get provably a random number into our smart contract.
notion image
 

Chainlink Keepers

decentralized event driven execution, if you have a decentralized application that needs to run at specific times, or after specific events or trigger, chainlink keepers are the solution to this.
 
chainlike keepers are chainlike nodes that listen to a registration contract for different events that you specify to fire.
notion image
notion image
notion image
 
 

Chainlink API Calls

function requestVolumeData() public returns (bytes32 requestId) { Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfill.selector); // Set the URL to perform the GET request on req.add('get', 'https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD'); // Set the path to find the desired data in the API response, where the response format is: // {"RAW": // {"ETH": // {"USD": // { // "VOLUME24HOUR": xxx.xxx, // } // } // } // } // request.add("path", "RAW.ETH.USD.VOLUME24HOUR"); // Chainlink nodes prior to 1.0.0 support this format req.add('path', 'RAW,ETH,USD,VOLUME24HOUR'); // Chainlink nodes 1.0.0 and later support this format // Multiply the result by 1000000000000000000 to remove decimals int256 timesAmount = 10**18; req.addInt('times', timesAmount); // Sends the request return sendChainlinkRequest(req, fee); }
 

Importing Tokens into your Metamask

notion image
 

Request and Receive Chainlink Model

 

Interfaces & Price Feeds

Chainlink Price Feeds (Data Feeds)

// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; contract PriceConsumerV3 { AggregatorV3Interface internal priceFeed; /** * Network: Goerli * Aggregator: ETH/USD * Address: 0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e */ constructor() { priceFeed = AggregatorV3Interface(0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e); } /** * Returns the latest price */ function getLatestPrice() public view returns (int) { ( /*uint80 roundID*/, int price, /*uint startedAt*/, /*uint timeStamp*/, /*uint80 answeredInRound*/ ) = priceFeed.latestRoundData(); return price; } }
 

Chainlink GitHub

 
 

Interface

 
  • cannot have any functions implemented
  • can inherit from other interfaces
  • all declared functions must be external
  • cannot declare a constructor
  • cannot declare state variables
 
interface ICounter { function count() external view returns (uint); function increment() external; }

Importing from GitHub & NPM

Chainlink NPM Package

Installation
# via Yarn $ yarn add @chainlink/contracts # via npm $ npm install @chainlink/contracts --save
 
Directory Structure
@chainlink/contracts ├── src # Solidity contracts │ ├── v0.4 │ ├── v0.5 │ ├── v0.6 │ ├── v0.7 │ └── v0.8 └── abi # ABI json output ├── v0.4 ├── v0.5 ├── v0.6 ├── v0.7 └── v0.8
 
Usage
import '@chainlink/contracts/src/v0.8/KeeperCompatibleInterface.sol';

Floating Point Math in Solidity

tuple

 
  • Gas Estimation Failed
    • Someone should make an article explaining this error

Basic Solidity: Arrays & Structs

 

Libraries

Library

 
 

Solidity-by-example Library

SafeMath, Overflow Checking, and the "unchecked" keyword

Openzeppelin Safemath

unchecked vs. checked

// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; contract C { function f(uint a, uint b) pure public returns (uint) { // This subtraction will wrap on underflow. unchecked { return a - b; } } function g(uint a, uint b) pure public returns (uint) { // This subtraction will revert on underflow. return a - b; } }

Basic Solidity: For Loop

For Loop

function withdraw() public { /* starting index, ending index, step amount */ for(uint256 funderIndex = 0; funderIndex < funders.length; funderIndex++) { address funder = funders[funderIndex]; addressToAmountFunded[funder] = 0; } // reset the array funders = new address[](0); }

Sending ETH from a Contract

Transfer, Send, Call

You can send Ether to other contracts by
  • transfer (2300 gas, throws error)
  • send (2300 gas, returns bool)
  • call (forward all gas or set gas, returns bool)
// transfer payable(msg.sender).transfer(address(this).balance) // send bool sendSuccess = payable(msg.sender).send(address(this).balance); require(sendSuccess, "Send failed"); // call (bool callSuccess, bytes memory dataReturned) = payable(msg.sender).call{value: address(this).balance}("") require(callSuccess, "Call failed");
 
Using call is the recommended way to actually send and receive ethereum or your blockchain native token for now.
 

this keyword

Basic Solidity: Constructor

Constructor

address public owner; constructor() { owner = msg.sender; }

Basic Solidity: Modifiers

Double equals

require(msg.sender == owner, "Sender is not owner!");
 

Modifier

modifier onlyOwner { require(msg.sender == owner, "Sender is not owner!"); _; } function withdraw() public onlyOwner { ... }

Testnet Demo

Disconnecting Metamask

Advanced Solidity

Immutable & Constant

In the solidity there are two keywords that make it so that your variables can’t be changed.
  • Immutable
    • address public i owner; // 21,508 gas - immutable // 23,644 gas - non immutable
  • Constant
    • uint256 public constant MINIMUM_USD = 50 * 1e18; // cost 21,415 gas - constant // cost 23,515 gas - non-constant // 21,415 * 141000000000 = $9. 058545 // 23,515 * 141000000000 = $9.946845
The reason that these two save gas is because instead of storing these variables inside of a storage slot, we actually store them directly into the bite code of the contract.
 
  • Don't stress about gas optimizations! (yet)

Custom Errors

error NotOwner(); modifier onlyOwner { // require(msg.sender == i_ owner, "Sender is not owner!"); if(msg.sender != i_ owner) { revert Notowner(); } _; }
This ends up saving us a lot of gas since we don’t have to store and emit this long string here.
 
We can revert any transaction or any function call in the middle of the function call without the conditional beforehand.
function test() { ... revert(); }

Receive & Fallback Functions

 
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; contract FallbackExample { uint256 public result; receive() external payable() { result = 1; } fallback() external payable() { result = 2; } }
call contract without a valid function, contract refer to fallback function, the value of result updated to 2.
notion image
 
call contract without specifying what you want to do, the value of result updates back to 1.
notion image
 
  • Receive
    • A contract can have at most one receive function, declared using receive( ) external payable ( .... ) (without the funct. ion keyword). This function cannot have arguments, cannot return anything and must have external visibility and payable state mutability. It can be virtual, can override and can have modifiers.
       
      The receive function is executed on a call to the contract with empty calldata. This is the function that is executed on plain Ether transfers (e.g. via f . send() or ,transfer() ). If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer. If neither a receive Ether nor a payable fallback function is present, the contract cannot receive Ether through regular transactions and throws an exception.
      notion image

Copyright © 2025 cyfuer

logo