{
  "slug": "Solidity-principle-06faaeb07b57",
  "title": "Solidity principle",
  "subtitle": "You can connect the Remix into your Ganache in your local machine:",
  "excerpt": "You can connect the Remix into your Ganache in your local machine:",
  "date": "2024-01-09",
  "tags": [],
  "readingTime": "14 min",
  "url": "https://medium.com/@mobinshaterian/solidity-principle-06faaeb07b57",
  "hero": "https://cdn-images-1.medium.com/max/800/1*xSsjDC-nCuUWS6bsfetcRQ.png",
  "content": [
    {
      "type": "heading",
      "level": 2,
      "text": "Solidity for beginner"
    },
    {
      "type": "paragraph",
      "html": "You can connect the Remix into your Ganache in your local machine:"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*xSsjDC-nCuUWS6bsfetcRQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1134,
      "height": 417
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*76RuAUiGH1VOvzZvuDJ2bw.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 312,
      "height": 578
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Solidity compile into byte code and then deploy on network"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*5UOg8sWC-Gwyuj2ulfuTww.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 489,
      "height": 141
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.14;\ncontract MyContract {\n  string public ourString = \"Hello World\";\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Sample code of writing solidity"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.13;\ncontract MyContract {\n  string public myString = \"Hello world\";\n  function updateOurString(string memory _myString) public {\n    myString = _myString;\n  }\n}"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*aw1gt5s1qts-cafReTdOOg.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 293,
      "height": 501
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*7zCECS5bjLFfScOj3GXpSQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1045,
      "height": 413
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*c-49s5t9EldkqNYM8gCvPw.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1143,
      "height": 281
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*GNQwloTLVMpXkl6LGfZpEA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1051,
      "height": 435
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*Jec5vIm5HCddJclSEEEecw.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1137,
      "height": 349
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Variables in solidity"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "uint is similar tor unit256 // 0 - ( 2 ^ 256 ) -1 uint8 uint16int -2^128 to 2 ^ 128 -1"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Be careful about overflow"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Solidity 0.8 unchecked example"
    },
    {
      "type": "paragraph",
      "html": "solidity dosen’t check the underflow and the value will be maximum of uint256"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.15;\ncontract ExampleWrapAround {\n  uint256 public myUint;\n  function decrementUintUnchecked() public {\n    unchecked {\n      myUint--;\n    }\n  }\n  function decrementUint() public {\n    myUint--;\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Check two string in solidity"
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "function compareTwoStrings(string memory _myString) public view returns(bool) {\n  return keccak256(abi.encodePacked(myString)) == keccak256(abi.encodePacked(_myString));\n}"
    },
    {
      "type": "paragraph",
      "html": "bytes can concert into string"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Address type"
    },
    {
      "type": "paragraph",
      "html": "Default value is 0x00000000000000000 (14 zeros)"
    },
    {
      "type": "paragraph",
      "html": "Address has a balance"
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "function getAddressBalance() public view returns(uint) {\n  return someAddress.balance;\n}"
    },
    {
      "type": "paragraph",
      "html": "1 ETH = 10¹⁸ wei"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Account of message sender"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "msg.sender  //is address of account"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "View or Pure"
    },
    {
      "type": "paragraph",
      "html": "View function can access global variable in contract and can’t write them. Pure function can’t call golbal variable. Cost of these function is nothing."
    },
    {
      "type": "paragraph",
      "html": "we can’t get or return value when writing value."
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.15;\ncontract ExampleViewPure {\n  uint public myStorageVariable;\n  function getMyStorageVariable() public view returns(uint) {\n    return myStorageVariable;\n  }\n  function getAddition(uint a, uint b) public pure returns(uint) {\n    return a+b;\n  }\n  function setMyStorageVariable(uint _newVar) public returns(uint) {\n    myStorageVariable = _newVar;\n    return _newVar;\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Constructor"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.15;\ncontract ExampleConstructor {\n  address public myAddress;\n  constructor(address _someAddress) {\n    myAddress = _someAddress;\n  }\n  function setMyAddress(address _myAddress) public {\n    myAddress = _myAddress;\n  }\n  function setMyAddressToMsgSender() public {\n    myAddress = msg.sender;\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Variables"
    },
    {
      "type": "paragraph",
      "html": "All variables has default value, fixed points not implemented yet in solidity."
    },
    {
      "type": "paragraph",
      "html": "String and bytes are expensive."
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "function updateTheMessage(string memory _newMessage) public {\n  if(msg.sender == owner) {\n    theMessage = _newMessage;\n    changeCounter++;\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "List of ETH Testnet Faucets"
    },
    {
      "type": "paragraph",
      "html": "Sometimes Faucets don’t work as expected. Unfortunately there is nothing much that I can do about it. It is time intensive to run a faucet and usually it doesn’t pay off economically. Here is a list of Faucets in case the one here doesn’t work, you can probably switch to another one:"
    },
    {
      "type": "paragraph",
      "html": "My current go-to Faucet I really like for all networks: <a href=\"https://faucet.paradigm.xyz/\" target=\"_blank\" rel=\"noreferrer noopener\">https://faucet.paradigm.xyz</a>"
    },
    {
      "type": "paragraph",
      "html": "<em>Ropsten</em>: <a href=\"https://faucet.metamask.io/\" target=\"_blank\" rel=\"noreferrer noopener\">https://faucet.metamask.io</a>"
    },
    {
      "type": "paragraph",
      "html": "<em>Rinkeby</em>: <a href=\"https://faucet.rinkeby.io/\" target=\"_blank\" rel=\"noreferrer noopener\">https://faucet.rinkeby.io</a> <a href=\"https://www.rinkebyfaucet.com/\" target=\"_blank\" rel=\"noreferrer noopener\">https://www.rinkebyfaucet.com</a> <a href=\"https://app.mycrypto.com/faucet\" target=\"_blank\" rel=\"noreferrer noopener\">https://app.mycrypto.com/faucet</a> <a href=\"https://faucets.chain.link/rinkeby\" target=\"_blank\" rel=\"noreferrer noopener\">https://faucets.chain.link/rinkeby</a>"
    },
    {
      "type": "paragraph",
      "html": "<em>Kovan</em>: <a href=\"https://gitter.im/kovan-testnet/faucet\" target=\"_blank\" rel=\"noreferrer noopener\">https://gitter.im/kovan-testnet/faucet</a> basically post your eth address in the gitter chat"
    },
    {
      "type": "paragraph",
      "html": "<em>Görli</em>: <a href=\"https://goerli-faucet.slock.it/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">https://goerli-faucet.slock.it/index.html</a> <a href=\"https://faucet.goerli.mudit.blog/\" target=\"_blank\" rel=\"noreferrer noopener\">https://faucet.goerli.mudit.blog</a>"
    },
    {
      "type": "paragraph",
      "html": "Another “special edition” Faucet is maintained by Keir “Blockchain-Gandalf” Finlow-Bates, who also wrote a great book about Blockchains. He tries to maintain it as good as possible and it outputs Ropsten Ether: <a href=\"https://moonborrow.com/\" target=\"_blank\" rel=\"noreferrer noopener\">https://moonborrow.com</a>"
    },
    {
      "type": "paragraph",
      "html": "<em>Kintsugi (Eth2.0)</em>: <a href=\"https://kintsugi.themerge.dev/\" target=\"_blank\" rel=\"noreferrer noopener\">https://kintsugi.themerge.dev</a>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Blockchain nodes"
    },
    {
      "type": "paragraph",
      "html": "Blockchain nodes are the <strong>moderators that build the infrastructure of a decentralized network</strong>. Their primary function is to maintain the public ledger’s consensus, which varies according to the type of node. The architecture and design requirements of a particular blockchain protocol determine the types of nodes."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "What is a Ethereum transaction?"
    },
    {
      "type": "paragraph",
      "html": "Transactions are cryptographically signed instructions from accounts. An account will initiate a transaction to update the state of the Ethereum network. The simplest transaction is transferring ETH from one account to another."
    },
    {
      "type": "paragraph",
      "html": "An Ethereum transaction refers to an action initiated by an externally-owned account, in other words an account managed by a human, not a contract. For example, if Bob sends Alice 1 ETH, Bob’s account must be debited and Alice’s must be credited. This state-changing action takes place within a transaction."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*8SKD1N58bRiCs1UNVgPuaA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 659,
      "height": 236
    },
    {
      "type": "heading",
      "level": 2,
      "text": "What is the Input Data Format for Ethereum Transaction?"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://www.doubloin.com/learn/how-ethereum-transactions-work\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Ethereum’s transaction</strong></a> input data format refers to the information that is included in a transaction when interacting with the Ethereum blockchain. It can contain various parameters and instructions for executing smart contracts, transferring tokens, or any other operation supported by the <a href=\"https://www.doubloin.com/learn/what-is-ethereum\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Ethereum network</strong></a>."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "ETH.Build"
    },
    {
      "type": "embed",
      "provider": "youtube",
      "url": "https://www.youtube.com/embed/30pa790tIIA?list=PLJz1HruEnenCXH7KW7wBCEBnBLOVkiqIi"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "ethereum sign transaction"
    },
    {
      "type": "paragraph",
      "html": "To sign a transaction in Ethereum, the originator must: Create a transaction data structure, containing nine fields: nonce, gasPrice, gasLimit, to, value, data, chainID, 0, 0. Produce an RLP-encoded serialized message of the transaction data structure. Compute the Keccak-256 hash of this serialized message."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Elliptic curve digitial signature algorithm"
    },
    {
      "type": "paragraph",
      "html": "The Elliptic Curve Digital Signature Algorithm (ECDSA) is <strong>a Digital Signature Algorithm (DSA) which uses keys derived from elliptic curve cryptography (ECC)</strong>. It is a particularly efficient equation based on public key cryptography (PKC)."
    },
    {
      "type": "embed",
      "provider": "youtube",
      "url": "https://www.youtube.com/embed/f9eitAS1nsY?feature=oembed"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "{    messageHash: '0x6893a6ee8df79b0f5d64a180cd1ef35d030f3e296a5361cf04d02ce720d32ec5',    r:\n'0x9ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9c',    s:\n'0x440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428',    v: '0x25',\nrawTransaction:\n'0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'    transactionHash: '0xd8f64a42b57be0d565f385378db2f6bf324ce14a594afc05de90436e9ce01f60'}"
    },
    {
      "type": "paragraph",
      "html": "Public key has been made by private key."
    },
    {
      "type": "paragraph",
      "html": "In each write on blockchain transaction private key is used."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "‍‍‍Cryptographic hashing"
    },
    {
      "type": "paragraph",
      "html": "What is a digest in cryptography?"
    },
    {
      "type": "paragraph",
      "html": "A message digest is <strong>a fixed size numeric representation of the contents of a message, computed by a hash function</strong>. A message digest can be encrypted, forming a digital signature. Messages are inherently variable in size. A message digest is a fixed size numeric representation of the contents of a message."
    },
    {
      "type": "paragraph",
      "html": "The digest is the output of the hash function."
    },
    {
      "type": "paragraph",
      "html": "For example, sha256 has a digest of 256 bits, i.e. its digest has a length of 32 bytes."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "SHA256"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Ethereum keccak256"
    },
    {
      "type": "paragraph",
      "html": "SHA-256 stems from the SHA-2 standard with a 256 bit key, while Keccak-256 is a function within Solidity and stems from the SHA-3 family. <strong>Keccak-256 is stronger than SHA-256</strong>. SHA-256 generates a SHA-256 hash, while Keccak-256 generates a Keccak-256 hash."
    },
    {
      "type": "paragraph",
      "html": "The hash function has different results if a single character has changed in the blockchain."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Update transaction in Ethereum"
    },
    {
      "type": "paragraph",
      "html": "Increase volume of gas fee without change a nonce."
    },
    {
      "type": "heading",
      "level": 3,
      "text": "“Replacing” vs “Canceling” Transactions"
    },
    {
      "type": "list",
      "ordered": false,
      "items": [
        "<strong>Canceling:</strong> This is when you want to ‘undo’ your transaction. You don’t want it to go through, so you generate a <code>0 ETH</code> transaction to your own address with the purpose of preventing a previous transaction from “going through” / “being mined” / being included in the blockchain.",
        "<strong>Replacing:</strong> This is when you want your same transaction to go through faster, or you want to replace it with another transaction. You generate a <code>XX ETH</code> transaction to someone else’s address with the purpose of doing something (i.e. sending funds, revealing an ENS bid, etc.) while simultaneously not having a previous transaction go through."
      ]
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://help.myetherwallet.com/en/articles/5461454-canceling-or-replacing-a-transaction-after-it-s-been-sent\" target=\"_blank\" rel=\"noreferrer noopener\">https://help.myetherwallet.com/en/articles/5461454-canceling-or-replacing-a-transaction-after-it-s-been-sent</a>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Pending transactions"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*czY25_cYqRnvsqPPYLWN1Q.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1204,
      "height": 298
    },
    {
      "type": "paragraph",
      "html": "Send transaction to your address with the <strong>same nonce</strong> it will cancel it."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*tqqdpIGsWmZrT1iiHkzPuQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 769,
      "height": 56
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*WEHjnFIDdznPbS0FGJK72g.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 305,
      "height": 523
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*LOOjWNs--hDSdVQ5xVIKdA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1063,
      "height": 500
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*RKtbbEa9oVg82b4VOaIZhA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1061,
      "height": 274
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*Pffr3EzLlivwzPAc1lr41g.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 834,
      "height": 203
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Payable function solidity"
    },
    {
      "type": "paragraph",
      "html": "In Solidity, a payable function is <strong>a function that can accept ether as an input</strong>. When a contract is called with a payable function, the caller can send ether along with the function call. The ether is then stored in the contract’s balance, which can be accessed using the “address(this). balance” property."
    },
    {
      "type": "paragraph",
      "html": "msg.value =&gt; value that send to smart contract"
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "function updateString(string memory _newString) public payable {\n  if(msg.value == 1 ether) {\n    myString = _newString;\n  }\n  else {\n    payable(msg.sender).transfer(msg.value);\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Fallback function"
    },
    {
      "type": "paragraph",
      "html": "In the Solidity programming language, a fallback function is <strong>a special type of function that is automatically called whenever a contract receives a message that is not handled by any of the contract’s other functions</strong>. The fallback function is defined using the fallback keyword, and it does not take any arguments."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*btuqjHnDCtN60ED3QHJbHA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 350,
      "height": 132
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "receive() external payable {        lastValueSent = msg.value;        lastFunctionCalled =\n\"receive\";    }"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Smart contract Wallet"
    },
    {
      "type": "paragraph",
      "html": "Send value to the smart contract wallet and withdraw in different account"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.16;\ncontract SendWithdrawMoney {\n  uint public balanceReceived;\n  function deposit() public payable {\n    balanceReceived += msg.value;\n  }\n  function getContractBalance() public view returns(uint) {\n    return address(this).balance;\n  }\n  function withdrawAll() public {\n    address payable to = payable(msg.sender);\n    to.transfer(getContractBalance());\n  }\n  function withdrawToAddress(address payable to) public {\n    to.transfer(getContractBalance());\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Mapping and struct in solidity"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity ^0.8.14;\ncontract SimpleMappingExample {\n  mapping(uint => bool) public myMapping;\n  mapping(address => bool) public myAddressMapping;\n  function setValue(uint _index) public {\n    myMapping[_index] = true;\n  }\n  function setMyAddressToTrue() public {\n    myAddressMapping[msg.sender] = true;\n  }\n}"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "mapping (uint => mapping(uint => bool)) uintUintBoolMapping;"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Child Smart Contract"
    },
    {
      "type": "paragraph",
      "html": "This method costs more than the Struct way."
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.15;\ncontract PaymentReceived {\n  address public from;\n  uint public amount;\n  constructor(address _from, uint _amount) {\n    from = _from;\n    amount = _amount;\n  }\n}\ncontract Wallet {\n  PaymentReceived public payment;\n  function payContract() public payable {\n    payment = new PaymentReceived(msg.sender, msg.value);\n  }\n}\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Assert"
    },
    {
      "type": "paragraph",
      "html": "It is look like a require. It will show panic opcode."
    },
    {
      "type": "paragraph",
      "html": "The assert function should only be used to test for internal errors, and to check invariants. The require function should be used to ensure valid conditions, such as inputs, or contract state variables are met, or to validate return values from calls to external contracts."
    },
    {
      "type": "paragraph",
      "html": "If the condition evaluates to false, the contract will immediately stop executing and any state changes made so far will be rolled back. Unlike require and revert, assert is not used for checking user inputs or enforcing preconditions. In the above example, the assert checks if the integer has overflowed or not."
    },
    {
      "type": "paragraph",
      "html": "The bigger difference between the two keywords is that assert when the condition is false tends to consume all the remaining gas and reverts all the changes made. In reverse, require when the condition is false refund all the remaining gas fees we offered to pay beyond reverts all the changes."
    },
    {
      "type": "paragraph",
      "html": "Exactly for this last reason, <strong>require is recommended</strong> than assert."
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://stackoverflow.com/questions/71502322/difference-between-assert-and-require\" target=\"_blank\" rel=\"noreferrer noopener\">https://stackoverflow.com/questions/71502322/difference-between-assert-and-require</a>"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "assert(msg.value == uint8(msg.value));"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Does solidity have a for loop?"
    },
    {
      "type": "paragraph",
      "html": "Solidity supports for&nbsp;, while&nbsp;, and do while loops. Don’t write loops that are unbounded as this can hit the gas limit, causing your transaction to fail."
    },
    {
      "type": "paragraph",
      "html": "Yes, the EVM has a problem with unbounded loops. The gas consumed increases with each iteration until it hits the block gasLimit and the function can’t run at all. Consequently, <em>unbounded iteration is an anti-pattern</em>."
    },
    {
      "type": "paragraph",
      "html": "Consider inverting control so the clients call the contract one row at a time. The contract can expose helper functions to return the length of the list, the key (to a mapping) at a row in the list, and the details of a struct stored in a mapping for a given key."
    },
    {
      "type": "paragraph",
      "html": "There are some example implementations over here: <a href=\"https://ethereum.stackexchange.com/questions/13167/are-there-well-solved-and-simple-storage-patterns-for-solidity\" target=\"_blank\" rel=\"noreferrer noopener\">Are there well-solved and simple storage patterns for Solidity?</a>"
    },
    {
      "type": "paragraph",
      "html": "The “Mapped Struct with Index” works as described above."
    },
    {
      "type": "paragraph",
      "html": "Hope it helps."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Try Catch"
    },
    {
      "type": "paragraph",
      "html": "We need another contract to catch the error."
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.14;\ncontract WillThrow {\n  function aFunction() public pure {\n    require(false, \"Error message\");\n  }\n}\ncontract ErrorHandling {\n  event ErrorLogging(string reason);\n  function catchError() public {\n    WillThrow will = new WillThrow();\n    try will.aFunction() {\n      //here we could do something if it works\n    }\n    catch Error(string memory reason) {\n      emit ErrorLogging(reason);\n    }\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "External Function Calls and Low-Level Calls In-Depth"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "In solidity transactions are atomic."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "What is an ‘EOA’ account?"
    },
    {
      "type": "paragraph",
      "html": "This is an <strong>Externally Owned Account</strong>, so your normal Ethereum address, not a wallet contract."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*25q0zUQfG-Ip36zWG66-2g.png",
      "alt": "https://www.oreilly.com/library/view/mastering-blockchain-programming/9781839218262/00403615-d0ec-4c80-94a0-dc1d24fd3246.xhtml",
      "caption": "https://www.oreilly.com/library/view/mastering-blockchain-programming/9781839218262/00403615-d0ec-4c80-94a0-dc1d24fd3246.xhtml",
      "width": 1225,
      "height": 588
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Input transaction data have contract payload data."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "What is Transaction Output and Input in Blockchain Technology?"
    },
    {
      "type": "paragraph",
      "html": "Inputs represent the source of funds being used in a transaction, while outputs indicate where these funds are going."
    },
    {
      "type": "paragraph",
      "html": "Transaction inputs and outputs refer to the transfer of digital assets between different stakeholders in a blockchain network, where inputs represent the sender’s address and outputs indicate the recipient’s address."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Wallet example"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "contract Consume{\n  function getBalance() public view returns (uint) {\n    return address(this).balance;\n  }\n  function deposit() payable public {\n  }\n}"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*gKE2gcn8RsP1VT0D6K3PEQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 284,
      "height": 189
    },
    {
      "type": "paragraph",
      "html": "to =&gt; address of consumer deploy"
    },
    {
      "type": "paragraph",
      "html": "payload =&gt; get from <strong>input</strong> after click on deposite"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Web3.js in Remix"
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "import { deploy } from './web3-lib'(async () => {\n    let accounts = await web3.eth.getAccounts();\n    console.log(\"Accounts: \", accounts);\n    console.log(accounts.length)\n    let balance = await web3.eth.getBalance(accounts[0])\n    console.log(balance)\n    console.log(web3.utils.fromwei(balance , \"eth\"))})();"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "Accounts:\n[\"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4\",\"0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2\",\"0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db\",\"0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB\",\"0x617F2E2fD72FD9D5503197092aC168c91465E7f2\",\"0x17F6AD8Ef982297579C203069C1DbfFE4348c372\",\"0x5c6B0f7Bf3E7ce046039Bd8FABdfD3f9F5021678\",\"0x03C6FcED478cBbC9a4FAB34eF9f40767739D1Ff7\",\"0x1aE0EA34a72D944a8C7603FfB3eC30a6669E454C\",\"0x0A098Eda01Ce92ff4A4CCb7A4fFFb5A43EBC70DC\",\"0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c\",\"0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C\",\"0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB\",\"0x583031D1113aD414F02576BD6afaBfb302140225\",\"0xdD870fA1b7C4700F2BD7f44238821C26f7392148\"] 15100000000000000000000"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "ABI"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.14;\ncontract MyContract {\n  uint public myUint = 123;\n  function setMyUint(uint newUint) public {\n    myUint = newUint;\n  }\n}"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*7M9DBZayGTpEQXLaV8QS0w.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 265,
      "height": 398
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*G_BdhOxG1aOr9hA2sM5RXQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 319,
      "height": 485
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*7PEuM15cNm8M1a0WXpidHQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 309,
      "height": 334
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "import { deploy } from './web3-lib'(async() => {\n    const address = \"0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8\";\n    const abi = [ {  \"inputs\": [],  \"name\": \"myUint\",  \"outputs\": [   {\n    \"internalType\": \"uint256\",\n    \"name\": \"\",\n    \"type\": \"uint256\"   }  ],  \"stateMutability\": \"view\",  \"type\": \"function\" }, {  \"inputs\": [   {\n    \"internalType\": \"uint256\",\n    \"name\": \"newUint\",\n    \"type\": \"uint256\"   }  ],  \"name\": \"setMyUint\",  \"outputs\": [],  \"stateMutability\":\n    \"nonpayable\",  \"type\": \"function\" }];\n    let contractInstance = new web3.eth.Contract(abi, address);\n    console.log(await contractInstance.methods.myUint().call());\n    let accounts = await web3.eth.getAccounts();\n    await contractInstance.methods.setMyUint(345).send({from: accounts[0]});\n    console.log(await contractInstance.methods.myUint().call());})()"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Event"
    },
    {
      "type": "paragraph",
      "html": "When write on blockchain&nbsp;, returns value didn’t work on real network and it only use when another contract call this function."
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "event TokensSent(address _from, address _to, uint _amount);"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "emit TokensSent(msg.sender, _to, _amount);"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*IRj_88HdYevuOVYuY9UPLA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1360,
      "height": 369
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.16;\ncontract EventExample {\n  mapping(address => uint) public tokenBalance;\n  event TokensSent(address _from, address _to, uint _amount);\n  constructor() {\n    tokenBalance[msg.sender] = 100;\n  }\n  function sendToken(address _to, uint _amount) public returns(bool) {\n    require(tokenBalance[msg.sender] >= _amount, \"Not enough tokens\");\n    tokenBalance[msg.sender] -= _amount;\n    tokenBalance[_to] += _amount;\n    emit TokensSent(msg.sender, _to, _amount);\n    return true;\n  }\n  receive() external payable {\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Inheritance and Modifiers"
    },
    {
      "type": "paragraph",
      "html": "‍‍‍"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity ^0.8.16;\ncontract InheritanceModifierExample {\n  mapping(address => uint) public tokenBalance;\n  address owner;\n  uint tokenPrice = 1 ether;\n  constructor() {\n    owner = msg.sender;\n    tokenBalance[owner] = 100;\n  }\n  function createNewToken() public {\n    require(msg.sender == owner, \"You are not allowed\");\n    tokenBalance[owner]++;\n  }\n  function burnToken() public {\n    require(msg.sender == owner, \"You are not allowed\");\n    tokenBalance[owner]--;\n  }\n  function purchaseToken() public payable {\n    require((tokenBalance[owner] * tokenPrice) / msg.value > 0, \"not enough tokens\");\n    tokenBalance[owner] -= msg.value / tokenPrice;\n    tokenBalance[msg.sender] += msg.value / tokenPrice;\n  }\n  function sendToken(address _to, uint _amount) public {\n    require(tokenBalance[msg.sender] >= _amount, \"Not enough tokens\");\n    tokenBalance[msg.sender] -= _amount;\n    tokenBalance[_to] += _amount;\n  }\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Adding A Simple Solidity Modifier"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "modifier onlyOwner() {        require(msg.sender == owner, \"You are not allowed\");        _;    }"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Inhertiance"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "contract Owned {    address owner;    constructor() {        owner = msg.sender;    }    modifier\nonlyOwner() {        require(msg.sender == owner, \"You are not allowed\");        _;    }}"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "contract InheritanceModifierExample is Owned {"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Importing Solidity Contracts"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "Did you know? In Remix you can also directly import contracts from github repositories"
    },
    {
      "type": "code",
      "lang": "go",
      "code": "import \"./Ownable.sol\";"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Destroying Smart Contracts using selfdestruct"
    },
    {
      "type": "paragraph",
      "html": "The <code>selfdestruct</code> function takes one argument, an address. It will burn your eth."
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "function destroySmartContract() public {\n  selfdestruct(payable(msg.sender));\n}"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.16;\ncontract StartStopUpdateExample {\n  receive() external payable {\n  }\n  function destroySmartContract() public {\n    selfdestruct(payable(msg.sender));\n  }\n  function Iamhere() public pure returns (string memory) {\n    return \"I am here\";\n  }\n}"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*HrUZknPnyDP-fwCeb8DjfQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 309,
      "height": 277
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://www.youtube.com/watch?v=IMSmEAYGTp4\" target=\"_blank\" rel=\"noreferrer noopener\">https://www.youtube.com/watch?v=IMSmEAYGTp4</a>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "How to Verify A Smart Contract manually on Etherscan"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "//SPDX-License-Identifier: MITpragma solidity 0.8.16;\ncontract MyContract {\n  mapping(address => uint) public balance;\n  constructor() {\n    balance[msg.sender] = 100;\n  }\n  function transfer(address to, uint amount) public {\n    balance[msg.sender] -= amount;\n    balance[to] += amount;\n  }\n  function someCrypticFunctionName(address _addr) public view returns(uint) {\n    return balance[_addr];\n  }\n}"
    },
    {
      "type": "paragraph",
      "html": "Sometimes Etherscan infers a function name. That is, for interfaces from known contracts, like the ERC20 contract. If you interact with this smart contract and use the transfer function, Etherscan would <em>probably</em> show you correctly that the function “transfer” was used. But if you use the function <code>someCrypticFunctionName</code> it would just show you the 4 byte hashed function signature."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*gXc-9a35q2nDRwT2JkEWlw.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1054,
      "height": 281
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*0fhmkAm18A9BHL4fkjRMvQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 918,
      "height": 484
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*03SxNbYKpwcuMQEJQKA3Ww.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 1013,
      "height": 608
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://goerli.etherscan.io/address/0x2efa0b77f4850797f91e5ec1e30b0eec59fa7863#readContract\" target=\"_blank\" rel=\"noreferrer noopener\">https://goerli.etherscan.io/address/0x2efa0b77f4850797f91e5ec1e30b0eec59fa7863#readContract</a>"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*f9fKL06Akejgip88vgPhlA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 788,
      "height": 530
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*PKe1n2Odyc8Aab7tFNLCcA.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 550,
      "height": 447
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Ethereum Request for Comment ERC"
    },
    {
      "type": "paragraph",
      "html": "ERC20 exist on etherium. token has been made by smart contracts."
    },
    {
      "type": "paragraph",
      "html": "ERC20 is a guide line for build your own token."
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://www.youtube.com/watch?v=cqZhNzZoMh8\" target=\"_blank\" rel=\"noreferrer noopener\">https://www.youtube.com/watch?v=cqZhNzZoMh8</a>"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "list of ERC20 tokens"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://bloxy.info/list_tokens/ERC20\" target=\"_blank\" rel=\"noreferrer noopener\">https://bloxy.info/list_tokens/ERC20</a>"
    },
    {
      "type": "paragraph",
      "html": "ERC-223 token is the expansion of the <a href=\"https://www.bitdegree.org/crypto/learn/crypto-terms/what-is-erc-20\" target=\"_blank\" rel=\"noreferrer noopener\">ERC-20 protocol</a>. It was developed by an Ethereum community member known by the Reddit username “Dexaran” to fix a bug in ERC-20 tokens. ERC-223 tokens are powered by <a href=\"https://www.bitdegree.org/crypto/learn/crypto-terms/what-is-smart-contract\" target=\"_blank\" rel=\"noreferrer noopener\">smart contracts</a>. They allow users to transfer their tokens into <a href=\"https://www.bitdegree.org/crypto/learn/crypto-terms/what-is-wallet\" target=\"_blank\" rel=\"noreferrer noopener\">digital wallets</a> securely."
    },
    {
      "type": "paragraph",
      "html": "What’s a fungible token? That is, where each token doesn’t have any sort of unique serial number and they are all worth equally much. Like Euro or Dollar coins. You take out the coins in your pocket and 50 cents are 50 cents, doesn’t matter if the coin is old and used or new and shiny."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "ERC20 Basic contract"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "// SPDX-License-Identifier: MITpragma solidity ^0.8.4;\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\ncontract MyToken is ERC20 {\n  constructor() ERC20(\"MyToken\", \"MYT\") {\n  }\n}"
    },
    {
      "type": "paragraph",
      "html": "There are two large groups of implementations for tokens:"
    },
    {
      "type": "list",
      "ordered": true,
      "items": [
        "Fixed Supply Tokens",
        "Variable Supply Tokens"
      ]
    },
    {
      "type": "paragraph",
      "html": "The difference is mainly in how the mint functionality is used. If you use OpenZeppelin smart contracts, then with fixed supply, the mint function is callable only in the constructor once. That means, once the token is deployed, there is no more access for the internal mint functionality, the supply of tokens remains fixed."
    },
    {
      "type": "paragraph",
      "html": "The Variable Supply Tokens implement some sort of functionality, so that its possible to mint more tokens after the contract is deployed."
    },
    {
      "type": "paragraph",
      "html": "You can define roles, such as a MINTER_ROLE or a BURNER_ROLE, which is basically just a keccak256 hash of the role name"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\" target=\"_blank\" rel=\"noreferrer noopener\">https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How</a>"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "// SPDX-License-Identifier: MITpragma solidity ^0.8.4;\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\ncontract MyToken is ERC20, AccessControl {\n  bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n  bytes32 public constant BURNER_ROLE = keccak256(\"BURNER_ROLE\");\n  constructor() ERC20(\"MyToken\", \"MYT\") {\n    _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n    _grantRole(MINTER_ROLE, msg.sender);\n    _grantRole(BURNER_ROLE, msg.sender);\n  }\n  function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {\n    _mint(to, amount);\n  }\n  function burn(address from, uint256 amount) public onlyRole(BURNER_ROLE) {\n    _burn(from, amount);\n  }\n}"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*H3ZAofO8H3BWtAS1nEmVMQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 294,
      "height": 208
    },
    {
      "type": "paragraph",
      "html": "Let’s use a sample contract from OpenZeppelin to deploy a token. This token could represent anything — for example a voucher for coffees."
    },
    {
      "type": "list",
      "ordered": true,
      "items": [
        "We can give users tokens for coffees",
        "The user can spend the coffee token in his own name, or give it to someone else",
        "Coffee tokens get burned when the user gets his coffee."
      ]
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "// SPDX-License-Identifier: MITpragma solidity ^0.8.4;\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\ncontract CoffeeToken is ERC20, AccessControl {\n  bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n  event CoffeePurchased(address indexed receiver, address indexed buyer);\n  constructor() ERC20(\"CoffeeToken\", \"CFE\") {\n    _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n    _grantRole(MINTER_ROLE, msg.sender);\n  }\n  function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {\n    _mint(to, amount);\n  }\n  function buyOneCoffee() public {\n    _burn(_msgSender(), 1);\n    emit CoffeePurchased(_msgSender(), _msgSender());\n  }\n  function buyOneCoffeeFrom(address account) public {\n    _spendAllowance(account, _msgSender(), 1);\n    _burn(account, 1);\n    emit CoffeePurchased(_msgSender(), account);\n  }\n}"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*GybyjG5moTt1cQqphPWZGQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 600,
      "height": 169
    },
    {
      "type": "heading",
      "level": 2,
      "text": "ERC721"
    },
    {
      "type": "paragraph",
      "html": "This contract has a token id for each token."
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://opensea.io/\" target=\"_blank\" rel=\"noreferrer noopener\">https://opensea.io/</a>"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://opensea.io/assets/ethereum/0x5c1a0cc6dadf4d0fb31425461df35ba80fcbc110/3948\" target=\"_blank\" rel=\"noreferrer noopener\">https://opensea.io/assets/ethereum/0x5c1a0cc6dadf4d0fb31425461df35ba80fcbc110/3948</a>"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*4Hy1lg5fsnsv8-Ja6DqgvQ.png",
      "alt": "Solidity principle",
      "caption": "",
      "width": 696,
      "height": 246
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://mint.pixels.online/contracts/0x5c1a0cc6dadf4d0fb31425461df35ba80fcbc110/3948\" target=\"_blank\" rel=\"noreferrer noopener\">https://mint.pixels.online/contracts/0x5c1a0cc6dadf4d0fb31425461df35ba80fcbc110/3948</a>"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://hang.mypinata.cloud/ipfs/QmRJSjDZqQu5yoUbBtMXhLp4T9czmpUmfpBg6ntLzbjMUV/3948.png\" target=\"_blank\" rel=\"noreferrer noopener\">https://hang.mypinata.cloud/ipfs/QmRJSjDZqQu5yoUbBtMXhLp4T9czmpUmfpBg6ntLzbjMUV/3948.png</a>"
    },
    {
      "type": "embed",
      "provider": "youtube",
      "url": "https://www.youtube.com/embed/29k2C1JXyg4?feature=oembed"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://boomland.io/\" target=\"_blank\" rel=\"noreferrer noopener\">https://boomland.io/</a>"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://opensea.io/assets/matic/0x20b807b9af56977ef475c089a0e7977540743560/5208\" target=\"_blank\" rel=\"noreferrer noopener\">https://opensea.io/assets/matic/0x20b807b9af56977ef475c089a0e7977540743560/5208</a>"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://hunt-nft.cdn.boombit.cloud/Recordings/024/024003020003.webm\" target=\"_blank\" rel=\"noreferrer noopener\">https://hunt-nft.cdn.boombit.cloud/Recordings/024/024003020003.webm</a>"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Make NFT"
    },
    {
      "type": "paragraph",
      "html": "Create wizard ERC721"
    },
    {
      "type": "code",
      "lang": "solidity",
      "code": "// SPDX-License-Identifier: MITpragma solidity ^0.8.20;\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\ncontract Mobin is ERC721, ERC721URIStorage, Ownable {\n  uint256 private _nextTokenId;\n  constructor(address initialOwner) ERC721(\"mobin\", \"MOB\") Ownable(initialOwner) {\n  }\n  function _baseURI() internal pure override returns (string memory) {\n    return \"https://mobinshaterian.medium.com\";\n  }\n  function safeMint(address to, string memory uri) public onlyOwner {\n    uint256 tokenId = _nextTokenId++;\n    _safeMint(to, tokenId);\n    _setTokenURI(tokenId, uri);\n  }\n  // The following\n  functions are overrides required by Solidity.function tokenURI(uint256 tokenId) public view\n  override(ERC721, ERC721URIStorage) returns (string memory) {\n    return super.tokenURI(tokenId);\n  }\n  function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721URIStorage)\n  returns (bool) {\n    return super.supportsInterface(interfaceId);\n  }\n}"
    }
  ]
}
