├── 01- Hello World Full Stack dApp on BSC ├── LICENSE ├── README.md ├── build │ └── contracts │ │ ├── HelloWorld.json │ │ └── Migrations.json ├── client │ ├── app.js │ ├── chain-smart-bsc-l.png │ ├── dist │ │ └── bundle.js │ ├── index.css │ └── index.html ├── contracts │ ├── HelloWorld.sol │ └── Migrations.sol ├── migrations │ ├── 1_initial_migration.js │ └── 2_hello_world.js ├── package-lock.json ├── package.json ├── server │ └── main.js ├── test │ └── hello_world.js ├── truffle-config.js ├── webpack.config.js └── yarn.lock ├── 02-BSC-Block-Explorer ├── README.md ├── img │ ├── favicon.ico │ ├── logo.png │ ├── screenshot.png │ ├── screenshot2.png │ └── screenshot3.png ├── index.html ├── js │ └── web3.min.js ├── list.txt └── screenshot.png ├── 03-Using-BlackIDE-for-Deploying-NFTs ├── ERC721_NFT.sol └── README.md ├── 04-Deploying-Smart-Contracts-Using-IDEs ├── README.md ├── chainide.md ├── hardhat.md ├── remixide.md ├── replit.md └── truffle.md ├── 05-Estimate-L2-Transaction-Gas-Cost ├── .DS_Store └── sdk-estimate-gas │ ├── .env │ ├── Greeter.json │ ├── README.md │ ├── gas.js │ ├── package.json │ └── yarn.lock ├── README.md ├── greenfield-website-hosting ├── .DS_Store ├── index.html ├── plato.jpeg └── styles.css └── upload-folder.sh /01- Hello World Full Stack dApp on BSC/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Truffle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/README.md: -------------------------------------------------------------------------------- 1 | # BSC Hello World Tutorial 2 | 3 | ## Overview 4 | An easy-to-understand tutorial for newbies to develop smart contact on BNB Smart Chain. In this tutorial, we provide a step-by-step guide on how to develop a full-stack Hello World Smart dApp that is used for storing and retrieving data from the BSC blockchain. The technology stack used includes Solidity, Truffle, Ganache, Web3.js, and Node js. This smart contract is then deployed on the BNB Smart Chain Testnet. 5 | 6 | ## What You Will Learn 7 | Through this tutorial, you will learn 8 | - MetaMask Wallet connectivity to BSC Testnet; 9 | - Smart-contract development; 10 | - Using truffle and ganache for local development and testing; 11 | - Unit testing of smart contracts; 12 | - Deploying smart contracts on BSC Testnet; 13 | - Front-end integration with smart contract using web3.js library; 14 | 15 | ## Target audience 16 | This tutorial aims to provide adequate information to anyone who wants to learn dApp development on BNB Smart Chain. 17 | 18 | ## Prerequisites 19 | - node --version 20 | - v16.13.0 21 | - npm --version 22 | - 8.1.0 23 | - truffle version 24 | - Truffle v5.5.19 (core: 5.5.19) 25 | - Ganache v7.2.0 26 | - Solidity - ^0.8.0 (solc-js) 27 | - Web3.js v1.5.3 28 | - MetaMask Wallet 29 | - 10.16.1 30 | 31 | ## Setup 32 | 33 | 1. **Clone the repository** 34 | ```gh repo clone https://github.com/bnb-chain/bnb-chain-tutorial``` 35 | 2. **Change the current directory** 36 | ```cd 01- Hello World Full Stack dApp on BSC``` 37 | 3. **Install all the dependencies (node modules)** 38 | ```npm install``` 39 | 4. Create a ```.secret``` file with the secret phrase of MetaMask. Refer [here](https://metamask.zendesk.com/hc/en-us/articles/360015290032-How-to-reveal-your-Secret-Recovery-Phrase) for details on how to get MetaMask secret phrase. 40 | 5. **Compile Smart Contracts** 41 | ```truffle compile``` 42 | 6. **Migrate Smart Contracts** 43 | ```truffle migrate --reset --network bscTestnet``` 44 | 7. **Create build** 45 | ```npm run build``` 46 | 8. **Run the application** ```npm run dev``` 47 | 48 | >**Note:** _Make Sure Nothing is Running on localhost:3000_ 49 | 50 | ## npm Error Handling 51 | - If you encounter an error while running on local host, run `npm install --save-dev lite-server` 52 | - then run `npm start` 53 | 54 | - If your current version of Solidity is not compiling your contracts, try running the following steps to clear your cache 55 | - `rm -rf build/` 56 | - `rm -rf .cache/` 57 | ```Reinstall the node module --> ``` 58 | 1. `npm install @truffle/hdwallet-provider` 59 | 2. `rm -rf node_modules` 60 | 3. `npm install` 61 | 4. `npm install -g truffle@latest` 62 | ```Once you do this, make sure `truffle-config.js` solc version is the same as your installed solidity version. check by running `$ truffle version` ``` 63 | 64 | ## Available Scripts 65 | ``` 66 | $ truffle compile 67 | $ truffle migrate 68 | $ truffle test 69 | $ npm run build 70 | $ npm run dev 71 | ``` 72 | 73 | ## Structure 74 | ```sh 75 | HelloWorld. 76 | | .env 77 | | .gitattributes 78 | | LICENSE 79 | | package-lock.json 80 | | package.json 81 | | README.md 82 | | truffle-config.js 83 | | webpack.config.js 84 | | yarn.lock 85 | | 86 | +---build 87 | | \---contracts 88 | | HelloWorld.json 89 | | Migrations.json 90 | | 91 | +---client 92 | | | app.js 93 | | | chain-smart-bsc-l.png 94 | | | index.css 95 | | | index.html 96 | | | 97 | | 98 | +---contracts 99 | | HelloWorld.sol 100 | | Migrations.sol 101 | | 102 | +---migrations 103 | | 1_initial_migration.js 104 | | 2_hello_world.js 105 | | 106 | +---server 107 | | main.js 108 | | 109 | +---test 110 | | .gitkeep 111 | | hello_world.js 112 | | 113 | ``` 114 | 115 | ## How it Works 116 | ### Checklist 117 | - Make sure you have MetaMask installed and logged in on your browser. 118 | - Make sure that your MetaMask wallet is correctly configured to connect to BSC Testnet. Refer to this [guide](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain) for details. 119 | - Create a file named ```.secret```, save your MetaMask Secret Phrase in this file. 120 | - Run the command ```truffle compile``` to compile the smart contracts. 121 | - Run the command ```truffle migrate --reset --network bscTestnet``` to deploy the contract on the BSC Testnet. 122 | - Run the command ```npm run build``` to build the application. 123 | - Run the command ```npm run dev``` to start the application. 124 | 125 | ### How to Use 126 | 1. Open browser and navigate to ```http://localhost:3000/``` 127 | 2. Make sure that your MetaMask wallet is correctly installed and configured to connect to BSC Testnet. Refer to this [guide](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain) for details. 128 | 3. Select your desired account of MetaMask that has BNB Test tokens to perform transactions. 129 | 4. To get test tokens use the [BNB Smart Chain Faucet](https://testnet.binance.org/faucet-smart). 130 | 5. Click on Greet Button to display message, by default its Hello World. 131 | 6. Enter a name in the input field, Click save button to save the name. 132 | 7. Confirm the transaction when MetaMask notification pops up. 133 | 8. Click on Greet Button to display message along with the last name saved with the current account. 134 | 135 | ## Unit Test of Smart Contracts 136 | - Make sure that Ganache is running. This is important because testing is done on the local network. 137 | - From the root directory of the project, open command prompt. 138 | - Run the command ```truffle test``` to run the tests. 139 | 140 | ## Unit Test Coverage 141 | ```sh 142 | Contract: HelloWorld 143 | √ Default message should be hello, world (264ms) 144 | √ Should save name (796ms) 145 | √ Should be default message for other accounts (412ms) 146 | √ Should throw error on empty name (3306ms) 147 | 148 | 149 | 4 passing (5s) 150 | ``` 151 | ## Contact 152 | For more inquiries and conversations, feel free to contact us at our [Discord Channel](https://discord.com/channels/789402563035660308/912296662834241597) 153 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contractName": "Migrations", 3 | "abi": [ 4 | { 5 | "inputs": [], 6 | "name": "last_completed_migration", 7 | "outputs": [ 8 | { 9 | "internalType": "uint256", 10 | "name": "", 11 | "type": "uint256" 12 | } 13 | ], 14 | "stateMutability": "view", 15 | "type": "function" 16 | }, 17 | { 18 | "inputs": [], 19 | "name": "owner", 20 | "outputs": [ 21 | { 22 | "internalType": "address", 23 | "name": "", 24 | "type": "address" 25 | } 26 | ], 27 | "stateMutability": "view", 28 | "type": "function" 29 | }, 30 | { 31 | "inputs": [ 32 | { 33 | "internalType": "uint256", 34 | "name": "completed", 35 | "type": "uint256" 36 | } 37 | ], 38 | "name": "setCompleted", 39 | "outputs": [], 40 | "stateMutability": "nonpayable", 41 | "type": "function" 42 | } 43 | ], 44 | "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"last_completed_migration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"completed\",\"type\":\"uint256\"}],\"name\":\"setCompleted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project:/contracts/Migrations.sol\":\"Migrations\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"project:/contracts/Migrations.sol\":{\"keccak256\":\"0x7eaedbb1a3e4e0f585d9063393872f88ded247ca3c3c3c8492ea18e7629a6411\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a3eb571cee910095df65a06a1c1d3f89187c72a3c184ef87a7538d9aa39ad07\",\"dweb:/ipfs/QmdqR3vrSSGR49qFGZr49Mb39z7dgD6tSzEDoaqtM31o61\"]}},\"version\":1}", 45 | "bytecode": "0x6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005057600080fd5b50610327806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd57614610082575b600080fd5b61004e61009e565b60405161005b9190610179565b60405180910390f35b61006c6100a4565b60405161007991906101d5565b60405180910390f35b61009c60048036038101906100979190610221565b6100c8565b005b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610156576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014d906102d1565b60405180910390fd5b8060018190555050565b6000819050919050565b61017381610160565b82525050565b600060208201905061018e600083018461016a565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101bf82610194565b9050919050565b6101cf816101b4565b82525050565b60006020820190506101ea60008301846101c6565b92915050565b600080fd5b6101fe81610160565b811461020957600080fd5b50565b60008135905061021b816101f5565b92915050565b600060208284031215610237576102366101f0565b5b60006102458482850161020c565b91505092915050565b600082825260208201905092915050565b7f546869732066756e6374696f6e206973207265737472696374656420746f207460008201527f686520636f6e74726163742773206f776e657200000000000000000000000000602082015250565b60006102bb60338361024e565b91506102c68261025f565b604082019050919050565b600060208201905081810360008301526102ea816102ae565b905091905056fea26469706673582212205dca1aff29d0fbb145975f8cd99149315d3897703086ca83bf94fcd2c4fefd0e64736f6c634300080f0033", 46 | "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd57614610082575b600080fd5b61004e61009e565b60405161005b9190610179565b60405180910390f35b61006c6100a4565b60405161007991906101d5565b60405180910390f35b61009c60048036038101906100979190610221565b6100c8565b005b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610156576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014d906102d1565b60405180910390fd5b8060018190555050565b6000819050919050565b61017381610160565b82525050565b600060208201905061018e600083018461016a565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101bf82610194565b9050919050565b6101cf816101b4565b82525050565b60006020820190506101ea60008301846101c6565b92915050565b600080fd5b6101fe81610160565b811461020957600080fd5b50565b60008135905061021b816101f5565b92915050565b600060208284031215610237576102366101f0565b5b60006102458482850161020c565b91505092915050565b600082825260208201905092915050565b7f546869732066756e6374696f6e206973207265737472696374656420746f207460008201527f686520636f6e74726163742773206f776e657200000000000000000000000000602082015250565b60006102bb60338361024e565b91506102c68261025f565b604082019050919050565b600060208201905081810360008301526102ea816102ae565b905091905056fea26469706673582212205dca1aff29d0fbb145975f8cd99149315d3897703086ca83bf94fcd2c4fefd0e64736f6c634300080f0033", 47 | "immutableReferences": {}, 48 | "generatedSources": [], 49 | "deployedGeneratedSources": [ 50 | { 51 | "ast": { 52 | "nodeType": "YulBlock", 53 | "src": "0:3176:2", 54 | "statements": [ 55 | { 56 | "body": { 57 | "nodeType": "YulBlock", 58 | "src": "52:32:2", 59 | "statements": [ 60 | { 61 | "nodeType": "YulAssignment", 62 | "src": "62:16:2", 63 | "value": { 64 | "name": "value", 65 | "nodeType": "YulIdentifier", 66 | "src": "73:5:2" 67 | }, 68 | "variableNames": [ 69 | { 70 | "name": "cleaned", 71 | "nodeType": "YulIdentifier", 72 | "src": "62:7:2" 73 | } 74 | ] 75 | } 76 | ] 77 | }, 78 | "name": "cleanup_t_uint256", 79 | "nodeType": "YulFunctionDefinition", 80 | "parameters": [ 81 | { 82 | "name": "value", 83 | "nodeType": "YulTypedName", 84 | "src": "34:5:2", 85 | "type": "" 86 | } 87 | ], 88 | "returnVariables": [ 89 | { 90 | "name": "cleaned", 91 | "nodeType": "YulTypedName", 92 | "src": "44:7:2", 93 | "type": "" 94 | } 95 | ], 96 | "src": "7:77:2" 97 | }, 98 | { 99 | "body": { 100 | "nodeType": "YulBlock", 101 | "src": "155:53:2", 102 | "statements": [ 103 | { 104 | "expression": { 105 | "arguments": [ 106 | { 107 | "name": "pos", 108 | "nodeType": "YulIdentifier", 109 | "src": "172:3:2" 110 | }, 111 | { 112 | "arguments": [ 113 | { 114 | "name": "value", 115 | "nodeType": "YulIdentifier", 116 | "src": "195:5:2" 117 | } 118 | ], 119 | "functionName": { 120 | "name": "cleanup_t_uint256", 121 | "nodeType": "YulIdentifier", 122 | "src": "177:17:2" 123 | }, 124 | "nodeType": "YulFunctionCall", 125 | "src": "177:24:2" 126 | } 127 | ], 128 | "functionName": { 129 | "name": "mstore", 130 | "nodeType": "YulIdentifier", 131 | "src": "165:6:2" 132 | }, 133 | "nodeType": "YulFunctionCall", 134 | "src": "165:37:2" 135 | }, 136 | "nodeType": "YulExpressionStatement", 137 | "src": "165:37:2" 138 | } 139 | ] 140 | }, 141 | "name": "abi_encode_t_uint256_to_t_uint256_fromStack", 142 | "nodeType": "YulFunctionDefinition", 143 | "parameters": [ 144 | { 145 | "name": "value", 146 | "nodeType": "YulTypedName", 147 | "src": "143:5:2", 148 | "type": "" 149 | }, 150 | { 151 | "name": "pos", 152 | "nodeType": "YulTypedName", 153 | "src": "150:3:2", 154 | "type": "" 155 | } 156 | ], 157 | "src": "90:118:2" 158 | }, 159 | { 160 | "body": { 161 | "nodeType": "YulBlock", 162 | "src": "312:124:2", 163 | "statements": [ 164 | { 165 | "nodeType": "YulAssignment", 166 | "src": "322:26:2", 167 | "value": { 168 | "arguments": [ 169 | { 170 | "name": "headStart", 171 | "nodeType": "YulIdentifier", 172 | "src": "334:9:2" 173 | }, 174 | { 175 | "kind": "number", 176 | "nodeType": "YulLiteral", 177 | "src": "345:2:2", 178 | "type": "", 179 | "value": "32" 180 | } 181 | ], 182 | "functionName": { 183 | "name": "add", 184 | "nodeType": "YulIdentifier", 185 | "src": "330:3:2" 186 | }, 187 | "nodeType": "YulFunctionCall", 188 | "src": "330:18:2" 189 | }, 190 | "variableNames": [ 191 | { 192 | "name": "tail", 193 | "nodeType": "YulIdentifier", 194 | "src": "322:4:2" 195 | } 196 | ] 197 | }, 198 | { 199 | "expression": { 200 | "arguments": [ 201 | { 202 | "name": "value0", 203 | "nodeType": "YulIdentifier", 204 | "src": "402:6:2" 205 | }, 206 | { 207 | "arguments": [ 208 | { 209 | "name": "headStart", 210 | "nodeType": "YulIdentifier", 211 | "src": "415:9:2" 212 | }, 213 | { 214 | "kind": "number", 215 | "nodeType": "YulLiteral", 216 | "src": "426:1:2", 217 | "type": "", 218 | "value": "0" 219 | } 220 | ], 221 | "functionName": { 222 | "name": "add", 223 | "nodeType": "YulIdentifier", 224 | "src": "411:3:2" 225 | }, 226 | "nodeType": "YulFunctionCall", 227 | "src": "411:17:2" 228 | } 229 | ], 230 | "functionName": { 231 | "name": "abi_encode_t_uint256_to_t_uint256_fromStack", 232 | "nodeType": "YulIdentifier", 233 | "src": "358:43:2" 234 | }, 235 | "nodeType": "YulFunctionCall", 236 | "src": "358:71:2" 237 | }, 238 | "nodeType": "YulExpressionStatement", 239 | "src": "358:71:2" 240 | } 241 | ] 242 | }, 243 | "name": "abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed", 244 | "nodeType": "YulFunctionDefinition", 245 | "parameters": [ 246 | { 247 | "name": "headStart", 248 | "nodeType": "YulTypedName", 249 | "src": "284:9:2", 250 | "type": "" 251 | }, 252 | { 253 | "name": "value0", 254 | "nodeType": "YulTypedName", 255 | "src": "296:6:2", 256 | "type": "" 257 | } 258 | ], 259 | "returnVariables": [ 260 | { 261 | "name": "tail", 262 | "nodeType": "YulTypedName", 263 | "src": "307:4:2", 264 | "type": "" 265 | } 266 | ], 267 | "src": "214:222:2" 268 | }, 269 | { 270 | "body": { 271 | "nodeType": "YulBlock", 272 | "src": "487:81:2", 273 | "statements": [ 274 | { 275 | "nodeType": "YulAssignment", 276 | "src": "497:65:2", 277 | "value": { 278 | "arguments": [ 279 | { 280 | "name": "value", 281 | "nodeType": "YulIdentifier", 282 | "src": "512:5:2" 283 | }, 284 | { 285 | "kind": "number", 286 | "nodeType": "YulLiteral", 287 | "src": "519:42:2", 288 | "type": "", 289 | "value": "0xffffffffffffffffffffffffffffffffffffffff" 290 | } 291 | ], 292 | "functionName": { 293 | "name": "and", 294 | "nodeType": "YulIdentifier", 295 | "src": "508:3:2" 296 | }, 297 | "nodeType": "YulFunctionCall", 298 | "src": "508:54:2" 299 | }, 300 | "variableNames": [ 301 | { 302 | "name": "cleaned", 303 | "nodeType": "YulIdentifier", 304 | "src": "497:7:2" 305 | } 306 | ] 307 | } 308 | ] 309 | }, 310 | "name": "cleanup_t_uint160", 311 | "nodeType": "YulFunctionDefinition", 312 | "parameters": [ 313 | { 314 | "name": "value", 315 | "nodeType": "YulTypedName", 316 | "src": "469:5:2", 317 | "type": "" 318 | } 319 | ], 320 | "returnVariables": [ 321 | { 322 | "name": "cleaned", 323 | "nodeType": "YulTypedName", 324 | "src": "479:7:2", 325 | "type": "" 326 | } 327 | ], 328 | "src": "442:126:2" 329 | }, 330 | { 331 | "body": { 332 | "nodeType": "YulBlock", 333 | "src": "619:51:2", 334 | "statements": [ 335 | { 336 | "nodeType": "YulAssignment", 337 | "src": "629:35:2", 338 | "value": { 339 | "arguments": [ 340 | { 341 | "name": "value", 342 | "nodeType": "YulIdentifier", 343 | "src": "658:5:2" 344 | } 345 | ], 346 | "functionName": { 347 | "name": "cleanup_t_uint160", 348 | "nodeType": "YulIdentifier", 349 | "src": "640:17:2" 350 | }, 351 | "nodeType": "YulFunctionCall", 352 | "src": "640:24:2" 353 | }, 354 | "variableNames": [ 355 | { 356 | "name": "cleaned", 357 | "nodeType": "YulIdentifier", 358 | "src": "629:7:2" 359 | } 360 | ] 361 | } 362 | ] 363 | }, 364 | "name": "cleanup_t_address", 365 | "nodeType": "YulFunctionDefinition", 366 | "parameters": [ 367 | { 368 | "name": "value", 369 | "nodeType": "YulTypedName", 370 | "src": "601:5:2", 371 | "type": "" 372 | } 373 | ], 374 | "returnVariables": [ 375 | { 376 | "name": "cleaned", 377 | "nodeType": "YulTypedName", 378 | "src": "611:7:2", 379 | "type": "" 380 | } 381 | ], 382 | "src": "574:96:2" 383 | }, 384 | { 385 | "body": { 386 | "nodeType": "YulBlock", 387 | "src": "741:53:2", 388 | "statements": [ 389 | { 390 | "expression": { 391 | "arguments": [ 392 | { 393 | "name": "pos", 394 | "nodeType": "YulIdentifier", 395 | "src": "758:3:2" 396 | }, 397 | { 398 | "arguments": [ 399 | { 400 | "name": "value", 401 | "nodeType": "YulIdentifier", 402 | "src": "781:5:2" 403 | } 404 | ], 405 | "functionName": { 406 | "name": "cleanup_t_address", 407 | "nodeType": "YulIdentifier", 408 | "src": "763:17:2" 409 | }, 410 | "nodeType": "YulFunctionCall", 411 | "src": "763:24:2" 412 | } 413 | ], 414 | "functionName": { 415 | "name": "mstore", 416 | "nodeType": "YulIdentifier", 417 | "src": "751:6:2" 418 | }, 419 | "nodeType": "YulFunctionCall", 420 | "src": "751:37:2" 421 | }, 422 | "nodeType": "YulExpressionStatement", 423 | "src": "751:37:2" 424 | } 425 | ] 426 | }, 427 | "name": "abi_encode_t_address_to_t_address_fromStack", 428 | "nodeType": "YulFunctionDefinition", 429 | "parameters": [ 430 | { 431 | "name": "value", 432 | "nodeType": "YulTypedName", 433 | "src": "729:5:2", 434 | "type": "" 435 | }, 436 | { 437 | "name": "pos", 438 | "nodeType": "YulTypedName", 439 | "src": "736:3:2", 440 | "type": "" 441 | } 442 | ], 443 | "src": "676:118:2" 444 | }, 445 | { 446 | "body": { 447 | "nodeType": "YulBlock", 448 | "src": "898:124:2", 449 | "statements": [ 450 | { 451 | "nodeType": "YulAssignment", 452 | "src": "908:26:2", 453 | "value": { 454 | "arguments": [ 455 | { 456 | "name": "headStart", 457 | "nodeType": "YulIdentifier", 458 | "src": "920:9:2" 459 | }, 460 | { 461 | "kind": "number", 462 | "nodeType": "YulLiteral", 463 | "src": "931:2:2", 464 | "type": "", 465 | "value": "32" 466 | } 467 | ], 468 | "functionName": { 469 | "name": "add", 470 | "nodeType": "YulIdentifier", 471 | "src": "916:3:2" 472 | }, 473 | "nodeType": "YulFunctionCall", 474 | "src": "916:18:2" 475 | }, 476 | "variableNames": [ 477 | { 478 | "name": "tail", 479 | "nodeType": "YulIdentifier", 480 | "src": "908:4:2" 481 | } 482 | ] 483 | }, 484 | { 485 | "expression": { 486 | "arguments": [ 487 | { 488 | "name": "value0", 489 | "nodeType": "YulIdentifier", 490 | "src": "988:6:2" 491 | }, 492 | { 493 | "arguments": [ 494 | { 495 | "name": "headStart", 496 | "nodeType": "YulIdentifier", 497 | "src": "1001:9:2" 498 | }, 499 | { 500 | "kind": "number", 501 | "nodeType": "YulLiteral", 502 | "src": "1012:1:2", 503 | "type": "", 504 | "value": "0" 505 | } 506 | ], 507 | "functionName": { 508 | "name": "add", 509 | "nodeType": "YulIdentifier", 510 | "src": "997:3:2" 511 | }, 512 | "nodeType": "YulFunctionCall", 513 | "src": "997:17:2" 514 | } 515 | ], 516 | "functionName": { 517 | "name": "abi_encode_t_address_to_t_address_fromStack", 518 | "nodeType": "YulIdentifier", 519 | "src": "944:43:2" 520 | }, 521 | "nodeType": "YulFunctionCall", 522 | "src": "944:71:2" 523 | }, 524 | "nodeType": "YulExpressionStatement", 525 | "src": "944:71:2" 526 | } 527 | ] 528 | }, 529 | "name": "abi_encode_tuple_t_address__to_t_address__fromStack_reversed", 530 | "nodeType": "YulFunctionDefinition", 531 | "parameters": [ 532 | { 533 | "name": "headStart", 534 | "nodeType": "YulTypedName", 535 | "src": "870:9:2", 536 | "type": "" 537 | }, 538 | { 539 | "name": "value0", 540 | "nodeType": "YulTypedName", 541 | "src": "882:6:2", 542 | "type": "" 543 | } 544 | ], 545 | "returnVariables": [ 546 | { 547 | "name": "tail", 548 | "nodeType": "YulTypedName", 549 | "src": "893:4:2", 550 | "type": "" 551 | } 552 | ], 553 | "src": "800:222:2" 554 | }, 555 | { 556 | "body": { 557 | "nodeType": "YulBlock", 558 | "src": "1068:35:2", 559 | "statements": [ 560 | { 561 | "nodeType": "YulAssignment", 562 | "src": "1078:19:2", 563 | "value": { 564 | "arguments": [ 565 | { 566 | "kind": "number", 567 | "nodeType": "YulLiteral", 568 | "src": "1094:2:2", 569 | "type": "", 570 | "value": "64" 571 | } 572 | ], 573 | "functionName": { 574 | "name": "mload", 575 | "nodeType": "YulIdentifier", 576 | "src": "1088:5:2" 577 | }, 578 | "nodeType": "YulFunctionCall", 579 | "src": "1088:9:2" 580 | }, 581 | "variableNames": [ 582 | { 583 | "name": "memPtr", 584 | "nodeType": "YulIdentifier", 585 | "src": "1078:6:2" 586 | } 587 | ] 588 | } 589 | ] 590 | }, 591 | "name": "allocate_unbounded", 592 | "nodeType": "YulFunctionDefinition", 593 | "returnVariables": [ 594 | { 595 | "name": "memPtr", 596 | "nodeType": "YulTypedName", 597 | "src": "1061:6:2", 598 | "type": "" 599 | } 600 | ], 601 | "src": "1028:75:2" 602 | }, 603 | { 604 | "body": { 605 | "nodeType": "YulBlock", 606 | "src": "1198:28:2", 607 | "statements": [ 608 | { 609 | "expression": { 610 | "arguments": [ 611 | { 612 | "kind": "number", 613 | "nodeType": "YulLiteral", 614 | "src": "1215:1:2", 615 | "type": "", 616 | "value": "0" 617 | }, 618 | { 619 | "kind": "number", 620 | "nodeType": "YulLiteral", 621 | "src": "1218:1:2", 622 | "type": "", 623 | "value": "0" 624 | } 625 | ], 626 | "functionName": { 627 | "name": "revert", 628 | "nodeType": "YulIdentifier", 629 | "src": "1208:6:2" 630 | }, 631 | "nodeType": "YulFunctionCall", 632 | "src": "1208:12:2" 633 | }, 634 | "nodeType": "YulExpressionStatement", 635 | "src": "1208:12:2" 636 | } 637 | ] 638 | }, 639 | "name": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", 640 | "nodeType": "YulFunctionDefinition", 641 | "src": "1109:117:2" 642 | }, 643 | { 644 | "body": { 645 | "nodeType": "YulBlock", 646 | "src": "1321:28:2", 647 | "statements": [ 648 | { 649 | "expression": { 650 | "arguments": [ 651 | { 652 | "kind": "number", 653 | "nodeType": "YulLiteral", 654 | "src": "1338:1:2", 655 | "type": "", 656 | "value": "0" 657 | }, 658 | { 659 | "kind": "number", 660 | "nodeType": "YulLiteral", 661 | "src": "1341:1:2", 662 | "type": "", 663 | "value": "0" 664 | } 665 | ], 666 | "functionName": { 667 | "name": "revert", 668 | "nodeType": "YulIdentifier", 669 | "src": "1331:6:2" 670 | }, 671 | "nodeType": "YulFunctionCall", 672 | "src": "1331:12:2" 673 | }, 674 | "nodeType": "YulExpressionStatement", 675 | "src": "1331:12:2" 676 | } 677 | ] 678 | }, 679 | "name": "revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db", 680 | "nodeType": "YulFunctionDefinition", 681 | "src": "1232:117:2" 682 | }, 683 | { 684 | "body": { 685 | "nodeType": "YulBlock", 686 | "src": "1398:79:2", 687 | "statements": [ 688 | { 689 | "body": { 690 | "nodeType": "YulBlock", 691 | "src": "1455:16:2", 692 | "statements": [ 693 | { 694 | "expression": { 695 | "arguments": [ 696 | { 697 | "kind": "number", 698 | "nodeType": "YulLiteral", 699 | "src": "1464:1:2", 700 | "type": "", 701 | "value": "0" 702 | }, 703 | { 704 | "kind": "number", 705 | "nodeType": "YulLiteral", 706 | "src": "1467:1:2", 707 | "type": "", 708 | "value": "0" 709 | } 710 | ], 711 | "functionName": { 712 | "name": "revert", 713 | "nodeType": "YulIdentifier", 714 | "src": "1457:6:2" 715 | }, 716 | "nodeType": "YulFunctionCall", 717 | "src": "1457:12:2" 718 | }, 719 | "nodeType": "YulExpressionStatement", 720 | "src": "1457:12:2" 721 | } 722 | ] 723 | }, 724 | "condition": { 725 | "arguments": [ 726 | { 727 | "arguments": [ 728 | { 729 | "name": "value", 730 | "nodeType": "YulIdentifier", 731 | "src": "1421:5:2" 732 | }, 733 | { 734 | "arguments": [ 735 | { 736 | "name": "value", 737 | "nodeType": "YulIdentifier", 738 | "src": "1446:5:2" 739 | } 740 | ], 741 | "functionName": { 742 | "name": "cleanup_t_uint256", 743 | "nodeType": "YulIdentifier", 744 | "src": "1428:17:2" 745 | }, 746 | "nodeType": "YulFunctionCall", 747 | "src": "1428:24:2" 748 | } 749 | ], 750 | "functionName": { 751 | "name": "eq", 752 | "nodeType": "YulIdentifier", 753 | "src": "1418:2:2" 754 | }, 755 | "nodeType": "YulFunctionCall", 756 | "src": "1418:35:2" 757 | } 758 | ], 759 | "functionName": { 760 | "name": "iszero", 761 | "nodeType": "YulIdentifier", 762 | "src": "1411:6:2" 763 | }, 764 | "nodeType": "YulFunctionCall", 765 | "src": "1411:43:2" 766 | }, 767 | "nodeType": "YulIf", 768 | "src": "1408:63:2" 769 | } 770 | ] 771 | }, 772 | "name": "validator_revert_t_uint256", 773 | "nodeType": "YulFunctionDefinition", 774 | "parameters": [ 775 | { 776 | "name": "value", 777 | "nodeType": "YulTypedName", 778 | "src": "1391:5:2", 779 | "type": "" 780 | } 781 | ], 782 | "src": "1355:122:2" 783 | }, 784 | { 785 | "body": { 786 | "nodeType": "YulBlock", 787 | "src": "1535:87:2", 788 | "statements": [ 789 | { 790 | "nodeType": "YulAssignment", 791 | "src": "1545:29:2", 792 | "value": { 793 | "arguments": [ 794 | { 795 | "name": "offset", 796 | "nodeType": "YulIdentifier", 797 | "src": "1567:6:2" 798 | } 799 | ], 800 | "functionName": { 801 | "name": "calldataload", 802 | "nodeType": "YulIdentifier", 803 | "src": "1554:12:2" 804 | }, 805 | "nodeType": "YulFunctionCall", 806 | "src": "1554:20:2" 807 | }, 808 | "variableNames": [ 809 | { 810 | "name": "value", 811 | "nodeType": "YulIdentifier", 812 | "src": "1545:5:2" 813 | } 814 | ] 815 | }, 816 | { 817 | "expression": { 818 | "arguments": [ 819 | { 820 | "name": "value", 821 | "nodeType": "YulIdentifier", 822 | "src": "1610:5:2" 823 | } 824 | ], 825 | "functionName": { 826 | "name": "validator_revert_t_uint256", 827 | "nodeType": "YulIdentifier", 828 | "src": "1583:26:2" 829 | }, 830 | "nodeType": "YulFunctionCall", 831 | "src": "1583:33:2" 832 | }, 833 | "nodeType": "YulExpressionStatement", 834 | "src": "1583:33:2" 835 | } 836 | ] 837 | }, 838 | "name": "abi_decode_t_uint256", 839 | "nodeType": "YulFunctionDefinition", 840 | "parameters": [ 841 | { 842 | "name": "offset", 843 | "nodeType": "YulTypedName", 844 | "src": "1513:6:2", 845 | "type": "" 846 | }, 847 | { 848 | "name": "end", 849 | "nodeType": "YulTypedName", 850 | "src": "1521:3:2", 851 | "type": "" 852 | } 853 | ], 854 | "returnVariables": [ 855 | { 856 | "name": "value", 857 | "nodeType": "YulTypedName", 858 | "src": "1529:5:2", 859 | "type": "" 860 | } 861 | ], 862 | "src": "1483:139:2" 863 | }, 864 | { 865 | "body": { 866 | "nodeType": "YulBlock", 867 | "src": "1694:263:2", 868 | "statements": [ 869 | { 870 | "body": { 871 | "nodeType": "YulBlock", 872 | "src": "1740:83:2", 873 | "statements": [ 874 | { 875 | "expression": { 876 | "arguments": [], 877 | "functionName": { 878 | "name": "revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b", 879 | "nodeType": "YulIdentifier", 880 | "src": "1742:77:2" 881 | }, 882 | "nodeType": "YulFunctionCall", 883 | "src": "1742:79:2" 884 | }, 885 | "nodeType": "YulExpressionStatement", 886 | "src": "1742:79:2" 887 | } 888 | ] 889 | }, 890 | "condition": { 891 | "arguments": [ 892 | { 893 | "arguments": [ 894 | { 895 | "name": "dataEnd", 896 | "nodeType": "YulIdentifier", 897 | "src": "1715:7:2" 898 | }, 899 | { 900 | "name": "headStart", 901 | "nodeType": "YulIdentifier", 902 | "src": "1724:9:2" 903 | } 904 | ], 905 | "functionName": { 906 | "name": "sub", 907 | "nodeType": "YulIdentifier", 908 | "src": "1711:3:2" 909 | }, 910 | "nodeType": "YulFunctionCall", 911 | "src": "1711:23:2" 912 | }, 913 | { 914 | "kind": "number", 915 | "nodeType": "YulLiteral", 916 | "src": "1736:2:2", 917 | "type": "", 918 | "value": "32" 919 | } 920 | ], 921 | "functionName": { 922 | "name": "slt", 923 | "nodeType": "YulIdentifier", 924 | "src": "1707:3:2" 925 | }, 926 | "nodeType": "YulFunctionCall", 927 | "src": "1707:32:2" 928 | }, 929 | "nodeType": "YulIf", 930 | "src": "1704:119:2" 931 | }, 932 | { 933 | "nodeType": "YulBlock", 934 | "src": "1833:117:2", 935 | "statements": [ 936 | { 937 | "nodeType": "YulVariableDeclaration", 938 | "src": "1848:15:2", 939 | "value": { 940 | "kind": "number", 941 | "nodeType": "YulLiteral", 942 | "src": "1862:1:2", 943 | "type": "", 944 | "value": "0" 945 | }, 946 | "variables": [ 947 | { 948 | "name": "offset", 949 | "nodeType": "YulTypedName", 950 | "src": "1852:6:2", 951 | "type": "" 952 | } 953 | ] 954 | }, 955 | { 956 | "nodeType": "YulAssignment", 957 | "src": "1877:63:2", 958 | "value": { 959 | "arguments": [ 960 | { 961 | "arguments": [ 962 | { 963 | "name": "headStart", 964 | "nodeType": "YulIdentifier", 965 | "src": "1912:9:2" 966 | }, 967 | { 968 | "name": "offset", 969 | "nodeType": "YulIdentifier", 970 | "src": "1923:6:2" 971 | } 972 | ], 973 | "functionName": { 974 | "name": "add", 975 | "nodeType": "YulIdentifier", 976 | "src": "1908:3:2" 977 | }, 978 | "nodeType": "YulFunctionCall", 979 | "src": "1908:22:2" 980 | }, 981 | { 982 | "name": "dataEnd", 983 | "nodeType": "YulIdentifier", 984 | "src": "1932:7:2" 985 | } 986 | ], 987 | "functionName": { 988 | "name": "abi_decode_t_uint256", 989 | "nodeType": "YulIdentifier", 990 | "src": "1887:20:2" 991 | }, 992 | "nodeType": "YulFunctionCall", 993 | "src": "1887:53:2" 994 | }, 995 | "variableNames": [ 996 | { 997 | "name": "value0", 998 | "nodeType": "YulIdentifier", 999 | "src": "1877:6:2" 1000 | } 1001 | ] 1002 | } 1003 | ] 1004 | } 1005 | ] 1006 | }, 1007 | "name": "abi_decode_tuple_t_uint256", 1008 | "nodeType": "YulFunctionDefinition", 1009 | "parameters": [ 1010 | { 1011 | "name": "headStart", 1012 | "nodeType": "YulTypedName", 1013 | "src": "1664:9:2", 1014 | "type": "" 1015 | }, 1016 | { 1017 | "name": "dataEnd", 1018 | "nodeType": "YulTypedName", 1019 | "src": "1675:7:2", 1020 | "type": "" 1021 | } 1022 | ], 1023 | "returnVariables": [ 1024 | { 1025 | "name": "value0", 1026 | "nodeType": "YulTypedName", 1027 | "src": "1687:6:2", 1028 | "type": "" 1029 | } 1030 | ], 1031 | "src": "1628:329:2" 1032 | }, 1033 | { 1034 | "body": { 1035 | "nodeType": "YulBlock", 1036 | "src": "2059:73:2", 1037 | "statements": [ 1038 | { 1039 | "expression": { 1040 | "arguments": [ 1041 | { 1042 | "name": "pos", 1043 | "nodeType": "YulIdentifier", 1044 | "src": "2076:3:2" 1045 | }, 1046 | { 1047 | "name": "length", 1048 | "nodeType": "YulIdentifier", 1049 | "src": "2081:6:2" 1050 | } 1051 | ], 1052 | "functionName": { 1053 | "name": "mstore", 1054 | "nodeType": "YulIdentifier", 1055 | "src": "2069:6:2" 1056 | }, 1057 | "nodeType": "YulFunctionCall", 1058 | "src": "2069:19:2" 1059 | }, 1060 | "nodeType": "YulExpressionStatement", 1061 | "src": "2069:19:2" 1062 | }, 1063 | { 1064 | "nodeType": "YulAssignment", 1065 | "src": "2097:29:2", 1066 | "value": { 1067 | "arguments": [ 1068 | { 1069 | "name": "pos", 1070 | "nodeType": "YulIdentifier", 1071 | "src": "2116:3:2" 1072 | }, 1073 | { 1074 | "kind": "number", 1075 | "nodeType": "YulLiteral", 1076 | "src": "2121:4:2", 1077 | "type": "", 1078 | "value": "0x20" 1079 | } 1080 | ], 1081 | "functionName": { 1082 | "name": "add", 1083 | "nodeType": "YulIdentifier", 1084 | "src": "2112:3:2" 1085 | }, 1086 | "nodeType": "YulFunctionCall", 1087 | "src": "2112:14:2" 1088 | }, 1089 | "variableNames": [ 1090 | { 1091 | "name": "updated_pos", 1092 | "nodeType": "YulIdentifier", 1093 | "src": "2097:11:2" 1094 | } 1095 | ] 1096 | } 1097 | ] 1098 | }, 1099 | "name": "array_storeLengthForEncoding_t_string_memory_ptr_fromStack", 1100 | "nodeType": "YulFunctionDefinition", 1101 | "parameters": [ 1102 | { 1103 | "name": "pos", 1104 | "nodeType": "YulTypedName", 1105 | "src": "2031:3:2", 1106 | "type": "" 1107 | }, 1108 | { 1109 | "name": "length", 1110 | "nodeType": "YulTypedName", 1111 | "src": "2036:6:2", 1112 | "type": "" 1113 | } 1114 | ], 1115 | "returnVariables": [ 1116 | { 1117 | "name": "updated_pos", 1118 | "nodeType": "YulTypedName", 1119 | "src": "2047:11:2", 1120 | "type": "" 1121 | } 1122 | ], 1123 | "src": "1963:169:2" 1124 | }, 1125 | { 1126 | "body": { 1127 | "nodeType": "YulBlock", 1128 | "src": "2244:132:2", 1129 | "statements": [ 1130 | { 1131 | "expression": { 1132 | "arguments": [ 1133 | { 1134 | "arguments": [ 1135 | { 1136 | "name": "memPtr", 1137 | "nodeType": "YulIdentifier", 1138 | "src": "2266:6:2" 1139 | }, 1140 | { 1141 | "kind": "number", 1142 | "nodeType": "YulLiteral", 1143 | "src": "2274:1:2", 1144 | "type": "", 1145 | "value": "0" 1146 | } 1147 | ], 1148 | "functionName": { 1149 | "name": "add", 1150 | "nodeType": "YulIdentifier", 1151 | "src": "2262:3:2" 1152 | }, 1153 | "nodeType": "YulFunctionCall", 1154 | "src": "2262:14:2" 1155 | }, 1156 | { 1157 | "hexValue": "546869732066756e6374696f6e206973207265737472696374656420746f2074", 1158 | "kind": "string", 1159 | "nodeType": "YulLiteral", 1160 | "src": "2278:34:2", 1161 | "type": "", 1162 | "value": "This function is restricted to t" 1163 | } 1164 | ], 1165 | "functionName": { 1166 | "name": "mstore", 1167 | "nodeType": "YulIdentifier", 1168 | "src": "2255:6:2" 1169 | }, 1170 | "nodeType": "YulFunctionCall", 1171 | "src": "2255:58:2" 1172 | }, 1173 | "nodeType": "YulExpressionStatement", 1174 | "src": "2255:58:2" 1175 | }, 1176 | { 1177 | "expression": { 1178 | "arguments": [ 1179 | { 1180 | "arguments": [ 1181 | { 1182 | "name": "memPtr", 1183 | "nodeType": "YulIdentifier", 1184 | "src": "2334:6:2" 1185 | }, 1186 | { 1187 | "kind": "number", 1188 | "nodeType": "YulLiteral", 1189 | "src": "2342:2:2", 1190 | "type": "", 1191 | "value": "32" 1192 | } 1193 | ], 1194 | "functionName": { 1195 | "name": "add", 1196 | "nodeType": "YulIdentifier", 1197 | "src": "2330:3:2" 1198 | }, 1199 | "nodeType": "YulFunctionCall", 1200 | "src": "2330:15:2" 1201 | }, 1202 | { 1203 | "hexValue": "686520636f6e74726163742773206f776e6572", 1204 | "kind": "string", 1205 | "nodeType": "YulLiteral", 1206 | "src": "2347:21:2", 1207 | "type": "", 1208 | "value": "he contract's owner" 1209 | } 1210 | ], 1211 | "functionName": { 1212 | "name": "mstore", 1213 | "nodeType": "YulIdentifier", 1214 | "src": "2323:6:2" 1215 | }, 1216 | "nodeType": "YulFunctionCall", 1217 | "src": "2323:46:2" 1218 | }, 1219 | "nodeType": "YulExpressionStatement", 1220 | "src": "2323:46:2" 1221 | } 1222 | ] 1223 | }, 1224 | "name": "store_literal_in_memory_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 1225 | "nodeType": "YulFunctionDefinition", 1226 | "parameters": [ 1227 | { 1228 | "name": "memPtr", 1229 | "nodeType": "YulTypedName", 1230 | "src": "2236:6:2", 1231 | "type": "" 1232 | } 1233 | ], 1234 | "src": "2138:238:2" 1235 | }, 1236 | { 1237 | "body": { 1238 | "nodeType": "YulBlock", 1239 | "src": "2528:220:2", 1240 | "statements": [ 1241 | { 1242 | "nodeType": "YulAssignment", 1243 | "src": "2538:74:2", 1244 | "value": { 1245 | "arguments": [ 1246 | { 1247 | "name": "pos", 1248 | "nodeType": "YulIdentifier", 1249 | "src": "2604:3:2" 1250 | }, 1251 | { 1252 | "kind": "number", 1253 | "nodeType": "YulLiteral", 1254 | "src": "2609:2:2", 1255 | "type": "", 1256 | "value": "51" 1257 | } 1258 | ], 1259 | "functionName": { 1260 | "name": "array_storeLengthForEncoding_t_string_memory_ptr_fromStack", 1261 | "nodeType": "YulIdentifier", 1262 | "src": "2545:58:2" 1263 | }, 1264 | "nodeType": "YulFunctionCall", 1265 | "src": "2545:67:2" 1266 | }, 1267 | "variableNames": [ 1268 | { 1269 | "name": "pos", 1270 | "nodeType": "YulIdentifier", 1271 | "src": "2538:3:2" 1272 | } 1273 | ] 1274 | }, 1275 | { 1276 | "expression": { 1277 | "arguments": [ 1278 | { 1279 | "name": "pos", 1280 | "nodeType": "YulIdentifier", 1281 | "src": "2710:3:2" 1282 | } 1283 | ], 1284 | "functionName": { 1285 | "name": "store_literal_in_memory_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 1286 | "nodeType": "YulIdentifier", 1287 | "src": "2621:88:2" 1288 | }, 1289 | "nodeType": "YulFunctionCall", 1290 | "src": "2621:93:2" 1291 | }, 1292 | "nodeType": "YulExpressionStatement", 1293 | "src": "2621:93:2" 1294 | }, 1295 | { 1296 | "nodeType": "YulAssignment", 1297 | "src": "2723:19:2", 1298 | "value": { 1299 | "arguments": [ 1300 | { 1301 | "name": "pos", 1302 | "nodeType": "YulIdentifier", 1303 | "src": "2734:3:2" 1304 | }, 1305 | { 1306 | "kind": "number", 1307 | "nodeType": "YulLiteral", 1308 | "src": "2739:2:2", 1309 | "type": "", 1310 | "value": "64" 1311 | } 1312 | ], 1313 | "functionName": { 1314 | "name": "add", 1315 | "nodeType": "YulIdentifier", 1316 | "src": "2730:3:2" 1317 | }, 1318 | "nodeType": "YulFunctionCall", 1319 | "src": "2730:12:2" 1320 | }, 1321 | "variableNames": [ 1322 | { 1323 | "name": "end", 1324 | "nodeType": "YulIdentifier", 1325 | "src": "2723:3:2" 1326 | } 1327 | ] 1328 | } 1329 | ] 1330 | }, 1331 | "name": "abi_encode_t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1_to_t_string_memory_ptr_fromStack", 1332 | "nodeType": "YulFunctionDefinition", 1333 | "parameters": [ 1334 | { 1335 | "name": "pos", 1336 | "nodeType": "YulTypedName", 1337 | "src": "2516:3:2", 1338 | "type": "" 1339 | } 1340 | ], 1341 | "returnVariables": [ 1342 | { 1343 | "name": "end", 1344 | "nodeType": "YulTypedName", 1345 | "src": "2524:3:2", 1346 | "type": "" 1347 | } 1348 | ], 1349 | "src": "2382:366:2" 1350 | }, 1351 | { 1352 | "body": { 1353 | "nodeType": "YulBlock", 1354 | "src": "2925:248:2", 1355 | "statements": [ 1356 | { 1357 | "nodeType": "YulAssignment", 1358 | "src": "2935:26:2", 1359 | "value": { 1360 | "arguments": [ 1361 | { 1362 | "name": "headStart", 1363 | "nodeType": "YulIdentifier", 1364 | "src": "2947:9:2" 1365 | }, 1366 | { 1367 | "kind": "number", 1368 | "nodeType": "YulLiteral", 1369 | "src": "2958:2:2", 1370 | "type": "", 1371 | "value": "32" 1372 | } 1373 | ], 1374 | "functionName": { 1375 | "name": "add", 1376 | "nodeType": "YulIdentifier", 1377 | "src": "2943:3:2" 1378 | }, 1379 | "nodeType": "YulFunctionCall", 1380 | "src": "2943:18:2" 1381 | }, 1382 | "variableNames": [ 1383 | { 1384 | "name": "tail", 1385 | "nodeType": "YulIdentifier", 1386 | "src": "2935:4:2" 1387 | } 1388 | ] 1389 | }, 1390 | { 1391 | "expression": { 1392 | "arguments": [ 1393 | { 1394 | "arguments": [ 1395 | { 1396 | "name": "headStart", 1397 | "nodeType": "YulIdentifier", 1398 | "src": "2982:9:2" 1399 | }, 1400 | { 1401 | "kind": "number", 1402 | "nodeType": "YulLiteral", 1403 | "src": "2993:1:2", 1404 | "type": "", 1405 | "value": "0" 1406 | } 1407 | ], 1408 | "functionName": { 1409 | "name": "add", 1410 | "nodeType": "YulIdentifier", 1411 | "src": "2978:3:2" 1412 | }, 1413 | "nodeType": "YulFunctionCall", 1414 | "src": "2978:17:2" 1415 | }, 1416 | { 1417 | "arguments": [ 1418 | { 1419 | "name": "tail", 1420 | "nodeType": "YulIdentifier", 1421 | "src": "3001:4:2" 1422 | }, 1423 | { 1424 | "name": "headStart", 1425 | "nodeType": "YulIdentifier", 1426 | "src": "3007:9:2" 1427 | } 1428 | ], 1429 | "functionName": { 1430 | "name": "sub", 1431 | "nodeType": "YulIdentifier", 1432 | "src": "2997:3:2" 1433 | }, 1434 | "nodeType": "YulFunctionCall", 1435 | "src": "2997:20:2" 1436 | } 1437 | ], 1438 | "functionName": { 1439 | "name": "mstore", 1440 | "nodeType": "YulIdentifier", 1441 | "src": "2971:6:2" 1442 | }, 1443 | "nodeType": "YulFunctionCall", 1444 | "src": "2971:47:2" 1445 | }, 1446 | "nodeType": "YulExpressionStatement", 1447 | "src": "2971:47:2" 1448 | }, 1449 | { 1450 | "nodeType": "YulAssignment", 1451 | "src": "3027:139:2", 1452 | "value": { 1453 | "arguments": [ 1454 | { 1455 | "name": "tail", 1456 | "nodeType": "YulIdentifier", 1457 | "src": "3161:4:2" 1458 | } 1459 | ], 1460 | "functionName": { 1461 | "name": "abi_encode_t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1_to_t_string_memory_ptr_fromStack", 1462 | "nodeType": "YulIdentifier", 1463 | "src": "3035:124:2" 1464 | }, 1465 | "nodeType": "YulFunctionCall", 1466 | "src": "3035:131:2" 1467 | }, 1468 | "variableNames": [ 1469 | { 1470 | "name": "tail", 1471 | "nodeType": "YulIdentifier", 1472 | "src": "3027:4:2" 1473 | } 1474 | ] 1475 | } 1476 | ] 1477 | }, 1478 | "name": "abi_encode_tuple_t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1__to_t_string_memory_ptr__fromStack_reversed", 1479 | "nodeType": "YulFunctionDefinition", 1480 | "parameters": [ 1481 | { 1482 | "name": "headStart", 1483 | "nodeType": "YulTypedName", 1484 | "src": "2905:9:2", 1485 | "type": "" 1486 | } 1487 | ], 1488 | "returnVariables": [ 1489 | { 1490 | "name": "tail", 1491 | "nodeType": "YulTypedName", 1492 | "src": "2920:4:2", 1493 | "type": "" 1494 | } 1495 | ], 1496 | "src": "2754:419:2" 1497 | } 1498 | ] 1499 | }, 1500 | "contents": "{\n\n function cleanup_t_uint256(value) -> cleaned {\n cleaned := value\n }\n\n function abi_encode_t_uint256_to_t_uint256_fromStack(value, pos) {\n mstore(pos, cleanup_t_uint256(value))\n }\n\n function abi_encode_tuple_t_uint256__to_t_uint256__fromStack_reversed(headStart , value0) -> tail {\n tail := add(headStart, 32)\n\n abi_encode_t_uint256_to_t_uint256_fromStack(value0, add(headStart, 0))\n\n }\n\n function cleanup_t_uint160(value) -> cleaned {\n cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff)\n }\n\n function cleanup_t_address(value) -> cleaned {\n cleaned := cleanup_t_uint160(value)\n }\n\n function abi_encode_t_address_to_t_address_fromStack(value, pos) {\n mstore(pos, cleanup_t_address(value))\n }\n\n function abi_encode_tuple_t_address__to_t_address__fromStack_reversed(headStart , value0) -> tail {\n tail := add(headStart, 32)\n\n abi_encode_t_address_to_t_address_fromStack(value0, add(headStart, 0))\n\n }\n\n function allocate_unbounded() -> memPtr {\n memPtr := mload(64)\n }\n\n function revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() {\n revert(0, 0)\n }\n\n function revert_error_c1322bf8034eace5e0b5c7295db60986aa89aae5e0ea0873e4689e076861a5db() {\n revert(0, 0)\n }\n\n function validator_revert_t_uint256(value) {\n if iszero(eq(value, cleanup_t_uint256(value))) { revert(0, 0) }\n }\n\n function abi_decode_t_uint256(offset, end) -> value {\n value := calldataload(offset)\n validator_revert_t_uint256(value)\n }\n\n function abi_decode_tuple_t_uint256(headStart, dataEnd) -> value0 {\n if slt(sub(dataEnd, headStart), 32) { revert_error_dbdddcbe895c83990c08b3492a0e83918d802a52331272ac6fdb6a7c4aea3b1b() }\n\n {\n\n let offset := 0\n\n value0 := abi_decode_t_uint256(add(headStart, offset), dataEnd)\n }\n\n }\n\n function array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, length) -> updated_pos {\n mstore(pos, length)\n updated_pos := add(pos, 0x20)\n }\n\n function store_literal_in_memory_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1(memPtr) {\n\n mstore(add(memPtr, 0), \"This function is restricted to t\")\n\n mstore(add(memPtr, 32), \"he contract's owner\")\n\n }\n\n function abi_encode_t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1_to_t_string_memory_ptr_fromStack(pos) -> end {\n pos := array_storeLengthForEncoding_t_string_memory_ptr_fromStack(pos, 51)\n store_literal_in_memory_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1(pos)\n end := add(pos, 64)\n }\n\n function abi_encode_tuple_t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1__to_t_string_memory_ptr__fromStack_reversed(headStart ) -> tail {\n tail := add(headStart, 32)\n\n mstore(add(headStart, 0), sub(tail, headStart))\n tail := abi_encode_t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1_to_t_string_memory_ptr_fromStack( tail)\n\n }\n\n}\n", 1501 | "id": 2, 1502 | "language": "Yul", 1503 | "name": "#utility.yul" 1504 | } 1505 | ], 1506 | "sourceMap": "66:352:1:-:0;;;113:10;90:33;;;;;;;;;;;;;;;;;;;;66:352;;;;;;;;;;;;;;;;", 1507 | "deployedSourceMap": "66:352:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;127:36;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;90:33;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;313:103;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;127:36;;;;:::o;90:33::-;;;;;;;;;;;;:::o;313:103::-;225:5;;;;;;;;;;211:19;;:10;:19;;;196:101;;;;;;;;;;;;:::i;:::-;;;;;;;;;402:9:::1;375:24;:36;;;;313:103:::0;:::o;7:77:2:-;44:7;73:5;62:16;;7:77;;;:::o;90:118::-;177:24;195:5;177:24;:::i;:::-;172:3;165:37;90:118;;:::o;214:222::-;307:4;345:2;334:9;330:18;322:26;;358:71;426:1;415:9;411:17;402:6;358:71;:::i;:::-;214:222;;;;:::o;442:126::-;479:7;519:42;512:5;508:54;497:65;;442:126;;;:::o;574:96::-;611:7;640:24;658:5;640:24;:::i;:::-;629:35;;574:96;;;:::o;676:118::-;763:24;781:5;763:24;:::i;:::-;758:3;751:37;676:118;;:::o;800:222::-;893:4;931:2;920:9;916:18;908:26;;944:71;1012:1;1001:9;997:17;988:6;944:71;:::i;:::-;800:222;;;;:::o;1109:117::-;1218:1;1215;1208:12;1355:122;1428:24;1446:5;1428:24;:::i;:::-;1421:5;1418:35;1408:63;;1467:1;1464;1457:12;1408:63;1355:122;:::o;1483:139::-;1529:5;1567:6;1554:20;1545:29;;1583:33;1610:5;1583:33;:::i;:::-;1483:139;;;;:::o;1628:329::-;1687:6;1736:2;1724:9;1715:7;1711:23;1707:32;1704:119;;;1742:79;;:::i;:::-;1704:119;1862:1;1887:53;1932:7;1923:6;1912:9;1908:22;1887:53;:::i;:::-;1877:63;;1833:117;1628:329;;;;:::o;1963:169::-;2047:11;2081:6;2076:3;2069:19;2121:4;2116:3;2112:14;2097:29;;1963:169;;;;:::o;2138:238::-;2278:34;2274:1;2266:6;2262:14;2255:58;2347:21;2342:2;2334:6;2330:15;2323:46;2138:238;:::o;2382:366::-;2524:3;2545:67;2609:2;2604:3;2545:67;:::i;:::-;2538:74;;2621:93;2710:3;2621:93;:::i;:::-;2739:2;2734:3;2730:12;2723:19;;2382:366;;;:::o;2754:419::-;2920:4;2958:2;2947:9;2943:18;2935:26;;3007:9;3001:4;2997:20;2993:1;2982:9;2978:17;2971:47;3035:131;3161:4;3035:131;:::i;:::-;3027:139;;2754:419;;;:::o", 1508 | "source": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\ncontract Migrations {\n address public owner = msg.sender;\n uint public last_completed_migration;\n\n modifier restricted() {\n require(\n msg.sender == owner,\n \"This function is restricted to the contract's owner\"\n );\n _;\n }\n\n function setCompleted(uint completed) public restricted {\n last_completed_migration = completed;\n }\n}\n", 1509 | "sourcePath": "F:\\rumeel\\hello-world-dev\\tutorial1\\helloworld\\contracts\\Migrations.sol", 1510 | "ast": { 1511 | "absolutePath": "project:/contracts/Migrations.sol", 1512 | "exportedSymbols": { 1513 | "Migrations": [ 1514 | 207 1515 | ] 1516 | }, 1517 | "id": 208, 1518 | "license": "MIT", 1519 | "nodeType": "SourceUnit", 1520 | "nodes": [ 1521 | { 1522 | "id": 176, 1523 | "literals": [ 1524 | "solidity", 1525 | ">=", 1526 | "0.4", 1527 | ".22", 1528 | "<", 1529 | "0.9", 1530 | ".0" 1531 | ], 1532 | "nodeType": "PragmaDirective", 1533 | "src": "32:32:1" 1534 | }, 1535 | { 1536 | "abstract": false, 1537 | "baseContracts": [], 1538 | "canonicalName": "Migrations", 1539 | "contractDependencies": [], 1540 | "contractKind": "contract", 1541 | "fullyImplemented": true, 1542 | "id": 207, 1543 | "linearizedBaseContracts": [ 1544 | 207 1545 | ], 1546 | "name": "Migrations", 1547 | "nameLocation": "75:10:1", 1548 | "nodeType": "ContractDefinition", 1549 | "nodes": [ 1550 | { 1551 | "constant": false, 1552 | "functionSelector": "8da5cb5b", 1553 | "id": 180, 1554 | "mutability": "mutable", 1555 | "name": "owner", 1556 | "nameLocation": "105:5:1", 1557 | "nodeType": "VariableDeclaration", 1558 | "scope": 207, 1559 | "src": "90:33:1", 1560 | "stateVariable": true, 1561 | "storageLocation": "default", 1562 | "typeDescriptions": { 1563 | "typeIdentifier": "t_address", 1564 | "typeString": "address" 1565 | }, 1566 | "typeName": { 1567 | "id": 177, 1568 | "name": "address", 1569 | "nodeType": "ElementaryTypeName", 1570 | "src": "90:7:1", 1571 | "stateMutability": "nonpayable", 1572 | "typeDescriptions": { 1573 | "typeIdentifier": "t_address", 1574 | "typeString": "address" 1575 | } 1576 | }, 1577 | "value": { 1578 | "expression": { 1579 | "id": 178, 1580 | "name": "msg", 1581 | "nodeType": "Identifier", 1582 | "overloadedDeclarations": [], 1583 | "referencedDeclaration": 4294967281, 1584 | "src": "113:3:1", 1585 | "typeDescriptions": { 1586 | "typeIdentifier": "t_magic_message", 1587 | "typeString": "msg" 1588 | } 1589 | }, 1590 | "id": 179, 1591 | "isConstant": false, 1592 | "isLValue": false, 1593 | "isPure": false, 1594 | "lValueRequested": false, 1595 | "memberName": "sender", 1596 | "nodeType": "MemberAccess", 1597 | "src": "113:10:1", 1598 | "typeDescriptions": { 1599 | "typeIdentifier": "t_address", 1600 | "typeString": "address" 1601 | } 1602 | }, 1603 | "visibility": "public" 1604 | }, 1605 | { 1606 | "constant": false, 1607 | "functionSelector": "445df0ac", 1608 | "id": 182, 1609 | "mutability": "mutable", 1610 | "name": "last_completed_migration", 1611 | "nameLocation": "139:24:1", 1612 | "nodeType": "VariableDeclaration", 1613 | "scope": 207, 1614 | "src": "127:36:1", 1615 | "stateVariable": true, 1616 | "storageLocation": "default", 1617 | "typeDescriptions": { 1618 | "typeIdentifier": "t_uint256", 1619 | "typeString": "uint256" 1620 | }, 1621 | "typeName": { 1622 | "id": 181, 1623 | "name": "uint", 1624 | "nodeType": "ElementaryTypeName", 1625 | "src": "127:4:1", 1626 | "typeDescriptions": { 1627 | "typeIdentifier": "t_uint256", 1628 | "typeString": "uint256" 1629 | } 1630 | }, 1631 | "visibility": "public" 1632 | }, 1633 | { 1634 | "body": { 1635 | "id": 193, 1636 | "nodeType": "Block", 1637 | "src": "190:119:1", 1638 | "statements": [ 1639 | { 1640 | "expression": { 1641 | "arguments": [ 1642 | { 1643 | "commonType": { 1644 | "typeIdentifier": "t_address", 1645 | "typeString": "address" 1646 | }, 1647 | "id": 188, 1648 | "isConstant": false, 1649 | "isLValue": false, 1650 | "isPure": false, 1651 | "lValueRequested": false, 1652 | "leftExpression": { 1653 | "expression": { 1654 | "id": 185, 1655 | "name": "msg", 1656 | "nodeType": "Identifier", 1657 | "overloadedDeclarations": [], 1658 | "referencedDeclaration": 4294967281, 1659 | "src": "211:3:1", 1660 | "typeDescriptions": { 1661 | "typeIdentifier": "t_magic_message", 1662 | "typeString": "msg" 1663 | } 1664 | }, 1665 | "id": 186, 1666 | "isConstant": false, 1667 | "isLValue": false, 1668 | "isPure": false, 1669 | "lValueRequested": false, 1670 | "memberName": "sender", 1671 | "nodeType": "MemberAccess", 1672 | "src": "211:10:1", 1673 | "typeDescriptions": { 1674 | "typeIdentifier": "t_address", 1675 | "typeString": "address" 1676 | } 1677 | }, 1678 | "nodeType": "BinaryOperation", 1679 | "operator": "==", 1680 | "rightExpression": { 1681 | "id": 187, 1682 | "name": "owner", 1683 | "nodeType": "Identifier", 1684 | "overloadedDeclarations": [], 1685 | "referencedDeclaration": 180, 1686 | "src": "225:5:1", 1687 | "typeDescriptions": { 1688 | "typeIdentifier": "t_address", 1689 | "typeString": "address" 1690 | } 1691 | }, 1692 | "src": "211:19:1", 1693 | "typeDescriptions": { 1694 | "typeIdentifier": "t_bool", 1695 | "typeString": "bool" 1696 | } 1697 | }, 1698 | { 1699 | "hexValue": "546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572", 1700 | "id": 189, 1701 | "isConstant": false, 1702 | "isLValue": false, 1703 | "isPure": true, 1704 | "kind": "string", 1705 | "lValueRequested": false, 1706 | "nodeType": "Literal", 1707 | "src": "238:53:1", 1708 | "typeDescriptions": { 1709 | "typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 1710 | "typeString": "literal_string \"This function is restricted to the contract's owner\"" 1711 | }, 1712 | "value": "This function is restricted to the contract's owner" 1713 | } 1714 | ], 1715 | "expression": { 1716 | "argumentTypes": [ 1717 | { 1718 | "typeIdentifier": "t_bool", 1719 | "typeString": "bool" 1720 | }, 1721 | { 1722 | "typeIdentifier": "t_stringliteral_f60fe2d9d123295bf92ecf95167f1fa709e374da35e4c083bd39dc2d82acd8b1", 1723 | "typeString": "literal_string \"This function is restricted to the contract's owner\"" 1724 | } 1725 | ], 1726 | "id": 184, 1727 | "name": "require", 1728 | "nodeType": "Identifier", 1729 | "overloadedDeclarations": [ 1730 | 4294967278, 1731 | 4294967278 1732 | ], 1733 | "referencedDeclaration": 4294967278, 1734 | "src": "196:7:1", 1735 | "typeDescriptions": { 1736 | "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", 1737 | "typeString": "function (bool,string memory) pure" 1738 | } 1739 | }, 1740 | "id": 190, 1741 | "isConstant": false, 1742 | "isLValue": false, 1743 | "isPure": false, 1744 | "kind": "functionCall", 1745 | "lValueRequested": false, 1746 | "names": [], 1747 | "nodeType": "FunctionCall", 1748 | "src": "196:101:1", 1749 | "tryCall": false, 1750 | "typeDescriptions": { 1751 | "typeIdentifier": "t_tuple$__$", 1752 | "typeString": "tuple()" 1753 | } 1754 | }, 1755 | "id": 191, 1756 | "nodeType": "ExpressionStatement", 1757 | "src": "196:101:1" 1758 | }, 1759 | { 1760 | "id": 192, 1761 | "nodeType": "PlaceholderStatement", 1762 | "src": "303:1:1" 1763 | } 1764 | ] 1765 | }, 1766 | "id": 194, 1767 | "name": "restricted", 1768 | "nameLocation": "177:10:1", 1769 | "nodeType": "ModifierDefinition", 1770 | "parameters": { 1771 | "id": 183, 1772 | "nodeType": "ParameterList", 1773 | "parameters": [], 1774 | "src": "187:2:1" 1775 | }, 1776 | "src": "168:141:1", 1777 | "virtual": false, 1778 | "visibility": "internal" 1779 | }, 1780 | { 1781 | "body": { 1782 | "id": 205, 1783 | "nodeType": "Block", 1784 | "src": "369:47:1", 1785 | "statements": [ 1786 | { 1787 | "expression": { 1788 | "id": 203, 1789 | "isConstant": false, 1790 | "isLValue": false, 1791 | "isPure": false, 1792 | "lValueRequested": false, 1793 | "leftHandSide": { 1794 | "id": 201, 1795 | "name": "last_completed_migration", 1796 | "nodeType": "Identifier", 1797 | "overloadedDeclarations": [], 1798 | "referencedDeclaration": 182, 1799 | "src": "375:24:1", 1800 | "typeDescriptions": { 1801 | "typeIdentifier": "t_uint256", 1802 | "typeString": "uint256" 1803 | } 1804 | }, 1805 | "nodeType": "Assignment", 1806 | "operator": "=", 1807 | "rightHandSide": { 1808 | "id": 202, 1809 | "name": "completed", 1810 | "nodeType": "Identifier", 1811 | "overloadedDeclarations": [], 1812 | "referencedDeclaration": 196, 1813 | "src": "402:9:1", 1814 | "typeDescriptions": { 1815 | "typeIdentifier": "t_uint256", 1816 | "typeString": "uint256" 1817 | } 1818 | }, 1819 | "src": "375:36:1", 1820 | "typeDescriptions": { 1821 | "typeIdentifier": "t_uint256", 1822 | "typeString": "uint256" 1823 | } 1824 | }, 1825 | "id": 204, 1826 | "nodeType": "ExpressionStatement", 1827 | "src": "375:36:1" 1828 | } 1829 | ] 1830 | }, 1831 | "functionSelector": "fdacd576", 1832 | "id": 206, 1833 | "implemented": true, 1834 | "kind": "function", 1835 | "modifiers": [ 1836 | { 1837 | "id": 199, 1838 | "kind": "modifierInvocation", 1839 | "modifierName": { 1840 | "id": 198, 1841 | "name": "restricted", 1842 | "nodeType": "IdentifierPath", 1843 | "referencedDeclaration": 194, 1844 | "src": "358:10:1" 1845 | }, 1846 | "nodeType": "ModifierInvocation", 1847 | "src": "358:10:1" 1848 | } 1849 | ], 1850 | "name": "setCompleted", 1851 | "nameLocation": "322:12:1", 1852 | "nodeType": "FunctionDefinition", 1853 | "parameters": { 1854 | "id": 197, 1855 | "nodeType": "ParameterList", 1856 | "parameters": [ 1857 | { 1858 | "constant": false, 1859 | "id": 196, 1860 | "mutability": "mutable", 1861 | "name": "completed", 1862 | "nameLocation": "340:9:1", 1863 | "nodeType": "VariableDeclaration", 1864 | "scope": 206, 1865 | "src": "335:14:1", 1866 | "stateVariable": false, 1867 | "storageLocation": "default", 1868 | "typeDescriptions": { 1869 | "typeIdentifier": "t_uint256", 1870 | "typeString": "uint256" 1871 | }, 1872 | "typeName": { 1873 | "id": 195, 1874 | "name": "uint", 1875 | "nodeType": "ElementaryTypeName", 1876 | "src": "335:4:1", 1877 | "typeDescriptions": { 1878 | "typeIdentifier": "t_uint256", 1879 | "typeString": "uint256" 1880 | } 1881 | }, 1882 | "visibility": "internal" 1883 | } 1884 | ], 1885 | "src": "334:16:1" 1886 | }, 1887 | "returnParameters": { 1888 | "id": 200, 1889 | "nodeType": "ParameterList", 1890 | "parameters": [], 1891 | "src": "369:0:1" 1892 | }, 1893 | "scope": 207, 1894 | "src": "313:103:1", 1895 | "stateMutability": "nonpayable", 1896 | "virtual": false, 1897 | "visibility": "public" 1898 | } 1899 | ], 1900 | "scope": 208, 1901 | "src": "66:352:1", 1902 | "usedErrors": [] 1903 | } 1904 | ], 1905 | "src": "32:387:1" 1906 | }, 1907 | "compiler": { 1908 | "name": "solc", 1909 | "version": "0.8.15+commit.e14f2714.Emscripten.clang" 1910 | }, 1911 | "networks": { 1912 | "97": { 1913 | "events": {}, 1914 | "links": {}, 1915 | "address": "0x66Ffc9b63d3c59123959376865C3C50404B208e2", 1916 | "transactionHash": "0x95f1044cab0bbcae6410c65f57cd0fa3e1670847ddcb864d61d6cada1f3d349a" 1917 | }, 1918 | "5777": { 1919 | "events": {}, 1920 | "links": {}, 1921 | "address": "0xE107e085A3366D07aA9f744aA1eAaA350B2B2f32", 1922 | "transactionHash": "0x765b99f93d20bda7d0e8784afa6ef9a348826da750434901425b398ee0b58837" 1923 | } 1924 | }, 1925 | "schemaVersion": "3.4.7", 1926 | "updatedAt": "2022-06-29T18:59:36.703Z", 1927 | "devdoc": { 1928 | "kind": "dev", 1929 | "methods": {}, 1930 | "version": 1 1931 | }, 1932 | "userdoc": { 1933 | "kind": "user", 1934 | "methods": {}, 1935 | "version": 1 1936 | } 1937 | } -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/client/app.js: -------------------------------------------------------------------------------- 1 | // This function detects most providers injected at window.ethereum 2 | var Web3 = require('web3'); 3 | var TruffleContract = require('truffle-contract'); 4 | 5 | App = { 6 | web3Provider: null, 7 | contracts: {}, 8 | currentAccount:{}, 9 | 10 | initWeb3 : async function (){ 11 | // Initialize the Web3 Provider with the Wallet Details 12 | if (process.env.MODE == 'development'){ 13 | App.web3Provider = new Web3.providers.HttpProvider(process.env.LOCAL_NODE); //for local development 14 | } 15 | else if(typeof window.web3 === 'undefined'){ 16 | App.showError("Install MetaMask"); 17 | } 18 | else{ 19 | App.web3Provider = web3.currentProvider; //for getting information from connected wallet 20 | } 21 | web3 = new Web3(App.web3Provider); 22 | return await App.initContractHelloWorld(); 23 | }, 24 | 25 | initContractHelloWorld : async function (){ 26 | //Function to fetch the HelloWorld Contract ABI 27 | await $.getJSON('HelloWorld.json',function(message){ 28 | var HelloWorldArtifact = message; 29 | App.contracts.HelloWorld = TruffleContract(HelloWorldArtifact); 30 | App.contracts.HelloWorld.setProvider(App.web3Provider); 31 | }) 32 | return App.bindEvents(); 33 | }, 34 | bindEvents: function() { 35 | $('#buttonSave').click(App.setName); //Setting on-click function for Save Button 36 | $('#buttonMessage').click(App.loadMessage); //Setting on-click function for Greet Button to display message 37 | }, 38 | 39 | loadMessage : function (){ 40 | //Function to Load Message 41 | App.contracts.HelloWorld.deployed().then(async function(instance){ 42 | let message; 43 | if(App.currentAccount.length){ 44 | message = await instance.getMessage.call({from:App.currentAccount}); 45 | } 46 | else{ 47 | message = await instance.getMessage.call(); 48 | } 49 | App.showMessage(message); 50 | }).catch((err) =>{ 51 | App.showError(err); 52 | }) 53 | }, 54 | 55 | showMessage: function (msg){ 56 | //Function to Load Message "Hello, Name" 57 | $('#output').html(msg.toString()); 58 | $('#errorHolder').hide(); 59 | $('#output').show(); 60 | }, 61 | 62 | //Function to Print Error Messages 63 | showError: function(err){ 64 | if(err.message != undefined){ 65 | $('#errorHolder').html(err.message.toString()); 66 | } 67 | else{ 68 | $('#errorHolder').html(err.toString()); 69 | } 70 | $('#errorHolder').show(); 71 | $('#output').hide(); 72 | }, 73 | 74 | setName: function (){ 75 | //Function to Set Name 76 | if ($('#name').val()){ 77 | web3.eth.getAccounts(function (error,accounts){ 78 | if (error){ 79 | if (accounts.length === 0) { 80 | console.log('Please connect to MetaMask.'); 81 | } 82 | App.showError(error); 83 | } 84 | App.currentAccount = accounts[0]; 85 | App.contracts.HelloWorld.deployed().then(function(instance){ 86 | return instance.setName.sendTransaction($('#name').val(),{from:App.currentAccount}) 87 | }).then(function(result){ 88 | document.getElementById("name").value = ""; 89 | App.showMessage('Save Successful'); 90 | }).catch(function (error){ 91 | App.showError(error); 92 | }) 93 | }) 94 | } 95 | else if($('#name').val() == ""){ 96 | App.showError('Error: Enter a Name to Save.'); 97 | } 98 | }, 99 | init : async function (){ 100 | await App.initWeb3(); 101 | App.loadMessage(); 102 | } 103 | 104 | } 105 | 106 | $(function() { 107 | $(window).load(function() { 108 | $('#errorHolder').hide(); 109 | $('#output').hide(); 110 | 111 | App.init(); 112 | }); 113 | }); -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/client/chain-smart-bsc-l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/01- Hello World Full Stack dApp on BSC/client/chain-smart-bsc-l.png -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/client/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color:#292929; 3 | /*background-image: url("data:image/jpeg;base64,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"); 4 | background-repeat: no-repeat; 5 | background-position: center;*/ 6 | /*padding: 2em;*/ 7 | margin-left: 5%; 8 | font-family: 'IBM Plex Sans','Raleway','Source Sans Pro', 'Arial'; 9 | } 10 | .container { 11 | width: 50%; 12 | margin: 0 auto; 13 | } 14 | .header-img { 15 | width: 50%; 16 | height: 80px; 17 | background: url('chain-smart-bsc-l.png'); 18 | background-size: contain; 19 | background-repeat: no-repeat; 20 | margin-top: 2em; 21 | } 22 | .container { 23 | display: flex; 24 | flex-direction: column; 25 | width: 100%; 26 | height: 300px; 27 | } 28 | 29 | .column { 30 | flex: 1; 31 | color: white; 32 | } 33 | 34 | label { 35 | display:block; 36 | margin-bottom:5px; 37 | } 38 | input { 39 | padding:10px; 40 | width: 30%; 41 | margin-bottom: 1em; 42 | font-family: 'IBM Plex Sans','Raleway','Source Sans Pro', 'Arial'; 43 | } 44 | button { 45 | margin: 1em 0; 46 | padding: 10px 3em; 47 | font-weight: bold; 48 | font-family: 'IBM Plex Sans','Raleway','Source Sans Pro', 'Arial'; 49 | } 50 | #buttonMessage{ 51 | float:left; 52 | } 53 | #output{ 54 | background-color: rgb(255, 208, 0); 55 | color: black; 56 | font-size: medium; 57 | padding: 10px; 58 | text-align:center; 59 | margin:1em 0; 60 | clear:both; 61 | width: 45%; 62 | float:left; 63 | margin:1em 0; 64 | } 65 | 66 | #errorHolder{ 67 | background-color: coral; 68 | padding: 10px; 69 | margin:1em 0; 70 | clear:both; 71 | width: 45%; 72 | } -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hello World Smart Contract 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Greetings from BNB Chain

15 |
16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 | 24 |
25 |
26 |
27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/contracts/HelloWorld.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | /** @title Documents. */ 5 | contract HelloWorld { 6 | 7 | string defaultName; 8 | mapping (address => string) public accounts; 9 | 10 | constructor() { 11 | defaultName = 'World'; 12 | } 13 | 14 | /** @dev Retrieve Message to Print 15 | * @return The Message to Print, Hello, Concatenated with the User Name 16 | */ 17 | function getMessage() public view returns(string memory){ 18 | string memory name = bytes(accounts[msg.sender]).length > 0 ? accounts[msg.sender] : defaultName; 19 | return concat("Hello, " , name); 20 | } 21 | 22 | /** @dev Set the Name to Greet 23 | * @param _name user name 24 | * @return success Returns bool value (True or False) to indicate if save was successful or not 25 | */ 26 | function setName(string memory _name) public returns(bool success){ 27 | require(bytes(_name).length > 0); 28 | accounts[msg.sender] = _name; 29 | return true; 30 | } 31 | 32 | /** @dev Set the Name to Greet 33 | * @param _base contains the base value " Hello, " 34 | * @param _value contains the name to append to message to display 35 | * @return the concatenated string of _base+_value i.e. Hello, Name 36 | */ 37 | function concat(string memory _base, string memory _value) internal pure returns (string memory) { 38 | bytes memory _baseBytes = bytes(_base); 39 | bytes memory _valueBytes = bytes(_value); 40 | 41 | string memory _tmpValue = new string(_baseBytes.length + _valueBytes.length); 42 | bytes memory _newValue = bytes(_tmpValue); 43 | 44 | uint i; 45 | uint j; 46 | 47 | for(i=0; i<_baseBytes.length; i++) { 48 | _newValue[j++] = _baseBytes[i]; 49 | } 50 | 51 | for(i=0; i<_valueBytes.length; i++) { 52 | _newValue[j++] = _valueBytes[i]; 53 | } 54 | 55 | return string(_newValue); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | contract Migrations { 5 | address public owner = msg.sender; 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | require( 10 | msg.sender == owner, 11 | "This function is restricted to the contract's owner" 12 | ); 13 | _; 14 | } 15 | 16 | function setCompleted(uint completed) public restricted { 17 | last_completed_migration = completed; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/migrations/2_hello_world.js: -------------------------------------------------------------------------------- 1 | var HelloWorld = artifacts.require('HelloWorld'); 2 | 3 | module.exports = function(deployer) { 4 | // Use deployer to state migration tasks. 5 | deployer.deploy(HelloWorld); 6 | }; -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "helloworld", 3 | "version": "1.0.0", 4 | "main": "truffle-config.js", 5 | "directories": { 6 | "test": "test" 7 | }, 8 | "scripts": { 9 | "test": "echo \"Error: no test specified\" && exit 1", 10 | "start": "node server/main.js", 11 | "dev": "node_modules/.bin/webpack && node server/main.js", 12 | "webpack": "node_modules/.bin/webpack --watch", 13 | "build": "npx webpack " 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "@metamask/detect-provider": "^1.2.0", 19 | "@rails/webpacker": "^5.4.3", 20 | "@truffle/hdwallet-provider": "^2.0.9", 21 | "dotenv": "^16.0.1", 22 | "express": "^4.18.1", 23 | "node_modules-path": "^2.0.5", 24 | "truffle-hdwallet-provider": "^1.0.17", 25 | "webpack": "4", 26 | "webpack-cli": "^4.10.0" 27 | }, 28 | "devDependencies": { 29 | "truffle-contract": "^4.0.31" 30 | }, 31 | "description": "" 32 | } 33 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/server/main.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const express = require('express'); 3 | const app = express(); 4 | const PORT = process.env.PORT || 3000; 5 | 6 | app.use(express.static('client')); 7 | app.use(express.static('build/contracts')); 8 | app.get('/', (req, res) => { 9 | res.sendFile(`${__dirname}/client/index.html`); 10 | }); 11 | 12 | app.get('*', (req, res) => { 13 | res.status(404); 14 | res.send('Sorry this URL does not exist'); 15 | }); 16 | 17 | app.listen(PORT, () => { 18 | console.log(`HelloWorld App running on port ${PORT}...`); 19 | }); -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/test/hello_world.js: -------------------------------------------------------------------------------- 1 | var helloworld = artifacts.require('HelloWorld'); 2 | contract('HelloWorld', function(accounts) { 3 | let instance; 4 | before(async () => { 5 | instance = await helloworld.deployed(); 6 | }); 7 | 8 | //Test to check if the default value is set to "hello, world" 9 | it('Default message should be hello, world',async () => { 10 | let message = await instance.getMessage.call({from: accounts[0]}); 11 | assert.equal(message, "Hello, World","Incorrect message."); 12 | }); 13 | 14 | //Test to check if the save button is working or not 15 | it('Should save name',async () => { 16 | let result = await instance.setName.sendTransaction('Rumeel',{from: accounts[0]}); 17 | let message = await instance.getMessage.call({from: accounts[0]}); 18 | assert.equal(message, "Hello, Rumeel","Incorrect message."); 19 | }); 20 | 21 | //Test to check if the default values for accounts other than the 1s default account of wallet 22 | it('Should be default message for other accounts',async () => { 23 | let message1 = await instance.getMessage.call({from: accounts[0]}); 24 | let message2 = await instance.getMessage.call({from: accounts[1]}); 25 | assert.equal(message1, "Hello, Rumeel","Incorrect user message."); 26 | assert.equal(message2, "Hello, World","Incorrect message."); 27 | }); 28 | 29 | //Test to check if error is thrown on empty name field 30 | it('Should throw error on empty name',async () => { 31 | try{ 32 | let result = await instance.setName.sendTransaction('',{from: accounts[0]}); 33 | assert.fail(true,false,"The function should throw error"); 34 | } 35 | catch(err){ 36 | assert.include(String(err),'revert','throws different error'); 37 | } 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/truffle-config.js: -------------------------------------------------------------------------------- 1 | const HDWalletProvider = require('@truffle/hdwallet-provider'); 2 | const fs = require('fs'); 3 | const mnemonic = fs.readFileSync(".secret").toString().trim(); 4 | 5 | module.exports = { 6 | 7 | networks: { 8 | development: { 9 | host: "127.0.0.1", // Localhost (default: none) 10 | port: 8545, // Standard Ethereum port (default: none) 11 | network_id: "*", // Any network (default: none) 12 | }, 13 | bscTestnet: { 14 | provider: () => new HDWalletProvider(mnemonic, `https://data-seed-prebsc-2-s1.binance.org:8545`), 15 | network_id: 97, 16 | confirmations: 2, 17 | //timeoutBlocks: 200, 18 | skipDryRun: true, 19 | }, 20 | bscMainnet: { 21 | provider: () => new HDWalletProvider(mnemonic, `https://bsc-dataseed1.binance.org`), 22 | network_id: 56, 23 | confirmations: 10, 24 | timeoutBlocks: 200, 25 | skipDryRun: true 26 | }, 27 | }, 28 | 29 | // Set default mocha options here, use special reporters, etc. 30 | mocha: { 31 | // timeout: 100000 32 | }, 33 | 34 | // Configure your compilers 35 | compilers: { 36 | solc: { 37 | version: "^0.8.0", // Fetch exact version from solc-bin (default: truffle's version) 38 | } 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /01- Hello World Full Stack dApp on BSC/webpack.config.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const webpack = require('webpack'); 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | resolve: { 7 | alias: { 8 | 'node_modules': path.join(__dirname, 'node_modules') 9 | } 10 | }, 11 | entry: './client/app.js', 12 | mode: process.env.MODE, 13 | output: { 14 | filename: 'bundle.js', 15 | path: path.resolve(__dirname, 'client/dist') 16 | }, 17 | plugins: [ 18 | new webpack.DefinePlugin({ 19 | 'process.env': { 20 | 'LOCAL_NODE': JSON.stringify(process.env.LOCAL_NODE), 21 | 'MODE':JSON.stringify(process.env.MODE), 22 | } 23 | }) 24 | ], 25 | node: { 26 | net: 'empty', 27 | tls: 'empty', 28 | dns: 'empty' 29 | }, 30 | externals:[{ 31 | xmlhttprequest: '{XMLHttpRequest:XMLHttpRequest}' 32 | }] 33 | }; -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/README.md: -------------------------------------------------------------------------------- 1 | # BSC Block Explorer Tutorial 2 | 3 | ## Overview 4 | Designed for anyone wanting to learn development on the BNB Smart Chain, this tutorial provides a step-by-step guide on how to develop a block explorer that uses the Nodereal API to fetch details from the BNB Smart Chain blockchain for the given transaction hash. The technology stack used in this tutorial includes Web3.js, Nodereal MegaNode, and http-server. 5 | 6 | ## What You Will Learn 7 | Through this tutorial, you will learn 8 | - How to use the Web3js library to fetch blockchain data; 9 | - How to use Nodereal’s Meganode API; 10 | - How to deploy static pages onto localhost using http-server 11 | 12 | ## Target audience 13 | This tutorial aims to provide adequate information to anyone who wants to learn dApp development on BNB Smart Chain. 14 | 15 | ## Prerequisites 16 | - node --version 17 | - v16.13.0 18 | - npm --version 19 | - 8.1.0 20 | - http-server --version 21 | - v14.1.1 22 | 23 | ## Setup 24 | 25 | 1. **Clone the repository** ```gh repo clone https://github.com/bnb-chain/bnb-chain-tutorial``` 26 | 2. **Change the current directory** ```cd 02-BSC-Block-Explorer``` 27 | 3. **Install all the dependencies (node modules)** ```npm install``` 28 | 4. **Include Nodereal Meganode API Key** make sure to include the HTTP link for the Nodereal Meganode API in the ```index.html``` as shown in the figure below. 29 | 30 | ![img](img/screenshot2.png) 31 | 32 | 5. For this project we have used the BSC Testnet public API key as shown in the figure below. For a complete list of Nodereal Meganode Public API keys, refer [here](https://docs.nodereal.io/nodereal/meganode/meganode-api-overview/public-api-key). 33 | 34 | ![img](img/screenshot3.png) 35 | 36 | 5. **Install htpp-server** ```npm install -g http-server``` 37 | 6. **Run the application** ```http-server``` 38 | 39 | ## Available Scripts 40 | ```sh 41 | $ http-server 42 | ``` 43 | 44 | ## Structure 45 | ``` 46 | 02-BSC-Block-Explorer. 47 | | index.html 48 | | list.txt 49 | | README.md 50 | | screenshot.png 51 | | 52 | +---img 53 | | favicon.ico 54 | | logo.png 55 | | screenshot.png 56 | | 57 | \---js 58 | web3.min.js 59 | ``` 60 | 61 | ## How it Works 62 | ### Checklist 63 | - Make sure you have installed all the dependences using the ```npm install``` command. 64 | - Make sure you have installed http-server using the ```npm install -g http-server``` command. 65 | - Before running the application, make sure that you have included the HTTP link for the Nodereal Meganode API in the ```index.html``` as shown in the figure below. 66 | 67 | ![img](img/screenshot2.png) 68 | 69 | - For this project we have used the public API key for BSC Testnet. For a complete list of Nodereal Meganode Public API keys, refer [here](https://docs.nodereal.io/nodereal/meganode/meganode-api-overview/public-api-key). 70 | 71 | ### How to Use 72 | - Run the application using the command ```http-server``` from the root directory of the project. 73 | - Open browser and navigate to any of the URLs specified by running the above step, for e.g., ```localhost:8080```. 74 | - Since we have used the HTTP reference of Nodereal’s Meganode API for BSC testnet, open [BSCscan for Testnet](https://testnet.bscscan.com/), and copy the transaction hash of any transaction of your choice. 75 | - Paste this transaction hash into the input field in our block explorer. 76 | - Click on the _**Fetch Details**_ button to fetch details of the transaction. 77 | 78 | ![img](img/screenshot.png) 79 | 80 | ## Contact 81 | For more inquiries and conversations, feel free to contact us at our [Discord Channel](https://discord.com/channels/789402563035660308/912296662834241597) 82 | -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/02-BSC-Block-Explorer/img/favicon.ico -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/02-BSC-Block-Explorer/img/logo.png -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/02-BSC-Block-Explorer/img/screenshot.png -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/img/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/02-BSC-Block-Explorer/img/screenshot2.png -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/img/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/02-BSC-Block-Explorer/img/screenshot3.png -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | BSC Block Explorer 9 | 10 | 11 | 12 | 20 | 21 | 22 |
23 |
24 |
25 | logo 26 |

Block Explorer

27 |
28 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
Block HashBlock NumberFrom
43 |
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/list.txt: -------------------------------------------------------------------------------- 1 | Folder PATH listing 2 | Volume serial number is 309C-F577 3 | F:. 4 | | index.html 5 | | list.txt 6 | | README.md 7 | | screenshot.png 8 | | 9 | +---img 10 | | favicon.ico 11 | | logo.png 12 | | screenshot.png 13 | | 14 | \---js 15 | web3.min.js 16 | 17 | -------------------------------------------------------------------------------- /02-BSC-Block-Explorer/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/02-BSC-Block-Explorer/screenshot.png -------------------------------------------------------------------------------- /03-Using-BlackIDE-for-Deploying-NFTs/ERC721_NFT.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 5 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; 6 | import "@openzeppelin/contracts/security/Pausable.sol"; 7 | import "@openzeppelin/contracts/access/Ownable.sol"; 8 | import "@openzeppelin/contracts/utils/Counters.sol"; 9 | 10 | /** @title BSCNFT */ 11 | contract BSCNFT is ERC721, ERC721Enumerable, Pausable, Ownable { 12 | 13 | /* Property Variables */ 14 | 15 | using Counters for Counters.Counter; 16 | 17 | Counters.Counter private _tokenIdCounter; 18 | 19 | uint256 public MINT_PRICE = 0.05 ether; //Change this value as per your requirement 20 | uint public MAX_SUPPLY = 100; //Change this value as per your requirement 21 | 22 | /** @dev Constructor to set Name and Initials for NFT 23 | and increment token counter 24 | */ 25 | constructor() ERC721("HappyMonkey", "HM") { 26 | // Start token ID at 1. By default is starts at 0. 27 | _tokenIdCounter.increment(); 28 | } 29 | 30 | /** @dev Withdraw Tokens 31 | */ 32 | function withdraw() public onlyOwner() { 33 | require(address(this).balance > 0, "Balance is zero"); 34 | payable(owner()).transfer(address(this).balance); 35 | } 36 | 37 | /** @dev Pause NFT Function 38 | */ 39 | function pause() public onlyOwner { 40 | _pause(); 41 | } 42 | /** @dev Unpause NFT Function 43 | */ 44 | function unpause() public onlyOwner { 45 | _unpause(); 46 | } 47 | 48 | /** @dev Function to Mint NFTs 49 | */ 50 | 51 | function safeMint(address to) public payable { 52 | // Check that totalSupply is less than MAX_SUPPLY 53 | require(totalSupply() < MAX_SUPPLY, "Can't mint anymore tokens."); 54 | 55 | // Check if enough amount of Ethers are passed 56 | require(msg.value >= MINT_PRICE, "Not enough ether sent."); 57 | uint256 tokenId = _tokenIdCounter.current(); 58 | _tokenIdCounter.increment(); 59 | _safeMint(to, tokenId); 60 | } 61 | 62 | /** @dev Function to set the URI of the NFT 63 | */ 64 | function _baseURI() internal pure override returns (string memory) { 65 | return "ipfs://happyMonkeyBaseURI/"; //change this for your token 66 | } 67 | 68 | /** @dev Sanity Checks before the token is transferrred 69 | */ 70 | function _beforeTokenTransfer(address from, address to, uint256 tokenId) 71 | internal 72 | whenNotPaused 73 | override(ERC721, ERC721Enumerable) 74 | { 75 | super._beforeTokenTransfer(from, to, tokenId); 76 | } 77 | 78 | /** @dev The following functions are overrides required by Solidity. 79 | */ 80 | function supportsInterface(bytes4 interfaceId) 81 | public 82 | view 83 | override(ERC721, ERC721Enumerable) 84 | returns (bool) 85 | { 86 | return super.supportsInterface(interfaceId); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /03-Using-BlackIDE-for-Deploying-NFTs/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Using Black IDE to Deploy NFTs on BSC 3 | 4 | In this tutorial, we provide a step-by-step guide to the readers on how to issue Non-fungible tokens (NFTs) (ERC721/1155) on the BNB Smart Chain (BSC) Testnet using the Black IDE. This is a detailed guide to learning how to issue, mint and transfer NFTs on the BSC Testnet. The technology stack used in this tutorial includes Solidity , Truffle, MetaMask, and BlackIDE. 5 | 6 | ## Learning Takeaways: 7 | This tutorial will help you gain knowledge on the following learning points: 8 | - Using BlackIDE for smart contract development; 9 | - Managing Keypairs and Funding BNB Tokens to your account on BlackIDE; 10 | - MetaMask Wallet connectivity to BSC Testnet; 11 | - Smart-contract development; 12 | - Issuing, minting, and transferring NFTs; 13 | 14 | ## Technology Stack Details 15 | - BlackIDE v0.15.4 16 | - Truffle v5.5.19 (core: 5.5.19) 17 | - MetaMask Wallet v10.16.1 18 | - Docker v20.10.14 19 | 20 | ## Brief Introduction Tech Stack 21 | 1. **Solidity:** one of the most popular object-oriented high-level smart contract programming languages. For more details on Solidity, refer here. 22 | 2. **MetaMask Wallet Browser Extension:** we recommend using the Metamask Chrome extension. It is a web wallet that allows connecting the chrome browser to any valid blockchain network. 23 | 3. **Black IDE:** Black IDE is an integrated development environment (IDE), making developing EVM-compatible smart contracts faster and easier. Black IDE offers both desktop and web (Black IDE Web) applications. 24 | 25 | ## Setting up the Environment 26 | We aim to keep this tutorial as simple as possible and hence tend to use as minimal resources as possible and have used the following tools in this tutorial. 27 | * Metamask Wallet 28 | * Ensure that you have the Metamask Wallet extension installed and running on our browser. 29 | * Configure the Metamask wallet for use with the BSC Testnet. Use the following details to add the BSC Testnet. For further details, refer here. 30 | * Network Name: BSC Testnet 31 | * RPC URL: https://data-seed-prebsc-1-s1.binance.org:8545/ 32 | * Chain ID: 97 33 | * Currency Symbol: BNB 34 | * Block Explorer URL: https://testnet.bscscan.com 35 | * Black IDE: both desktop app and web app are available and it is up to your convenience to choose from. For this tutorial, we used the desktop app as the web app lacks support for importing OpenZeppelin Contracts. 36 | * Download/Install any dependencies required by BlackIDE 37 | 38 | ![image](https://user-images.githubusercontent.com/93580180/177942609-e2c942a6-342c-46cd-b794-92fc8e72bdc0.png) 39 | 40 | ## Login into Black IDE 41 | 1. Open the Black IDE desktop application. We will be using it for compiling and deploying our smart contract for NFTs on the BSC Testnet. 42 | 2. Click on the Login button and authorize using your GitHub account. 43 | 44 | ![image](https://user-images.githubusercontent.com/93580180/177942736-d3d79717-8952-4fc7-b7c2-b28dc978f277.png) 45 | 46 | ## Create New Project 47 | 3. Click on the New button next to the projects to create a new project. 48 | 49 | ![image](https://user-images.githubusercontent.com/93580180/177942931-510837df-ed97-4a8e-a4df-cc4aeca24294.png) 50 | 51 | 4. Specify the location where you want to save your project on your device, the project name, e.g. “BSC-NFT”, and select the project type from the dropdown list as “Basics- ERC20, ERC721, & ERC1155 (v31+)”. Then click the Create button to create the project. 52 | 53 | ![image](https://user-images.githubusercontent.com/93580180/177942969-a1e8170f-e806-44d5-9e9f-99e5cc2914f8.png) 54 | 55 | 5. Remember the smart contract in this tutorial is just a sample, you can always modify and be innovative. 56 | 57 | ## Smart Contract Creation 58 | 6. Expand the contracts menu and delete the default files. 59 | 60 | ![image](https://user-images.githubusercontent.com/93580180/177948005-436776e5-07b4-4109-8b19-897925e623e4.png) 61 | 62 | 7. Right-click on the contracts menu and select New File. Specify a name for your file, e.g., BSC-NFT.sol, and then click Create button. 63 | 64 | ![image](https://user-images.githubusercontent.com/93580180/177943065-cc591abd-d856-4c9c-bbef-94b2e826af7f.png) 65 | 66 | ## Write your smart contract code 67 | 8. Copy the following code into your smart contract file. We have used the contract code from the [ERC721_NFT.sol](ERC721_NFT.sol) file in this repo. 68 | 9. Remember to change the ```MINT_PRICE```, ```MAX_SUPPLY```, ```name```, and ```symbol``` of the token as per your need. Also, remember to change the ```_baseURI``` as per your token. 69 | 10. 70 | ![image](https://user-images.githubusercontent.com/93580180/177949895-a095fdb5-f770-4530-84f6-8854a0d7a5eb.png) 71 | 72 | ## Edit default project settings 73 | 10. Click on the config.json file to change the default setting. Change the main file name to the name of your contract, BSC-NFT.sol in our case. Similarly, change the name of the smart contract to deploy, BSCNFT.json in our case. 74 | 75 | ![image](https://user-images.githubusercontent.com/93580180/177948095-b6a905da-792c-47da-86d6-8a5d5db6a40b.png) 76 | 77 | ## Connect the Black IDE to the BSC Testnet 78 | 11. In order to connect the Black IDE to the BSC Testnet, click on the dropdown icon on the network menu in the top right corner and then select Testnet under the BNB Chain label. 79 | 80 | ![image](https://user-images.githubusercontent.com/93580180/177948186-e052e522-7069-4072-abae-fd0e6c819ee6.png) 81 | 82 | 12. Click on the ![image](https://user-images.githubusercontent.com/93580180/177943789-3557fde5-8805-4b03-ace8-05d2ace216c0.png) icon in the bottom left corner of the IDE to generate new keypair to perform transactions. You can skip this step if you already have generated a keypair. On the Keypair Manager, click on the CREATE button to generate new keypair. 83 | 84 | ![image](https://user-images.githubusercontent.com/93580180/177944146-eb6e2f1e-95f0-4b00-8458-c8145b008d15.png) 85 | 86 | 13. Specify your desired name for the keypair, in our case BSC-Testnet-Key. Then click on the CREATE button. Remember to keep your private keys securely and not share them with anyone. 87 | 88 | ![image](https://user-images.githubusercontent.com/93580180/177944170-fa9ed3bc-53d9-41f3-8a46-a07f56fee1d7.png) 89 | 90 | ## Acquire BNB Test Tokens 91 | * Initially, the balance of a newly created key pair is 0.0 ETH. To get BNB test tokens, you can use the [BSC Testnet Faucet](https://testnet.binance.org/faucet-smart/). 92 | * Copy your public address from the keypair manager 93 | 94 | ![image](https://user-images.githubusercontent.com/93580180/177944290-d06f2f06-e256-4110-8936-809c0f78e0fa.png) 95 | 96 | * Paste this on the facet and acquire test tokens as required, as shown below. A green pop-up is displayed on the successful transfer of test tokens. 97 | 98 | ![image](https://user-images.githubusercontent.com/93580180/177944333-ca8aefed-fec2-4271-aa3e-d2ccc301eb6c.png) 99 | 100 | * Close and re-open keypair manager to verify that the balance has been updated. Wait for approx. 1-2 mins for balance to get updated. 101 | 102 | ![image](https://user-images.githubusercontent.com/93580180/177944370-3aa70613-be45-4558-8c83-aca1a00557c3.png) 103 | 104 | ## Deploy Smart Contract on BSC Testnet 105 | 1. Select the appropriate Solidity compiler version from the bottom right corner of the IDE, Solc (0.8.4), ![image](https://user-images.githubusercontent.com/93580180/177944415-e733562a-54ad-4ed8-85a5-f17c79edfeac.png) 106 | in our case. 107 | 2. Click on the Build icon ![image](https://user-images.githubusercontent.com/93580180/177944483-ff523eed-017d-4265-b722-78ded06fe826.png) to build your smart contract. Upon successful build, the project navigation pane reflects a new folder named build. This folder contains contracts folder that has json files of the contracts built. All of the contracts imported in our BSCNFT contract are also built and imported as json files. 108 | 109 | ![image](https://user-images.githubusercontent.com/93580180/177948331-ece850ae-01fd-479b-b25f-d1f28c3400f6.png) 110 | 111 | 3. After successfully building your contract, it’s time to deploy the contract. Click on the Deploy icon ![image](https://user-images.githubusercontent.com/93580180/177944540-10d86198-03f2-40d8-8ac0-c013483c6458.png) for deploying your smart contract. Specify the details for your contract, as shown below, then click on the Estimate & Deploy button. The wizard will auto-estimate and fill the gas limit for your contract. Then click the Deploy button. 112 | 113 | ![image](https://user-images.githubusercontent.com/93580180/177944618-47b0fb1d-0ce3-4512-9b29-66f7a3416325.png) 114 | ![image](https://user-images.githubusercontent.com/93580180/177944632-839f7ac5-c9d5-4d80-b6fe-0b6be2e6c3fb.png) 115 | 116 | 4. Deployment details will pop-up, as shown in the figure below. 117 | 118 | ![image](https://user-images.githubusercontent.com/93580180/177944726-41c20038-1fc5-434a-b61f-be54f36f3ac6.png) 119 | 120 | 5. The status of the transaction will be updated to confirmed after the transaction is confirmed as shown in the figure below 121 | 122 | ![image](https://user-images.githubusercontent.com/93580180/177944768-dc622464-832f-4afd-8ccd-0529c675d46d.png) 123 | 124 | 6. You can also view this transaction by clicking on the transaction icon in the bottom left on the IDE. 125 | 126 | ![image](https://user-images.githubusercontent.com/93580180/177944786-8b7f3e34-e562-406b-890e-dcc22d48313f.png) 127 | 128 | ## Interact with deployed smart contract and Mint NFTs 129 | 1. You can also interact with the contract using the different functions. Click on the Transactions Icon on the bottom-left corner of the IDE and then transaction of deployment of your smart contract. On the transaction details, click on the contract address to access the functions to interact with the smart contract. The left most column has all the Write Functions. The middle column has the View Functions and the right most column has the Events details. 130 | 131 | ![image](https://user-images.githubusercontent.com/93580180/177948835-197860e5-8f25-4692-bc34-467a997f98a1.png) 132 | 133 | ## Mint NFTs 134 | 1. As per our smart contract, when the contract is deployed, unless the NFTs are minted they won’t be visible in the wallet. 135 | 2. Create another keypair as defined previously. We will be issuing i.e. minting NFTs to the public address of this new keypair. 136 | 3. To mint i.e. issue an NFT to a specific user we use the “safeMint” function of the deployed smart contract. As shown in Steps 1 and 2 in the figure below, navigate to the deployed contracts, then in the left-most column click the drop-down menu to view the list of write functions available for use with the deployed contract. Select the “safeMint” function. 137 | 4. Use the safeMint function to mint new NFTs to a specific user address. As shown in figure above, steps 3 to 6, enter the “ETH to send” as the minting price of NFT, as per our smart contract the minting price is 50000000000000000 Wei, i.e., 0.05 ETH. We entered 0.06 ETH to cover the transaction charges as well. Then select the address to whom you want to issue (mint) an NFT to. Here, for the To address use the newly generated keypair in the section above. After this, click the transact button to execute the safeMint function. For the Signer, ensure that you are using the account that was used to deploy the smart contract. 138 | 139 | ![image](https://user-images.githubusercontent.com/93580180/177949113-3de5d538-852f-4a21-aa75-47d0231b6521.png) 140 | 141 | 5. To confirm what transfers have occurred, execute the Transfer event from the right most column. This will display the list of NFT transfers along with NFT token id, as shown in the figure below. 142 | 143 | ![image](https://user-images.githubusercontent.com/93580180/177945187-4e426ba2-a63f-4648-a259-fc9506ab5cb1.png) 144 | 145 | 6. To confirm owner of an NFT, use the ownerOf function. Pass the token id as input to the function, as illustrated in the figure below. 146 | 147 | ![image](https://user-images.githubusercontent.com/93580180/177945228-3a984146-dfa5-4a7b-9306-6258e9990f2a.png) 148 | 149 | ## View Your NFTs in Metamask Wallet 150 | 1. On the receiving end, the user can import the NFT token details into their Metamask wallet to view the assets. Please note that currently, Metamask Web Extension does not support the use of NFTs however, the mobile app version does support it. For the next steps to view the owned NFTs in your Metamask wallet, we will be using the Metamask Mobile Application. 151 | 2. Open Keypair manager on the Black IDE and copy the private key of the keypair that you minted i.e., transfer NFT. 152 | 153 | ![image](https://user-images.githubusercontent.com/93580180/177945281-060b95ce-2912-49a2-aa5d-bbf848ba9688.png) 154 | 155 | 3. On the Metamask wallet mobile app, import an account using this key pair. Enter the private key copied in the previous step and click import. 156 | 157 | ![image](https://user-images.githubusercontent.com/93580180/177954799-b86dae87-5274-4408-9d0b-5b52682549d1.png) 158 | 159 | 4. After importing account, the next step is to add the BSC Testnet configuration to the wallet. Ensure that you are using the same account whose pubic address was issued the NFT. 160 | 161 | ![image](https://user-images.githubusercontent.com/93580180/177950571-4674930b-c8c6-4480-8808-ea587af2bb2d.png) 162 | 163 | 5. Ensure that your account is connected to the BSC Testnet. Also, ensure that you have enough BNB test tokens in your account. If not, you can use the BSC Testnet Faucet to acquire some, as mentioned earlier. 164 | 165 | ![image](https://user-images.githubusercontent.com/93580180/177945438-84033dff-6d51-4fe6-875b-3b12bfe815c1.png) 166 | 167 | 6. To view the owned NFT assets your Metamask Mobile Wallet, click on the NFTs tab and then on the Import Tokens. Fill in the NFT details. In the address field, pass the address of the deployed contract and in the Id field pass the tokenID. Then click the Import button. 168 | 169 | ![image](https://user-images.githubusercontent.com/93580180/177949365-52efd22c-25ac-4eac-b47e-82349d6b0a5c.png) 170 | 171 | ## Conclusion 172 | In this tutorial, we provided a step-to-step guide on how to issue, mint and transfer NFTs on the BSC Testnet using the BlackIDE from Obsidian Labs.. The technology stack used in this tutorial includes Solidity, Truffle, MetaMask, and BlackIDE. Check out our [GitHub](https://github.com/bnb-chain/bnb-chain-tutorial) for more tutorials on how to develop on BSC. If you have any questions or are stuck, reach out to us on our [Discord Channel](https://discord.com/channels/789402563035660308/912296662834241597). 173 | 174 | -------------------------------------------------------------------------------- /04-Deploying-Smart-Contracts-Using-IDEs/README.md: -------------------------------------------------------------------------------- 1 | # Deploying Smart Contracts Using IDEs 2 | 3 | This repository contains step-by-step guides on how to deploy smart contracts on the BNB Smart Chain network using different IDEs. 4 | 5 | - [Tutorial on How to Deploy Smart Contract on BSC using Chainlink IDE](https://github.com/bnb-chain/bnb-chain-tutorial/blob/main/04-Deploying-Smart-Contracts-Using-IDEs/chainide.md). 6 | 7 | - [Tutorial on How to Deploy Smart Contract on BSC using Remix IDE](https://github.com/bnb-chain/bnb-chain-tutorial/blob/main/04-Deploying-Smart-Contracts-Using-IDEs/remixide.md). 8 | 9 | - [Tutorial on How to Deploy Smart Contract on BSC using Truffle IDE](https://github.com/bnb-chain/bnb-chain-tutorial/blob/main/04-Deploying-Smart-Contracts-Using-IDEs/truffle.md). 10 | 11 | - [Tutorial on How to Deploy Smart Contract on BSC using Hardhat IDE](https://github.com/bnb-chain/bnb-chain-tutorial/blob/main/04-Deploying-Smart-Contracts-Using-IDEs/hardhat.md). 12 | 13 | - [Tutorial on How to Deploy Smart Contract on BSC using Replit IDE](https://github.com/bnb-chain/bnb-chain-tutorial/blob/main/04-Deploying-Smart-Contracts-Using-IDEs/replit.md/). 14 | -------------------------------------------------------------------------------- /04-Deploying-Smart-Contracts-Using-IDEs/chainide.md: -------------------------------------------------------------------------------- 1 | 2 | # Using Chain IDE for Deploying Smart Contracts on BSC 3 | 4 | In this tutorial, we explain step-by-step how to create, compile and deploy a simple smart contract on the BSC Testnet using Chain IDE. 5 | 6 | ## What is Chain IDE? 7 | 8 | [ChainIDE](https://chainide.com/) is a chain agnostic, cloud-based IDE for creating decentralized applications. It enhances the development cycle through pre-configured plugins that save users' time and effort. This is a beginner guide on creating a simple smart contract and deploying it to the BNB Smart Chain. If you have any questions, feel free to ask them in the [ChainIDE Discord](https://discord.gg/QpGq4hjWrh). 9 | 10 | ## Pre-requisites 11 | 12 | 1. ChainIDE 13 | 2. Web3 Wallet 14 | 3. Solidity 15 | 16 | ## What You'll Do 17 | 18 | The following are general steps for deploying a storage smart contract 19 | 20 | 1. Setting up a Wallet 21 | 2. Write down a Storage Smart Contract 22 | 3. Compile a Storage Smart Contract 23 | 4. Deploy a Storage Smart Contract 24 | 5. Create a Flattened File using Flattener Library 25 | 6. Verify a Storage Smart Contract 26 | 7. Contract Interaction 27 | 28 | ## Setting up a Wallet 29 | 30 | ### Install Binance Wallet/MetaMask 31 | 32 | When deploying a smart contract to a blockchain or when making a transaction to a deployed smart contract, a gas fee must be paid, and for that, we need to use a crypto wallet which can be Binance Wallet or MetaMask. If you want to use Binance Wallet, click [here](https://chrome.google.com/webstore/detail/binance-wallet/fhbohimaelbohpjbbldcngcnapndodjp) to get Binance Wallet and if you want to continue with MetaMask Wallet, click [here](https://metamask.io/) to install MetaMask. 33 | 34 | ### Adding BNB Smart Chain Test Network to MetaMask Wallet 35 | 36 | Visit [ChainIDE](https://chainide.com/), create a project, and click on the "unconnected button" in the upper right corner, select the "Injected Web3 Provider" button, and then click the "MetaMask" to connect to the MetaMask wallet ("BNB Chain Mainnet" is the main network, and "BNB Chain Testnet" is the test network, click on the "BNB Chain Testnet" and it will be added to your MetaMask wallet. 37 | ![]() 38 | 39 | ### Enabling the BNB Smart Chain Test Network to Binance Wallet 40 | 41 | If you want to continue with Binance Wallet, install Binance Wallet, and After installing Binance Wallet, you need to enable "Show Test Networks" and switch to the "BNB Smart Chain Test Network". 42 | 43 | img 44 | 45 | ### Obtaining Test BNB tokens 46 | 47 | Once BNB Smart Chain Test Network has been added to MetaMask, navigate to the [BNB Smart Chain Faucet](https://testnet.binance.org/faucet-smart) to receive test tokens. Tokens are needed to pay for gas fees to deploy and interact with the smart contract. On the faucet page, paste your MetaMask wallet address. Then, click submit and the faucet will send you some test BNBs. 48 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/BNB_Smart_Chain_Faucet.png) 49 | 50 | ## Write down a Storage Smart Contract 51 | 52 | You need to write down all the required functions that you want to implement in your storage smart contract. A general storage smart contract has the following functions: 53 | 54 | - `Store()`: store value in variables 55 | - `retrieve()`: returns the stored value 56 | 57 | The ChainIDE team has prepared a simple storage smart contract that includes all the required functions; you may use this built-in template and add/delete functions according to your requirements. 58 | 59 | Visit the [ChainIDE site](https://chainide.com/) and click on "Try Now". 60 | 61 | ![](https://3869740696-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MYy-lqJKjq1m0yBAX4r%2Fuploads%2Fnpdf7fg51675wYmFcL6b%2Fimage.png?alt=media&token=353fc876-a319-49cb-92d5-1ed23c39aa90) 62 | 63 | Then, click on "New Project" and select "BNB Chain", and "Storage". 64 | 65 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/3_.png) 66 | 67 | Now, you can see the template contract, **Storage.sol**, that includes all the required functions. 68 | 69 | ## Compile a Storage Smart Contract 70 | 71 | After you have completed your smart contract, it is time to compile it. To compile, navigate to the "Compile", module, choose an appropriate compiler version according to your source code, and press the "Compile" button. An ABI and bytecode for the source code generate upon successful compilation. If there are some errors in your source code, they will be displayed under the output panel in the "Logger module". You may need to carefully read the error, resolve it accordingly and compile the contract again. 72 | 73 | Note down the compiler version and the license for your source code as it would be needed when you verify your smart contract on the BNB Smart Chain Test Network. 74 | 75 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/4.png) 76 | 77 | ## Deploy a Storage Smart Contract 78 | 79 | After successful compilation, it's time to deploy your compiled storage smart contract to the BNB Smart Chain Test Network. For that, you need to have a MetaMask installed, the BNB Smart Chain Test Network added to your wallet, and some testnet tokens to pay for the transaction fee. 80 | 81 | Navigate to the "Deploy & Interaction" module and choose the smart contract that you want to deploy among the compiled smart contracts and click the "deploy" button. For this tutorial, the `Storage` smart contract will be deployed. 82 | 83 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/5.png) 84 | 85 | ## Create a Flattened File using Flattener Library 86 | 87 | To verify a smart contract that imports other smart contracts, we need to create a flattened file, a flattened file including all the source code of imported contracts in a single file. To create a flattened file, you need to add a "Flattener" plug-in. 88 | 89 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/7.png) 90 | 91 | Once the Flatterner plug-in is activated, you'll be able to access it as a separate module as shown in the figure below. Choose the compiled file, and click on the flatten button to create a flattened file, once the flattened file is created, it will be automatically copied to the clipboard, you may paste it to a file and save it for later usage. 92 | 93 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/8.png) 94 | 95 | If you want to save the flattened file, click the save button, and a flattened file will be saved in the current repository. 96 | 97 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/9.png) 98 | 99 | The saved flattened file can be accessed under the explorer module. 100 | 101 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/10.png) 102 | 103 | ## Verify a Smart Contract 104 | 105 | To verify a smart contract, you need to visit [BNB Smart Chain Explorer](https://bscscan.com/) and search for the deployed smart contract using the contract address. 106 | 107 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/10.png) 108 | 109 | Click on the "verify and publish" link shown under the contract section. 110 | 111 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/11.png) 112 | 113 | Once you click on the verify and publish link, you will be asked for the following: 114 | 115 | - Contract Address: The address of a deployed smart contract that you want to verify 116 | - Compiler Type: Either you want to verify a single file or multiple files 117 | - Compiler Version: The compiler version that you used to compile the smart contract 118 | - License: Open-source license type that you used for your source code 119 | 120 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/12.png) 121 | 122 | After that, you need to paste the flattened file that you created in step 5, and your smart contract will be verified. 123 | 124 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/13.png) 125 | 126 | If there are no issues with your smart contract, it would be verified, and you'll be able to see an image similar to the one that is shown below. 127 | 128 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/14.png) 129 | 130 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/15.png) 131 | Congratulations, you have successfully deployed your smart contract to the blockchain and verified it, now it's time to interact with your deployed smart contract. 132 | 133 | ## Contract Interaction 134 | 135 | After successful deployment and verification. All the functions in the deployed smart contract can be seen in the "INTERACT" panel. In our scenario, we have two functions, `Store()` that is used to store the value to the blockchain, and `Retrieve()` to retrieve stored data from the blockchain. 136 | 137 | ![](https://d3gvnlbntpm4ho.cloudfront.net/Using+ChainIDE+BNB+Smart+Chain/6.png) 138 | 139 | 140 | ## Conclusion 141 | This tutorial guided you through the basics of creating and deploying a simple smart contract using the Chain IDE. It also provides step-by-step guide on how to verify your deployed smart contract. This tutorial uses testnet, however, the exact same instructions and sequence will work on the mainnet as well. 142 | -------------------------------------------------------------------------------- /04-Deploying-Smart-Contracts-Using-IDEs/hardhat.md: -------------------------------------------------------------------------------- 1 | 2 | # Using Hardhat for Deploying Smart Contracts on BSC 3 | 4 | In this tutorial, we explain step-by-step how to create, compile and deploy a simple smart contract on the BSC Testnet using Hardhat. 5 | 6 | ## What is Hardhat 7 | 8 | Hardhat is a development environment to compile, deploy, test, and debug your smart contract. 9 | 10 | ## Setting up the development environment 11 | 12 | There are a few technical requirements before we start. 13 | 14 | ### Pre-requisites 15 | 16 | There are a few technical requirements before we start as listed below: 17 | 18 | - [Node.js v10+ LTS and npm](https://nodejs.org/en/) (comes with Node) 19 | - [Git](https://git-scm.com/) 20 | - Create an empty project ```npm init --yes``` 21 | - Once your project is ready, run ```npm install --save-dev hardhat``` to install Hardhat. 22 | - Install hardhat toolbox ```npm install @nomicfoundation/hardhat-toolbox``` 23 | - To use your local installation of Hardhat, you need to use `npx` to run it (i.e. `npx hardhat`). 24 | 25 | ## Create A Project 26 | 27 | - To create your Hardhat project run ```npx hardhat``` in your project folder to intialize your project. 28 | - Select ```Create an empty hardhat.config.js``` with your keyboard and hit enter. 29 | 30 | ``` 31 | $ npx hardhat 32 | 888 888 888 888 888 33 | 888 888 888 888 888 34 | 888 888 888 888 888 35 | 8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 36 | 888 888 "88b 888P" d88" 888 888 "88b "88b 888 37 | 888 888 .d888888 888 888 888 888 888 .d888888 888 38 | 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. 39 | 888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 40 | 41 | Welcome to Hardhat v2.10.1 42 | 43 | √ What do you want to do? · Create a JavaScript project 44 | √ Hardhat project root: · Project-Directory 45 | √ Do you want to add a .gitignore? (Y/n) · y 46 | 47 | You need to install these dependencies to run the sample project: 48 | npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead. 49 | npm install --save-dev "hardhat@^2.10.1" "@nomicfoundation/hardhat-toolbox@^1.0.1" 50 | 51 | Project created 52 | 53 | See the README.md file for some example tasks you can run 54 | 55 | Give Hardhat a star on Github if you're enjoying it! 56 | 57 | https://github.com/NomicFoundation/hardhat 58 | ``` 59 | 60 | When Hardhat is run, it searches for the closest ```hardhat.config.js``` file starting from the current working directory. This file normally lives in the root of your project and an empty ```hardhat.config.js``` is enough for Hardhat to work. The entirety of your setup is contained in this file. 61 | 62 | 63 | ## Create Smart Contract 64 | 65 | You can write your own smart contract or download the [BEP20 token smart contract template](https://github.com/bnb-chain/bsc-genesis-contract/blob/master/contracts/bep20_template/BEP20Token.template), place it in the ```contracts``` directory of your project and remane it as ```BEP20Token.sol```. 66 | 67 | ## Configure Hardhat for BSC 68 | 69 | - Go to ```hardhat.config.js``` 70 | - Update the config with bsc-network-crendentials. 71 | 72 | ```js 73 | require("@nomicfoundation/hardhat-toolbox"); 74 | 75 | const { mnemonic } = require('./secrets.json'); 76 | 77 | // This is a sample Hardhat task. To learn how to create your own go to 78 | // https://hardhat.org/guides/create-task.html 79 | task("accounts", "Prints the list of accounts", async () => { 80 | const accounts = await ethers.getSigners(); 81 | 82 | for (const account of accounts) { 83 | console.log(account.address); 84 | } 85 | }); 86 | 87 | // You need to export an object to set up your config 88 | // Go to https://hardhat.org/config/ to learn more 89 | 90 | /** 91 | * @type import('hardhat/config').HardhatUserConfig 92 | */ 93 | module.exports = { 94 | defaultNetwork: "mainnet", 95 | networks: { 96 | localhost: { 97 | url: "http://127.0.0.1:8545" 98 | }, 99 | hardhat: { 100 | }, 101 | testnet: { 102 | url: "https://data-seed-prebsc-1-s1.binance.org:8545", 103 | chainId: 97, 104 | gasPrice: 20000000000, 105 | accounts: {mnemonic: mnemonic} 106 | }, 107 | mainnet: { 108 | url: "https://bsc-dataseed.binance.org/", 109 | chainId: 56, 110 | gasPrice: 20000000000, 111 | accounts: {mnemonic: mnemonic} 112 | } 113 | }, 114 | solidity: { 115 | version: "0.8.9", 116 | settings: { 117 | optimizer: { 118 | enabled: true 119 | } 120 | } 121 | }, 122 | paths: { 123 | sources: "./contracts", 124 | tests: "./test", 125 | cache: "./cache", 126 | artifacts: "./artifacts" 127 | }, 128 | mocha: { 129 | timeout: 20000 130 | } 131 | }; 132 | 133 | ``` 134 | 135 | :::note 136 | It requires mnemonic to be passed in for Provider, this is the seed phrase for the account you'd like to deploy from. Create a new `secrets.json` file in root directory and enter your 12 word mnemonic seed phrase to get started. To get the seedwords from metamask wallet you can go to Metamask Settings, then from the menu choose Security and Privacy where you will see a button that says reveal seed words. 137 | ``` 138 | Sample secrets.json 139 | 140 | { 141 | "mnemonic": "Your_12_Word_MetaMask_Seed_Phrase" 142 | } 143 | ``` 144 | ::: 145 | 146 | ## Compile Smart Contract 147 | 148 | To compile a Hardhat project, change to the root of the directory where the project is located and then type the following into a terminal: 149 | 150 | ``` 151 | npx hardhat compile 152 | ``` 153 | 154 | ## Deploy Smart Contract on BSC Network 155 | 156 | - Copy and paste the following content into the ```scripts/deploy.js``` file. 157 | 158 | ```js 159 | async function main() { 160 | const [deployer] = await ethers.getSigners(); 161 | 162 | console.log("Deploying contracts with the account:", deployer.address); 163 | 164 | console.log("Account balance:", (await deployer.getBalance()).toString()); 165 | 166 | const Token = await ethers.getContractFactory("BEP20Token"); 167 | const token = await Token.deploy(); 168 | 169 | console.log("Token address:", token.address); 170 | } 171 | 172 | main() 173 | .then(() => process.exit(0)) 174 | .catch((error) => { 175 | console.error(error); 176 | process.exit(1); 177 | }); 178 | 179 | ``` 180 | 181 | - Run this command in root of the project directory: 182 | 183 | ```js 184 | $ npx hardhat run --network testnet scripts/deploy.js 185 | ``` 186 | - Sample Output 187 | 188 | ``` 189 | $ npx hardhat run --network testnet scripts/deploy.js 190 | Deploying contracts with the account: 0x27cf2CEAcdedce834f1673005Ed1C60efA63c081 191 | Account balance: 100721709119999208161 192 | Token address: 0xbF39886B4F91F5170934191b0d96Dd277147FBB2 193 | ``` 194 | > Remember your address, transaction_hash and other details provided would differ, Above is just to provide an idea of structure. 195 | 196 | **Congratulations!** You have successfully deployed BEP20 Smart Contract. Now you can interact with the Smart Contract. 197 | 198 | You can check the deployment status here: or 199 | 200 | ## Verify with Hardhat 201 | 202 | Hardhat has an Etherscan plugin: [Hardhat Etherscan plugin](https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html) 203 | 204 | > Note: Hardhat was previously Buidler. 205 | 206 | ### Install the plugin 207 | 208 | ``` 209 | npm install --save-dev @nomiclabs/hardhat-etherscan 210 | ``` 211 | 212 | ### Configure the EthereScan plugin in hardhat.config.js 213 | 214 | - Step1: Add ```require("@nomiclabs/hardhat-etherscan");``` 215 | - Step2: Add your Bscscan API key. Register and obtain your API key from . 216 | - Step3: Always remember to set the solidity compiler version to match what was used for deploying the smart contract. 217 | 218 | !!! warning 219 | Keep your API key as secret and never it commit to version control 220 | 221 | 222 | ```js 223 | // hardhat.config.js 224 | const { mnemonic, bscscanApiKey } = require('./secrets.json'); 225 | 226 | require('@nomiclabs/hardhat-ethers'); 227 | require("@nomiclabs/hardhat-etherscan"); 228 | /** 229 | * @type import('hardhat/config').HardhatUserConfig 230 | */ 231 | module.exports = { 232 | 233 | networks: { 234 | testnet: { 235 | url: `https://data-seed-prebsc-1-s1.binance.org:8545`, 236 | accounts: {mnemonic: mnemonic} 237 | }, 238 | mainnet: { 239 | url: `https://bsc-dataseed.binance.org/`, 240 | accounts: {mnemonic: mnemonic} 241 | } 242 | }, 243 | 244 | etherscan: { 245 | // Your API key for Etherscan 246 | // Obtain one at https://bscscan.com/ 247 | apiKey: bscscanApiKey 248 | }, 249 | solidity: "0.8.9" 250 | }; 251 | ``` 252 | ### Verify Command 253 | !!! warning 254 | Remove any unnecessary contracts and clear the artifacts otherwise these will also be part of the verified contract. 255 | 256 | Run the following command: 257 | 258 | ``` 259 | npx buidler verify --network mainnet DEPLOYED_CONTRACT_ADDRESS "Constructor argument 1" 260 | ``` 261 | 262 | * Example 263 | 264 | ```shell 265 | $ npx hardhat verify --network testnet 0xbF39886B4F91F5170934191b0d96Dd277147FBB2 266 | Nothing to compile 267 | Compiling 1 file with 0.5.16 268 | Successfully submitted source code for contract 269 | contracts/BEP20Token.sol:BEP20Token at 0xbF39886B4F91F5170934191b0d96Dd277147FBB2 270 | for verification on Etherscan. Waiting for verification result... 271 | 272 | Successfully verified contract BEP20Token on Etherscan. 273 | https://testnet.bscscan.com/address/0xbF39886B4F91F5170934191b0d96Dd277147FBB2#code 274 | ``` 275 | 276 | ## Conclusion 277 | This tutorial guided you through the basics of creating and deploying a simple smart contract using the Hardhat IDE. It also provides step-by-step guide on how to verify your deployed smart contract. This tutorial uses testnet, however, the exact same instructions and sequence will work on the mainnet as well. -------------------------------------------------------------------------------- /04-Deploying-Smart-Contracts-Using-IDEs/remixide.md: -------------------------------------------------------------------------------- 1 | 2 | # Using Remix IDE for Deploying Smart Contracts on BSC 3 | 4 | In this tutorial, we provide guidelines on how to create, compile, and deploy a simple Hello World smart contract on BSC using the [Remix IDE](https://remix.ethereum.org/). 5 | 6 | ### Pre-requisites 7 | There is no need for any local environment settings for deploying solidity smart contracts on BSC using the Remix IDE. 8 | 9 | All you require is a browser-based Web3 wallet (e.g. MetaMask) to interact with the BSC Testnet and deployed contracts. If you are already using MetaMask, it is recommended to create a new account for testing with Replit. You can do this from the account menu, which appears when you click on the account avatar in the top right corner of MetaMask interface. 10 | 11 | You must set up all of the following Pre-requisites to be able to deploy your solidity smart contract on BSC: 12 | 13 | * [Download Metamask wallet](https://metamask.io/) 14 | * [Configure BNB Smart Chain Testnet on Metamask](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain) 15 | * [Get BNB testnet tokens](https://testnet.binance.org/faucet-smart) 16 | 17 | ### Setting Up Remix IDE 18 | 19 | - Remix is an online IDE to develop smart contracts. 20 | - You need to choose Solidity Compiler, Choose the appropriate compiler version. We used 0.8.15 for this tutorial. 21 | 22 | 23 | 24 | ## Writing the Smart Contract 25 | 26 | - Create a new file, name it ```HelloWorld.sol```, and copy the contract code given below 27 | 28 | ``` 29 | // SPDX-License-Identifier: MIT 30 | pragma solidity ^0.8.15; 31 | contract HelloWorld { 32 | function sayHelloWorld() public pure returns (string memory) { 33 | return "Hello World"; 34 | } 35 | } 36 | ``` 37 | 38 | The first line, `pragma solidity ^0.8.15` specifies that the source code is for a Solidity version greater than 0.8.15. [Pragmas](https://solidity.readthedocs.io/en/latest/layout-of-source-files.html#pragma) are common instructions for compilers about how to treat the source code (e.g., pragma once). 39 | 40 | A contract in the sense of Solidity is a collection of code (its functions) and data (its state) that resides at a specific address on the Ethereum blockchain. Learn more about the [constructor](https://solidity.readthedocs.io/en/latest/contracts.html#constructor) and [memory](https://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html#storage-memory-and-the-stack) in the docs. 41 | 42 | ## Compile Smart Contract 43 | 44 | - Step1: Click button to switch to compile page. 45 | 46 | - Step2: Select the appropriate compiler version, 0.8.15 in our case. 47 | 48 | - Step3: Enable "Auto compile" and "Optimization" from Advanced Configurations, 49 | 50 | - Step4: Select "HelloWorld" from the contract drop-down menu. 51 | 52 | - Step5: Click "ABI" to copy the contract ABI and save it. 53 | 54 | img 55 | 56 | ## Configure MetaMask and Fund Your Account 57 | 58 | Now, We have to deploy our smart contract on BNB Smart Chain Network. For that, we have to connect to Web3 world, this can be done by many services like MetaMask, Brave, Portis etc. We will be using MetaMask. Please follow this [tutorial to setup a Metamask Account](wallet/metamask.md) for configuring the MetaMask wallet to use with BSC. 59 | 60 | 61 | - Open Metamask and select Custom RPC from the networks dropdown 62 | 63 | - Go to setting page 64 | 65 | img 66 | 67 | - Add a new network 68 | 69 | img 70 | 71 | * Testnet 72 | * [RPC URLs](./rpc.md) 73 | * ChainID: 97 74 | * Symbol: BNB 75 | * Block Explorer: https://testnet.bscscan.com 76 | 77 | * Mainnet 78 | * [RPC URLs](./rpc.md) 79 | * ChainID: 56 80 | * Symbol: BNB 81 | * Block Explorer: https://bscscan.com 82 | 83 | - Go ahead and click save 84 | - Copy your address from Metamask 85 | 86 | - Head over to [Faucet](https://testnet.binance.org/faucet-smart) and request test BNB 87 | 88 | ## Deploy Smart Contract 89 | 90 | Follow the following steps to deploy the HelloWorld smart contract on the BNB Smart Chain Testnet. 91 | 92 | img 93 | 94 | - Step1: Navigate to the Deployment Page. 95 | - Step2: Select Injected Provider in the Environment dropdown 96 | - Step3: Confirm the Connection Request on the MetaMask notification. 97 | 98 | img 99 | 100 | - Step4: Once Metamask is connected to Remix, click on the "Deploy" button which would generate another metamask popup that requires transaction confirmation. 101 | 102 | img 103 | 104 | **Congratulations!** You have successfully deployed a simple Smart Contract on the BSC Testnet. Now you can interact with the Smart Contract. Check the deployment status here: 105 | 106 | # Flatten and Verify the deployed contract on BscScan 107 | 108 | The first and foremost step is to flatten the solidity contract into a single file to be able to get it verified on [BscScan](https://testnet.bscscan.com/). 109 | 110 | ### Flatten the Smart Contract Code 111 | 112 | * Install [Truffle Flattener](https://github.com/nomiclabs/truffle-flattener) by running the command ```npm install truffle-flattener``` 113 | * Flatten the contract by running the command in the ```npx truffle-flattener HelloWorld.sol > FlatHelloWorld.sol``` contracts directory 114 | * Clean up the licensing information. 115 | * The flattened contract will have the same licensing note imported from each of the files. 116 | * Multiple licensing notes in one file break the BscScan verification, so you have to leave one licensing note for the entirety of the flattened contract. 117 | * The easiest way to clean up is to search for the SPDX mentions in the file and remove all of them except for the very first one. 118 | 119 | ### Using Flattened Code to Verify 120 | At this point, you have your flattened and cleaned-up contract ready for the BscScan verification. 121 | * Go to [BscScan Testnet](https://testnet.bscscan.com/). 122 | * Find your deployed contract by searching it using its address. 123 | * On the main page of BscScan, on the header click **Misc > Verify Contract.** 124 | * In Compiler Type, select **Solidity (Single file)**. 125 | * In Compiler Version, select **v0.8.15**. This is the version this tutorial used to compile the contract. 126 | * In Open Source License Type, select **MIT License (MIT)**. 127 | * Click **Continue**. 128 | * Keep the **Optimization** option set to **No** as Remix does not use optimization by default. 129 | * Paste the entirety of your flattened .sol contract in the **Enter the Solidity Contract Code below** field. 130 | * Click **Verify and Publish**. 131 | * BscScan will take a few seconds to compile your contract, verify, and publish it. 132 | 133 | 134 | ## Conclusion 135 | This tutorial guided you through the basics of creating and deploying a simple smart contract using the Remix IDE and MetaMask Web Wallet. It also provides step-by-step guide on how to verify and publish your deployed smart contract. This tutorial uses testnet, however, the exact same instructions and sequence will work on the mainnet as well. -------------------------------------------------------------------------------- /04-Deploying-Smart-Contracts-Using-IDEs/replit.md: -------------------------------------------------------------------------------- 1 | # Using Replit IDE for Deploying Smart Contracts on BSC 2 | 3 | [Replit](https://docs.replit.com/tutorials/01-introduction-to-the-repl-it-ide) is a coding platform that allows you to write code and host apps. Replit supports [Solidity programming language](https://replit.com/@replit/Solidity-starter-beta?v=1) and provides all of the features and functionality that are required by Web3 developers for creating and deploying smart contracts. 4 | 5 | In this tutorial, we explain how to build and deploy a solidity smart contract on the BSC Testnet using the [Replit IDE](https://replit.com/signup) and the [Replit Solidity Template (Solidity starter beta)](https://replit.com/@replit/Solidity-starter-beta?v=1) 6 | 7 | :::note 8 | For additional examples about Solidity with Replit, you can read the article **[Get started with Replit!](https://blog.replit.com/solidity)** or check **[Replit Solidity documentation and Escrow contract tutorial](https://docs.replit.com/tutorials/33-escrow-contract-with-solidity)** 9 | ::: 10 | 11 | ## Pre-Requisites 12 | 13 | There is no need for any local environment settings for deploying solidity smart contracts on BSC using Replit. 14 | 15 | All you require is a browser-based Web3 wallet (e.g. MetaMask) to interact with the BSC Testnet and deployed contracts. If you are already using MetaMask, it is recommended to create a new account for testing with Replit. You can do this from the account menu, which appears when you click on the account avatar in the top right corner of MetaMask interface. 16 | 17 | You must set up all of the following Pre-requisites to be able to deploy your solidity smart contract on BSC: 18 | 19 | 1. [Create a Replit account](https://replit.com/signup) 20 | 2. [Download Metamask wallet](https://metamask.io/) 21 | 3. [Configure BNB Smart Chain Testnet on Metamask](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain) 22 | 4. [Get BNB testnet tokens](https://testnet.binance.org/faucet-smart) 23 | 24 | ## Working with a Repl 25 | 26 | Every [Repl](https://docs.replit.com/getting-started/using-replit-free#repls) that you create is a fully functional development and production environment. Follow the steps to create a solidity starter Repl: 27 | 28 | 1. [Login](https://replit.com/login) or [create an account](https://replit.com/signup). After creating your [Replit account](https://docs.replit.com/tutorials/01-introduction-to-the-repl-it-ide), your home screen will include a dashboard where you can view, create projects, and manage your account. 29 | 2. Once logged in, create a Solidity starter repl, Select **+ Create Repl** from the left panel or **+** in the top right corner of the screen. 30 | 3. Select the [**Solidity starter (beta)**](https://replit.com/@replit/Solidity-starter-beta?v=1) template and specify a title for your project. 31 | 4. Click on **+ Create Repl** for creating your project. 32 | 33 | > **Note** 34 | The Solidity starter repl comes with a friendly web interface, built using the **[Web3 Ethereum JavaScript API](https://web3js.readthedocs.io/en/v1.5.2/)**, which you can use to deploy and interact with your smart contracts. For this tutorial, we will deploy smart contract on to BNB Smart Chain Testnet. 35 | 36 | ## Create Smart Contract 37 | Delete the contents of the contract.sol file and paste the following solidity code into this file. 38 | 39 | ![image](https://user-images.githubusercontent.com/93580180/189648710-7185193d-b705-4453-99f6-51cfa103499e.png) 40 | 41 | ## Deploy on BSC 42 | 43 | Make sure that you have followed the list of Pre-requisites above so that you are ready to deploy and interact with your smart contract: 44 | 45 | 1. Click on **Run** (at the Top) to install all relevant packages and start up the contract deployment UI. 46 | 2. Click on ![image](https://user-images.githubusercontent.com/93580180/189651036-d5c68e4d-9154-4f36-a9b1-09ddb75bf64c.png) icon to open the web interface for deloyment in a new browser tab. 47 | 3. Connect your MetaMask wallet to the web interface and switch to the [BSC Testnet](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain). 48 | 4. Click on **Connect wallet**, select your account, then choose Connect. 49 | 50 | ![image](https://user-images.githubusercontent.com/93580180/189649199-320b56ef-8cf8-44f7-a90d-d4a640c4521f.png) 51 | 52 | ![image](https://user-images.githubusercontent.com/93580180/189649134-41518f50-054f-4d5d-9b37-9af57bd16526.png) 53 | 54 | 5. From the Drop-down list, Select the contract that you want to deploy. Click on **Deploy**. 55 | 56 | ![image](https://user-images.githubusercontent.com/93580180/189649368-75a8e91d-3225-48f9-81f4-3bc1c2f5a7a5.png) 57 | 58 | 6. Approve the MetaMask notification that appears asking for confirmation of the transaction from your wallet to deploy the smart contract. 59 | 60 | ![image](https://user-images.githubusercontent.com/93580180/189649422-4677b218-4292-43dd-8c7f-c9c14d6604fe.png) 61 | 62 | 7. Copy the address of the deployed contract. 63 | 64 | ![image](https://user-images.githubusercontent.com/93580180/189649474-8ba1660f-ee56-4284-bdf7-e216161409f5.png) 65 | 66 | 8. [Navigate to BscScan Testnet Explorer](https://testnet.bscscan.com/) to search and view your deployed contract. Using the contract address to search for it. 67 | 68 | ![image](https://user-images.githubusercontent.com/93580180/189649528-73701873-9a32-41cc-9276-fe1daafe809d.png) 69 | 70 | Once your contract has been deployed, it will show up as expandable boxes below the drop-down box. Expand it and take a look at all the different functions available. You can now interact with your contract using the provided user interface or from a sharable URL shown on the interface. 71 | 72 | ![image](https://user-images.githubusercontent.com/93580180/189649592-5ce05a4f-1961-41f3-9a97-e0b11f54a470.png) 73 | 74 | ## Publish to Replit​ 75 | 76 | Replit allows you to publish your projects to a personal profile. After publishing, projects will show up on your spotlight page for others to explore, interact with, clone, and collaborate. 77 | 78 | See [Publish your Repl](https://docs.replit.com/hosting/sharing-your-repl#publish-your-repl). 79 | 80 | ## Conclusion 81 | This tutorial guided you through the basics of creating and deploying a smart contract using the Replit IDE. We also provided steps on how to interact with the deployed contract online and publish your replit project. This tutorial uses testnet, however, the exact same instructions and sequence will work on the mainnet as well. 82 | -------------------------------------------------------------------------------- /04-Deploying-Smart-Contracts-Using-IDEs/truffle.md: -------------------------------------------------------------------------------- 1 | 2 | # Using Remix IDE for Deploying Smart Contracts on BSC 3 | 4 | In this tutorial, we provide guidelines on how to create, compile, and deploy a simple Hello World smart contract on BSC using the [Remix IDE](https://remix.ethereum.org/). 5 | 6 | ### Pre-requisites 7 | There is no need for any local environment settings for deploying solidity smart contracts on BSC using the Remix IDE. 8 | 9 | All you require is a browser-based Web3 wallet (e.g. MetaMask) to interact with the BSC Testnet and deployed contracts. If you are already using MetaMask, it is recommended to create a new account for testing with Replit. You can do this from the account menu, which appears when you click on the account avatar in the top right corner of MetaMask interface. 10 | 11 | You must set up all of the following Pre-requisites to be able to deploy your solidity smart contract on BSC: 12 | 13 | * [Download Metamask wallet](https://metamask.io/) 14 | * [Configure BNB Smart Chain Testnet on Metamask](https://academy.binance.com/en/articles/connecting-metamask-to-binance-smart-chain) 15 | * [Get BNB testnet tokens](https://testnet.binance.org/faucet-smart) 16 | 17 | ### Setting Up Remix IDE 18 | 19 | - Remix is an online IDE to develop smart contracts. 20 | - You need to choose Solidity Compiler, Choose the appropriate compiler version. We used 0.8.15 for this tutorial. 21 | 22 | 23 | 24 | ## Writing the Smart Contract 25 | 26 | - Create a new file, name it ```HelloWorld.sol```, and copy the contract code given below 27 | 28 | ``` 29 | // SPDX-License-Identifier: MIT 30 | pragma solidity ^0.8.15; 31 | contract HelloWorld { 32 | function sayHelloWorld() public pure returns (string memory) { 33 | return "Hello World"; 34 | } 35 | } 36 | ``` 37 | 38 | The first line, `pragma solidity ^0.8.15` specifies that the source code is for a Solidity version greater than 0.8.15. [Pragmas](https://solidity.readthedocs.io/en/latest/layout-of-source-files.html#pragma) are common instructions for compilers about how to treat the source code (e.g., pragma once). 39 | 40 | A contract in the sense of Solidity is a collection of code (its functions) and data (its state) that resides at a specific address on the Ethereum blockchain. Learn more about the [constructor](https://solidity.readthedocs.io/en/latest/contracts.html#constructor) and [memory](https://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html#storage-memory-and-the-stack) in the docs. 41 | 42 | ## Compile Smart Contract 43 | 44 | - Step1: Click button to switch to compile page. 45 | 46 | - Step2: Select the appropriate compiler version, 0.8.15 in our case. 47 | 48 | - Step3: Enable "Auto compile" and "Optimization" from Advanced Configurations, 49 | 50 | - Step4: Select "HelloWorld" from the contract drop-down menu. 51 | 52 | - Step5: Click "ABI" to copy the contract ABI and save it. 53 | 54 | img 55 | 56 | ## Configure MetaMask and Fund Your Account 57 | 58 | Now, We have to deploy our smart contract on BNB Smart Chain Network. For that, we have to connect to Web3 world, this can be done by many services like MetaMask, Brave, Portis etc. We will be using MetaMask. Please follow this [tutorial to setup a Metamask Account](wallet/metamask.md) for configuring the MetaMask wallet to use with BSC. 59 | 60 | 61 | - Open Metamask and select Custom RPC from the networks dropdown 62 | 63 | - Go to setting page 64 | 65 | img 66 | 67 | - Add a new network 68 | 69 | img 70 | 71 | * Testnet 72 | * [RPC URLs](./rpc.md) 73 | * ChainID: 97 74 | * Symbol: BNB 75 | * Block Explorer: https://testnet.bscscan.com 76 | 77 | * Mainnet 78 | * [RPC URLs](./rpc.md) 79 | * ChainID: 56 80 | * Symbol: BNB 81 | * Block Explorer: https://bscscan.com 82 | 83 | - Go ahead and click save 84 | - Copy your address from Metamask 85 | 86 | - Head over to [Faucet](https://testnet.binance.org/faucet-smart) and request test BNB 87 | 88 | ## Deploy Smart Contract 89 | 90 | Follow the following steps to deploy the HelloWorld smart contract on the BNB Smart Chain Testnet. 91 | 92 | img 93 | 94 | - Step1: Navigate to the Deployment Page. 95 | - Step2: Select Injected Provider in the Environment dropdown 96 | - Step3: Confirm the Connection Request on the MetaMask notification. 97 | 98 | img 99 | 100 | - Step4: Once Metamask is connected to Remix, click on the "Deploy" button which would generate another metamask popup that requires transaction confirmation. 101 | 102 | img 103 | 104 | **Congratulations!** You have successfully deployed a simple Smart Contract on the BSC Testnet. Now you can interact with the Smart Contract. Check the deployment status here: 105 | 106 | # Flatten and Verify the deployed contract on BscScan 107 | 108 | The first and foremost step is to flatten the solidity contract into a single file to be able to get it verified on [BscScan](https://testnet.bscscan.com/). 109 | 110 | ### Flatten the Smart Contract Code 111 | 112 | * Install [Truffle Flattener](https://github.com/nomiclabs/truffle-flattener) by running the command ```npm install truffle-flattener``` 113 | * Flatten the contract by running the command in the ```npx truffle-flattener HelloWorld.sol > FlatHelloWorld.sol``` contracts directory 114 | * Clean up the licensing information. 115 | * The flattened contract will have the same licensing note imported from each of the files. 116 | * Multiple licensing notes in one file break the BscScan verification, so you have to leave one licensing note for the entirety of the flattened contract. 117 | * The easiest way to clean up is to search for the SPDX mentions in the file and remove all of them except for the very first one. 118 | 119 | ### Using Flattened Code to Verify 120 | At this point, you have your flattened and cleaned-up contract ready for the BscScan verification. 121 | * Go to [BscScan Testnet](https://testnet.bscscan.com/). 122 | * Find your deployed contract by searching it using its address. 123 | * On the main page of BscScan, on the header click **Misc > Verify Contract.** 124 | * In Compiler Type, select **Solidity (Single file)**. 125 | * In Compiler Version, select **v0.8.15**. This is the version this tutorial used to compile the contract. 126 | * In Open Source License Type, select **MIT License (MIT)**. 127 | * Click **Continue**. 128 | * Keep the **Optimization** option set to **No** as Remix does not use optimization by default. 129 | * Paste the entirety of your flattened .sol contract in the **Enter the Solidity Contract Code below** field. 130 | * Click **Verify and Publish**. 131 | * BscScan will take a few seconds to compile your contract, verify, and publish it. 132 | 133 | 134 | ## Conclusion 135 | This tutorial guided you through the basics of creating and deploying a simple smart contract using the Remix IDE and MetaMask Web Wallet. It also provides step-by-step guide on how to verify and publish your deployed smart contract. This tutorial uses testnet, however, the exact same instructions and sequence will work on the mainnet as well. -------------------------------------------------------------------------------- /05-Estimate-L2-Transaction-Gas-Cost/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/05-Estimate-L2-Transaction-Gas-Cost/.DS_Store -------------------------------------------------------------------------------- /05-Estimate-L2-Transaction-Gas-Cost/sdk-estimate-gas/.env: -------------------------------------------------------------------------------- 1 | # Put the mnemonic for an account on opBNB here 2 | MNEMONIC="" 3 | 4 | # URL to access BNB smart chain testnet 5 | L1URL="https://data-seed-prebsc-1-s1.bnbchain.org:8545" 6 | 7 | # URL to access opBNB testnet 8 | L2URL="https://opbnb-testnet-rpc.bnbchain.org" -------------------------------------------------------------------------------- /05-Estimate-L2-Transaction-Gas-Cost/sdk-estimate-gas/Greeter.json: -------------------------------------------------------------------------------- 1 | { 2 | "_format": "hh-sol-artifact-1", 3 | "contractName": "Greeter", 4 | "sourceName": "contracts/Greeter.sol", 5 | "abi": [ 6 | { 7 | "inputs": [ 8 | { 9 | "internalType": "string", 10 | "name": "_greeting", 11 | "type": "string" 12 | } 13 | ], 14 | "stateMutability": "nonpayable", 15 | "type": "constructor" 16 | }, 17 | { 18 | "inputs": [], 19 | "name": "greet", 20 | "outputs": [ 21 | { 22 | "internalType": "string", 23 | "name": "", 24 | "type": "string" 25 | } 26 | ], 27 | "stateMutability": "view", 28 | "type": "function" 29 | }, 30 | { 31 | "inputs": [ 32 | { 33 | "internalType": "string", 34 | "name": "_greeting", 35 | "type": "string" 36 | } 37 | ], 38 | "name": "setGreeting", 39 | "outputs": [], 40 | "stateMutability": "nonpayable", 41 | "type": "function" 42 | } 43 | ], 44 | "bytecode": "0x60806040523480156200001157600080fd5b5060405162000c3238038062000c32833981810160405281019062000037919062000278565b6200006760405180606001604052806022815260200162000c1060229139826200008760201b620001ce1760201c565b80600090805190602001906200007f92919062000156565b5050620004c5565b620001298282604051602401620000a0929190620002fe565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506200012d60201b60201c565b5050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b8280546200016490620003ea565b90600052602060002090601f016020900481019282620001885760008555620001d4565b82601f10620001a357805160ff1916838001178555620001d4565b82800160010185558215620001d4579182015b82811115620001d3578251825591602001919060010190620001b6565b5b509050620001e39190620001e7565b5090565b5b8082111562000202576000816000905550600101620001e8565b5090565b60006200021d620002178462000362565b62000339565b9050828152602081018484840111156200023657600080fd5b62000243848285620003b4565b509392505050565b600082601f8301126200025d57600080fd5b81516200026f84826020860162000206565b91505092915050565b6000602082840312156200028b57600080fd5b600082015167ffffffffffffffff811115620002a657600080fd5b620002b4848285016200024b565b91505092915050565b6000620002ca8262000398565b620002d68185620003a3565b9350620002e8818560208601620003b4565b620002f381620004b4565b840191505092915050565b600060408201905081810360008301526200031a8185620002bd565b90508181036020830152620003308184620002bd565b90509392505050565b60006200034562000358565b905062000353828262000420565b919050565b6000604051905090565b600067ffffffffffffffff82111562000380576200037f62000485565b5b6200038b82620004b4565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015620003d4578082015181840152602081019050620003b7565b83811115620003e4576000848401525b50505050565b600060028204905060018216806200040357607f821691505b602082108114156200041a576200041962000456565b5b50919050565b6200042b82620004b4565b810181811067ffffffffffffffff821117156200044d576200044c62000485565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b61073b80620004d56000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae321714610057575b600080fd5b6100556004803603810190610050919061043d565b610075565b005b61005f61013c565b60405161006c91906104b7565b60405180910390f35b6101226040518060600160405280602381526020016106e3602391396000805461009e90610610565b80601f01602080910402602001604051908101604052809291908181526020018280546100ca90610610565b80156101175780601f106100ec57610100808354040283529160200191610117565b820191906000526020600020905b8154815290600101906020018083116100fa57829003601f168201915b50505050508361026a565b8060009080519060200190610138929190610332565b5050565b60606000805461014b90610610565b80601f016020809104026020016040519081016040528092919081815260200182805461017790610610565b80156101c45780601f10610199576101008083540402835291602001916101c4565b820191906000526020600020905b8154815290600101906020018083116101a757829003601f168201915b5050505050905090565b61026682826040516024016101e49291906104d9565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b5050565b61030483838360405160240161028293929190610510565b6040516020818303038152906040527f2ced7cef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b82805461033e90610610565b90600052602060002090601f01602090048101928261036057600085556103a7565b82601f1061037957805160ff19168380011785556103a7565b828001600101855582156103a7579182015b828111156103a657825182559160200191906001019061038b565b5b5090506103b491906103b8565b5090565b5b808211156103d15760008160009055506001016103b9565b5090565b60006103e86103e384610581565b61055c565b90508281526020810184848401111561040057600080fd5b61040b8482856105ce565b509392505050565b600082601f83011261042457600080fd5b81356104348482602086016103d5565b91505092915050565b60006020828403121561044f57600080fd5b600082013567ffffffffffffffff81111561046957600080fd5b61047584828501610413565b91505092915050565b6000610489826105b2565b61049381856105bd565b93506104a38185602086016105dd565b6104ac816106d1565b840191505092915050565b600060208201905081810360008301526104d1818461047e565b905092915050565b600060408201905081810360008301526104f3818561047e565b90508181036020830152610507818461047e565b90509392505050565b6000606082019050818103600083015261052a818661047e565b9050818103602083015261053e818561047e565b90508181036040830152610552818461047e565b9050949350505050565b6000610566610577565b90506105728282610642565b919050565b6000604051905090565b600067ffffffffffffffff82111561059c5761059b6106a2565b5b6105a5826106d1565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b82818337600083830152505050565b60005b838110156105fb5780820151818401526020810190506105e0565b8381111561060a576000848401525b50505050565b6000600282049050600182168061062857607f821691505b6020821081141561063c5761063b610673565b5b50919050565b61064b826106d1565b810181811067ffffffffffffffff8211171561066a576106696106a2565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f830116905091905056fe4368616e67696e67206772656574696e672066726f6d202725732720746f2027257327a264697066735822122062b06e5bdee39e73f7ae7ef8606fe9f23da851629e4e297316ce7747f5074b1964736f6c634300080400334465706c6f79696e67206120477265657465722077697468206772656574696e673a", 45 | "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063cfae321714610057575b600080fd5b6100556004803603810190610050919061043d565b610075565b005b61005f61013c565b60405161006c91906104b7565b60405180910390f35b6101226040518060600160405280602381526020016106e3602391396000805461009e90610610565b80601f01602080910402602001604051908101604052809291908181526020018280546100ca90610610565b80156101175780601f106100ec57610100808354040283529160200191610117565b820191906000526020600020905b8154815290600101906020018083116100fa57829003601f168201915b50505050508361026a565b8060009080519060200190610138929190610332565b5050565b60606000805461014b90610610565b80601f016020809104026020016040519081016040528092919081815260200182805461017790610610565b80156101c45780601f10610199576101008083540402835291602001916101c4565b820191906000526020600020905b8154815290600101906020018083116101a757829003601f168201915b5050505050905090565b61026682826040516024016101e49291906104d9565b6040516020818303038152906040527f4b5c4277000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b5050565b61030483838360405160240161028293929190610510565b6040516020818303038152906040527f2ced7cef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610309565b505050565b60008151905060006a636f6e736f6c652e6c6f679050602083016000808483855afa5050505050565b82805461033e90610610565b90600052602060002090601f01602090048101928261036057600085556103a7565b82601f1061037957805160ff19168380011785556103a7565b828001600101855582156103a7579182015b828111156103a657825182559160200191906001019061038b565b5b5090506103b491906103b8565b5090565b5b808211156103d15760008160009055506001016103b9565b5090565b60006103e86103e384610581565b61055c565b90508281526020810184848401111561040057600080fd5b61040b8482856105ce565b509392505050565b600082601f83011261042457600080fd5b81356104348482602086016103d5565b91505092915050565b60006020828403121561044f57600080fd5b600082013567ffffffffffffffff81111561046957600080fd5b61047584828501610413565b91505092915050565b6000610489826105b2565b61049381856105bd565b93506104a38185602086016105dd565b6104ac816106d1565b840191505092915050565b600060208201905081810360008301526104d1818461047e565b905092915050565b600060408201905081810360008301526104f3818561047e565b90508181036020830152610507818461047e565b90509392505050565b6000606082019050818103600083015261052a818661047e565b9050818103602083015261053e818561047e565b90508181036040830152610552818461047e565b9050949350505050565b6000610566610577565b90506105728282610642565b919050565b6000604051905090565b600067ffffffffffffffff82111561059c5761059b6106a2565b5b6105a5826106d1565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b82818337600083830152505050565b60005b838110156105fb5780820151818401526020810190506105e0565b8381111561060a576000848401525b50505050565b6000600282049050600182168061062857607f821691505b6020821081141561063c5761063b610673565b5b50919050565b61064b826106d1565b810181811067ffffffffffffffff8211171561066a576106696106a2565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f830116905091905056fe4368616e67696e67206772656574696e672066726f6d202725732720746f2027257327a264697066735822122062b06e5bdee39e73f7ae7ef8606fe9f23da851629e4e297316ce7747f5074b1964736f6c63430008040033", 46 | "linkReferences": {}, 47 | "deployedLinkReferences": {} 48 | } 49 | -------------------------------------------------------------------------------- /05-Estimate-L2-Transaction-Gas-Cost/sdk-estimate-gas/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## How to estimate opBNB Layer 2 transaction gas and gas cost 4 | 5 | opBNB leverages the Optimism OP Stack to build the high performance and low cost Layer 2 solution. 6 | 7 | To develop and deploy your own Layer 2 applications on opBNB, you can use the [OP Stack SDK](https://sdk.optimism.io/), which provides a simple and intuitive interface for working with the OP Stack. The OP Stack SDK allows you to estimate the gas usage and gas cost of both the Layer 1 and Layer 2 components of your Layer 2 transactions, so you can optimize your code and minimize your fees. 8 | 9 | Estimate the Layer 1 gas of a particular Layer 2 transaction 10 | 11 | https://sdk.optimism.io/modules.html#estimateL1Gas 12 | 13 | Estimate the Layer 1 gas cost of a particular Layer 2 transaction in wei 14 | 15 | https://sdk.optimism.io/modules.html#estimateL1GasCost 16 | 17 | Similar it also supports the Layer 2 part gas cost 18 | 19 | https://sdk.optimism.io/modules.html#estimateL2GasCost 20 | 21 | And total cost of the Layer 2 transaction 22 | 23 | https://sdk.optimism.io/modules.html#estimateL2GasCost 24 | 25 | You only need to make minor changes to your existing codebase to use the OP Stack SDK. 26 | 27 | 28 | **ENV settings** 29 | 30 | Please configure your mnemonic in the .env file, and the URL is preconfigured to the opBNB testnet and BSC testnet. 31 | 32 | 33 | ```shell 34 | # Put the mnemonic for an account on opBNB here 35 | 36 | MNEMONIC="" 37 | 38 | # URL to access BNB smart chain testnet 39 | 40 | L1URL="https://data-seed-prebsc-1-s1.bnbchain.org:8545" 41 | 42 | # URL to access opBNB testnet 43 | 44 | L2URL="https://opbnb-testnet-rpc.bnbchain.org" 45 | ``` 46 | 47 | 48 | 49 | **Steps to run** 50 | 51 | Go the directory of the sdk-estimate-gas 52 | 53 | ```shell 54 | cd sdk-estimate-gas 55 | yarn install 56 | node gas.js --network=testnet 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /05-Estimate-L2-Transaction-Gas-Cost/sdk-estimate-gas/gas.js: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/node 2 | 3 | // Estimate the costs of an opBNB 4 | 5 | const ethers = require("ethers") 6 | const optimismSDK = require("@eth-optimism/sdk") 7 | const fs = require("fs") 8 | require('dotenv').config() 9 | const yargs = require("yargs") 10 | const { 11 | boolean 12 | } = require("yargs") 13 | 14 | 15 | const argv = yargs 16 | .option('network', { 17 | // All of those choices are : 18 | // mainnet - opBNB Mainnet, the production network, not live yet 19 | // testnet - opBNB testnet 20 | choices: ["mainnet", "testnet"], 21 | description: 'L2 network to use' 22 | }). 23 | option('verify', { 24 | type: boolean, 25 | description: 'Run the transaction, compare to the estimate' 26 | }) 27 | .help() 28 | .alias('help', 'h').argv; 29 | 30 | 31 | const words = process.env.MNEMONIC.match(/[a-zA-Z]+/g).length 32 | validLength = [12, 15, 18, 24] 33 | if (!validLength.includes(words)) { 34 | console.log(`The mnemonic (${process.env.MNEMONIC}) is the wrong number of words`) 35 | process.exit(-1) 36 | } 37 | 38 | const greeterJSON = JSON.parse(fs.readFileSync("Greeter.json")) 39 | 40 | const greeterAddrs = { 41 | "mainnet": "0xcf210488dad6da5fe54d260c45253afc3a9e708c", 42 | "testnet": "0x106941459a8768f5a92b770e280555faf817576f", 43 | } 44 | 45 | 46 | // Utilities 47 | const displayWei = x => x.toString().padStart(20, " ") 48 | const displayGas = x => x.toString().padStart(10, " ") 49 | const sleep = ms => new Promise(resp => setTimeout(resp, ms)); 50 | 51 | // Get an L2 signer 52 | const getSigner = async () => { 53 | let endpointUrl; 54 | 55 | if (argv.network == 'testnet') 56 | endpointUrl = process.env.L2URL; 57 | if (argv.network == 'mainnet') 58 | endpointUrl = process.env.L2URL; 59 | 60 | const l2RpcProvider = optimismSDK.asL2Provider( 61 | new ethers.providers.JsonRpcProvider(endpointUrl) 62 | ) 63 | const wallet = ethers.Wallet.fromMnemonic(process.env.MNEMONIC). 64 | connect(l2RpcProvider) 65 | 66 | return wallet 67 | } // getSigner 68 | 69 | 70 | // Get estimates from the SDK 71 | const getEstimates = async (provider, tx) => { 72 | return { 73 | totalCost: await provider.estimateTotalGasCost(tx), 74 | l1Cost: await provider.estimateL1GasCost(tx), 75 | l2Cost: await provider.estimateL2GasCost(tx), 76 | l1Gas: await provider.estimateL1Gas(tx) 77 | } 78 | } // getEstimates 79 | 80 | 81 | 82 | const displayResults = (estimated, real) => { 83 | console.log(`Estimates:`) 84 | console.log(` Total gas cost: ${displayWei(estimated.totalCost)} wei`) 85 | console.log(` L1 gas cost: ${displayWei(estimated.l1Cost)} wei`) 86 | console.log(` L2 gas cost: ${displayWei(estimated.l2Cost)} wei`) 87 | 88 | if (argv.verify) { 89 | console.log(`\nReal values:`) 90 | console.log(` Total gas cost: ${displayWei(real.totalCost)} wei`) 91 | console.log(` L1 gas cost: ${displayWei(real.l1Cost)} wei`) 92 | console.log(` L2 gas cost: ${displayWei(real.l2Cost)} wei`) 93 | 94 | console.log(`\nL1 Gas:`) 95 | console.log(` Estimate: ${displayGas(estimated.l1Gas)}`) 96 | console.log(` Real: ${displayGas(real.l1Gas)}`) 97 | console.log(` Difference: ${displayGas(real.l1Gas-estimated.l1Gas)}`) 98 | 99 | console.log(`\nL2 Gas:`) 100 | console.log(` Estimate: ${displayGas(estimated.l2Gas)}`) 101 | console.log(` Real: ${displayGas(real.l2Gas)}`) 102 | console.log(` Difference: ${displayGas(real.l2Gas-estimated.l2Gas)}`) 103 | } else { // if argv.verify 104 | console.log(` L1 gas: ${displayGas(estimated.l1Gas)}`) 105 | console.log(` L2 gas: ${displayGas(estimated.l2Gas)}`) 106 | } // if argv.verify 107 | 108 | } // displayResults 109 | 110 | 111 | 112 | const main = async () => { 113 | 114 | const signer = await getSigner() 115 | 116 | if (!greeterAddrs[argv.network]) { 117 | console.log(`I don't know the Greeter address on chain: ${argv.network}`) 118 | process.exit(-1) 119 | } 120 | 121 | const Greeter = new ethers.ContractFactory(greeterJSON.abi, greeterJSON.bytecode, signer) 122 | const greeter = Greeter.attach(greeterAddrs[argv.network]) 123 | 124 | const greeting = "Hello!" 125 | 126 | let real = {} 127 | 128 | const fakeTxReq = await greeter.populateTransaction.setGreeting(greeting) 129 | const fakeTx = await signer.populateTransaction(fakeTxReq) 130 | console.log("About to get estimates") 131 | let estimated = await getEstimates(signer.provider, fakeTx) 132 | estimated.l2Gas = await greeter.estimateGas.setGreeting(greeting) 133 | 134 | if (argv.verify) { 135 | let realTx, realTxResp 136 | const weiB4 = await signer.getBalance() 137 | 138 | // If the transaction fails, error out with additional information 139 | try { 140 | console.log("About to create the transaction") 141 | realTx = await greeter.setGreeting(greeting) 142 | realTx.gasPrice = realTx.maxFeePerGas; 143 | console.log("Transaction created and submitted") 144 | realTxResp = await realTx.wait() 145 | console.log("Transaction processed") 146 | } catch (err) { 147 | console.log(`Error: ${err}`) 148 | console.log(`Coming from address: ${await signer.getAddress()} on Optimistic ${network}`) 149 | console.log(` balance: ${displayWei(await signer.getBalance())} wei`) 150 | process.exit(-1) 151 | } 152 | 153 | // If the balance hasn't been updated yet, wait 0.1 sec 154 | real.totalCost = 0 155 | while (real.totalCost === 0) { 156 | const weiAfter = await signer.getBalance() 157 | real.totalCost = weiB4 - weiAfter 158 | await sleep(100) 159 | } 160 | 161 | // Get the real information (cost, etc.) from the transaction response 162 | real.l1Gas = realTxResp.l1GasUsed 163 | real.l2Gas = realTxResp.gasUsed 164 | real.l1Cost = realTxResp.l1Fee 165 | real.l2Cost = real.totalCost - real.l1Cost 166 | } // if argv.verify 167 | 168 | displayResults(estimated, real) 169 | 170 | } // main 171 | 172 | 173 | main().then(() => process.exit(0)) 174 | .catch((error) => { 175 | console.error(error) 176 | process.exit(1) 177 | }) -------------------------------------------------------------------------------- /05-Estimate-L2-Transaction-Gas-Cost/sdk-estimate-gas/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sdk-gas-estimate", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@eth-optimism/sdk": "^1.8.0", 8 | "dotenv": "^16.0.1", 9 | "yarg": "^1.0.8" 10 | }, 11 | "scripts": { 12 | "estimate": "node gas.js" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BNB Chain Tutorials 2 | Blockchain tutorials using BNB Chain. Learn how to build Decentralized Applications (Dapps) on BNB Chain and Solidity Smart contracts. 3 | 4 | Covers: 5 | - BNB Chain 6 | - Solidity 7 | - Web3 8 | - Truffle 9 | 10 | ### Organization 11 | - **[01-BSC Hello World Full Stack dApp](https://github.com/bnb-chain/bnb-chain-tutorial/tree/main/01-%20Hello%20World%20Full%20Stack%20dApp%20on%20BSC):** Tutorial on how to develop a simple full-stack dapp with front-end integration on BSC Testnet. 12 | - **[02-BSC Block Explorer](https://github.com/bnb-chain/bnb-chain-tutorial/tree/main/02-BSC-Block-Explorer):** Tutorial on how to develop a simple full-stack dapp that can fetch transaction details from a user given transaction hash. 13 | - **[03-Using BlackIDE for Deploying NFTs](https://github.com/bnb-chain/bnb-chain-tutorial/tree/main/03-Using-BlackIDE-for-Deploying-NFTs):** Tutorial on how to use BlackIDE to deploy NFTs on the BSC testnet and view them in the MetaMask wallet. 14 | - **[04-Deploying Smart Contracts Using IDEs](https://github.com/bnb-chain/bnb-chain-tutorial/tree/main/04-Deploying-Smart-Contracts-Using-IDEs):** Tutorials on how to deploy smart contracts using different IDEs, such as, Chainlink, Hardhat, Truffle, and Remix. 15 | 16 | -------------------------------------------------------------------------------- /greenfield-website-hosting/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/greenfield-website-hosting/.DS_Store -------------------------------------------------------------------------------- /greenfield-website-hosting/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Plato | Personal Website 6 | 7 | 8 | 9 |
10 |

Plato

11 | 19 |
20 | 21 |
22 |
23 |

Biography

24 | Plato 25 |

Born around 427 BCE in Athens, Greece, Plato was one of the most important and enduring philosophers of the ancient world. His father, Ariston, was descended from Athenian nobility, while his mother, Perictione, came from a prominent and wealthy family. This aristocratic background undoubtedly influenced Plato's views on the role of the philosophers and the nature of the ideal society.

26 | 27 |

From an early age, Plato showed a deep interest in philosophy and the pursuit of knowledge. He was a pupil of the great philosopher Socrates, who had a profound impact on Plato's thinking. Socrates' method of questioning and exploring fundamental ideas was an important part of Plato's education and would later become a cornerstone of his own philosophical method.

28 | 29 |

After Socrates' execution in 399 BCE, Plato traveled around the Mediterranean, absorbing the teachings of other philosophers as well as engaging in political activities. In 387 BCE, he returned to Athens and founded the Academy, an institution dedicated to the study of philosophy, mathematics, and science. The Academy would become a center of learning that attracted some of the greatest philosophers and thinkers of the ancient world, including Aristotle, who would later become one of Plato's most famous pupils.

30 | 31 |

It was at the Academy that Plato wrote most of his philosophical works, which he composed in the form of dialogues. These dialogues explored a wide range of topics, including ethics, justice, and the nature of reality. Many of them feature Socrates as the main character, serving as a mouthpiece for Plato's ideas. Some of the most famous dialogues include The Republic, an exploration of the ideal society, and The Symposium, a meditation on love and desire.

32 | 33 |

Plato continued to lead the Academy and write dialogues until his death in 347 BCE. His influence on Western philosophy cannot be overstated. The works of Plato have been studied and analyzed for millennia, and his ideas on metaphysics, ethics, and the nature of reality continue to be debated by philosophers today.

34 | 35 |
36 |
37 |

Accomplishments

38 |

Plato's accomplishments include:

39 |
    40 |
  • Establishing the Academy, one of the earliest known 41 | institutions of higher learning.
  • 42 |
  • Contributing to the development of Western philosophy through 43 | his dialogues.
  • 44 |
  • Formulating the theory of forms, which postulated that 45 | abstract ideas represent the true reality behind the physical world.
  • 46 |
  • Influencing numerous philosophers and thinkers throughout 47 | history, shaping the course of philosophy and intellectual thought.
  • 48 |
49 |
50 | 51 |
52 |

Famous Quotes

53 |
54 |

"Wise men speak because they have something to say; fools 55 | because they have to say something."

56 |
— Plato
57 |
58 |
59 |

"Courage is knowing what not to fear."

60 |
— Plato
61 |
62 |
63 | 64 |
65 |

Personal Story

66 |

Plato's personal story is one of intellectual pursuit and 67 | philosophical exploration. As a young man, he became a devoted disciple of 68 | Socrates and was greatly influenced by his mentor's teachings and ideas. 69 | Plato witnessed Socrates' trial and subsequent execution, which had a 70 | profound impact on his philosophical views and the nature of justice.

71 |

After Socrates' death, Plato founded the Academy, a center of 72 | learning and philosophical inquiry. The Academy attracted students from 73 | various backgrounds and became a hub for intellectual discussions and 74 | debates. Plato dedicated his life to the pursuit of truth, knowledge, and 75 | the betterment of society through philosophical contemplation and 76 | education.

77 |
78 |
79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /greenfield-website-hosting/plato.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bnb-chain/bnb-chain-tutorial/6626670d651dc8dd95f2fa5531c18b418d1b8507/greenfield-website-hosting/plato.jpeg -------------------------------------------------------------------------------- /greenfield-website-hosting/styles.css: -------------------------------------------------------------------------------- 1 | /* General Styles */ 2 | body { 3 | font-family: "Times New Roman", serif; 4 | margin: 0; 5 | padding: 0; 6 | background-color: #F8F8F8; 7 | color: #333; 8 | } 9 | 10 | h1, h2 { 11 | font-family: "Georgia", serif; 12 | } 13 | 14 | /* Header Styles */ 15 | header { 16 | background-color: #D3A625; 17 | padding: 20px; 18 | text-align: center; 19 | } 20 | 21 | nav ul { 22 | list-style: none; 23 | margin: 0; 24 | padding: 0; 25 | } 26 | 27 | nav ul li { 28 | display: inline; 29 | margin-right: 10px; 30 | } 31 | 32 | nav ul li a { 33 | text-decoration: none; 34 | color: #FFF; 35 | } 36 | 37 | /* Main Content Styles */ 38 | main { 39 | padding: 20px; 40 | } 41 | 42 | section { 43 | margin-bottom: 40px; 44 | } 45 | 46 | h2 { 47 | color: #D3A625; 48 | } 49 | 50 | blockquote { 51 | margin: 0; 52 | padding: 10px; 53 | border-left: 5px solid #D3A625; 54 | } 55 | 56 | /* Footer Styles */ 57 | footer { 58 | background-color: #D3A625; 59 | padding: 20px; 60 | text-align: center; 61 | font-size: 14px; 62 | color: #FFF; 63 | } 64 | 65 | /* Image Styles */ 66 | .plato-image { 67 | width: 200px; 68 | height: auto; 69 | border-radius: 50%; 70 | margin-bottom: 20px; 71 | } 72 | -------------------------------------------------------------------------------- /upload-folder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | print_usage() { 4 | echo "Usage: $0 [OPTIONS] FOLDER_PATH BUCKET_NAME GNFD_CMD_FILEPATH" 5 | echo "" 6 | echo "Upload files from a folder to a bucket using gnfd-cmd." 7 | echo "" 8 | echo "Positional Arguments:" 9 | echo " FOLDER_PATH Path to the folder containing files to upload" 10 | echo " BUCKET_NAME Name of the bucket to upload files to" 11 | echo " GNFD_CMD_FILEPATH Path to the gnfd-cmd executable" 12 | echo "" 13 | echo "Options:" 14 | echo " -h, --help Show this help message and exit" 15 | echo " -v, --verbose Enable verbose mode, echoing execution of each file and progress" 16 | } 17 | 18 | if [[ "$1" == "-h" || "$1" == "--help" ]]; then 19 | print_usage 20 | exit 0 21 | fi 22 | 23 | verbose=false 24 | 25 | while [[ $# -gt 0 ]]; do 26 | key="$1" 27 | 28 | case $key in 29 | -v|--verbose) 30 | verbose=true 31 | shift 32 | ;; 33 | *) 34 | break 35 | ;; 36 | esac 37 | done 38 | 39 | if [ "$#" -ne 3 ]; then 40 | echo "Error: Invalid number of arguments." 41 | echo "" 42 | print_usage 43 | exit 1 44 | fi 45 | 46 | FOLDER_PATH="$1" 47 | BUCKET_NAME="$2" 48 | GNFD_CMD_FILEPATH="$3" 49 | 50 | # Function to get the content type based on file extension 51 | get_content_type() { 52 | case "$1" in 53 | *.html) 54 | echo "text/html" 55 | ;; 56 | *.css) 57 | echo "text/css" 58 | ;; 59 | *.js) 60 | echo "application/javascript" 61 | ;; 62 | *.jpg|*.jpeg) 63 | echo "image/jpeg" 64 | ;; 65 | *.png) 66 | echo "image/png" 67 | ;; 68 | # Add more file extensions and their corresponding content types if needed 69 | *) 70 | echo "application/octet-stream" 71 | ;; 72 | esac 73 | } 74 | 75 | # Function to calculate the total number of files 76 | count_files() { 77 | local folder="$1" 78 | local count=0 79 | 80 | # Iterate over files in the current folder 81 | for file in "$folder"/*; do 82 | if [ -f "$file" ]; then 83 | count=$((count + 1)) 84 | elif [ -d "$file" ]; then 85 | # Recursively count files in subfolders 86 | count_subfolder=$(count_files "$file") 87 | count=$((count + count_subfolder)) 88 | fi 89 | done 90 | 91 | echo "$count" 92 | } 93 | 94 | # Function to process files recursively 95 | process_files() { 96 | local folder="$1" 97 | local count="$2" 98 | local processed=0 99 | 100 | # Iterate over files in the current folder 101 | for file in "$folder"/*; do 102 | if [ -f "$file" ]; then 103 | filename=$(basename "$file") 104 | content_type=$(get_content_type "$filename") 105 | full_file_path=$(realpath "$file") 106 | gnfd_cmd="$GNFD_CMD_FILEPATH object put --visibility=public-read --contentType=$content_type $full_file_path gnfd://$BUCKET_NAME/$filename" 107 | 108 | if [ "$verbose" = true ]; then 109 | echo "Executing command: $gnfd_cmd" 110 | fi 111 | 112 | # Uncomment the line below to execute the command 113 | eval "$gnfd_cmd" 114 | 115 | processed=$((processed + 1)) 116 | if [ "$verbose" = true ]; then 117 | progress=$((processed * 100 / count)) 118 | echo "Progress: $progress% ($processed/$count)" 119 | fi 120 | elif [ -d "$file" ]; then 121 | # Recursively process subfolders 122 | process_files "$file" "$count" 123 | fi 124 | done 125 | } 126 | 127 | # Start processing files 128 | if [ "$verbose" = true ]; then 129 | echo "Verbose mode enabled." 130 | total_files=$(count_files "$FOLDER_PATH") 131 | echo "Total files to process: $total_files" 132 | fi 133 | 134 | process_files "$FOLDER_PATH" "$total_files" 135 | 136 | --------------------------------------------------------------------------------