# Nero 實習 (vera) <!-- https://www.figma.com/file/D8rVMIMO791hg0XYiVHKBv/Nero-UI?type=design&node-id=0-1&mode=design --> <!-- 任務連結:https://hackmd.io/@zinstitute/HktIQ3yH2 --> ### [套件安裝](https://docs.blockscout.com/for-developers/information-and-settings/requirements) ``` brew install erlang brew install elixir brew install postgresql brew install node brew install automake brew install libtool brew install gcc brew install gmp ``` -- ### [Docker setup](https://docs.blockscout.com/for-developers/information-and-settings/docker-integration-local-use-only) 安裝 m2 的 [docker 環境](https://yeasy.gitbook.io/docker_practice/install/mac) -- terminal 1: run 本機的 geth ![](https://hackmd.io/_uploads/SkHKiZWSh.png) terminal 2: ``` docker-compose up --build ``` 他會卡在 build 階段 ![](https://hackmd.io/_uploads/HynT9PgSn.png) 把 alpine-elixir-phoenix:1.14 版本降下來變成 1.13,有順利解決 139 的錯誤訊息 ``` // 有兩處都要改成 1.13 FROM bitwalker/alpine-elixir-phoenix:1.13 ``` 錯誤訊息變成無法 install ![](https://hackmd.io/_uploads/BJaG3b-Sn.png) package-lock.json 刪除重新 build( block_scout_web / explorer 裡面的 ) ![](https://hackmd.io/_uploads/Hkce7MWSn.png) build 成功,但裡面目前沒東西 ``` http://localhost:4000/ ``` ![](https://hackmd.io/_uploads/S1bM7Gbr3.png) -- 0611:本機目前 run 不起來,問題同下 https://github.com/blockscout/blockscout/issues/7549 -- 注意事項: 1. docker 裡面的 Use Rosetta for x86/amd64 emulation on Apple Silicon 選項要勾起來。 2. mac m1 / m2 是屬於 arm64 晶片,設定上要注意 -- ### [OP Stack and Celestia tutorial](https://docs.celestia.org/developers/optimism/) #### Environment setup and Golang installation Install wget and jq ``` brew install wget && brew install jq ``` Install Golang ``` ver="1.20.2" cd $HOME wget "https://golang.org/dl/go$ver.darwin-amd64.tar.gz" sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf "go$ver.darwin-amd64.tar.gz" rm "go$ver.darwin-amd64.tar.gz" ``` Now we need to add the /usr/local/go/bin directory to $PATH: ``` echo "export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin" >> $HOME/.bash_profile source $HOME/.bash_profile ``` 確認安裝成功 ``` go version ``` -- #### Clone repository ``` cd $HOME git clone https://github.com/celestiaorg/optimism cd optimism git checkout celestia-develop ``` ### asdf <!-- 打開新的terminal --> ``` cd $HOME git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.2 echo '. "$HOME/.asdf/asdf.sh"' >> ~/.bashrc echo '. "$HOME/.asdf/completions/asdf.bash"' >> ~/.bashrc ``` -- Set the path: ``` export PATH=$PATH:~/.asdf/bin/ ``` 確認安裝 ``` asdf ``` Install nodejs 16.16.0: ``` asdf plugin add nodejs asdf install nodejs 16.16.0 asdf local nodejs 16.16.0 source ~/.bashrc curl -L https://foundry.paradigm.xyz/ | bash source /Users/vera/.zshenv foundryup ``` #### Build devnet ``` cd $HOME cd optimism make build-ts export SEQUENCER_BATCH_INBOX_ADDRESS=0xff00000000000000000000000000000000000000 export L2OO_ADDRESS=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 ``` -- ### Start devnet ``` make devnet-up ``` ![](https://hackmd.io/_uploads/Byx1fLwr2.png) 錯誤訊息如下 ![](https://hackmd.io/_uploads/S1iez8wrn.png) 把已經定義過重複的值隱蔽 ![](https://hackmd.io/_uploads/SJcjrLwSn.png) 成功 ![](https://hackmd.io/_uploads/ry3xv8wS3.png) -- ### Stop devnet ``` make devnet-down make devnet-clean ``` ![](https://hackmd.io/_uploads/SklRmaIDB2.png) -- ### Viewing containers 當 docker run 起來的時候 ``` docker ps ``` ![](https://hackmd.io/_uploads/H18LpUDS3.png) -- ### Find a transaction ``` cast block latest --rpc-url localhost:8545 ``` ![](https://hackmd.io/_uploads/ByuJCUPBh.png) <!-- =>>> 先做到這裡 --> --> -- 結合任務 1 / 2,成功 ![](https://hackmd.io/_uploads/BJQNotvBh.png) <!-- -- 調整的參數清單 https://docs.blockscout.com/for-developers/information-and-settings/env-variables --> -- ### 任務三 * [工具](https://www.npmjs.com/package/hardhat-forta)(hardhat plugin) * 測試時可連接到目前的測試網,並模擬發送交易看看有沒有跳出正確的交易模擬訊息 1. 研究後發現他是監控[交易異常](https://docs.forta.network/en/latest/api-example-use-cases/ )的工具,並非可以偵測交易後 token 的轉變 (與需求不符合) 2. 重新確認需求是希望能<核可交易之後會減少或增加多少 token>,目前還在尋求做法或是範例 * 像是preview的功能嗎 https://github.com/blocknative/web3-onboard * 還是我要在本機做一個 fork 測試機 rpc,然後發送交易 * 先傳到後端express(node js),先丟到fork去,確認event的值,回傳res帶著0x data,回傳給客戶看資產變化的預測值,他確認後還是要再送一次後端,再上鏈 * 開發api去發送交易,不能用8545可能是8546之類的 先用hardhat做fork,發交易,拿到資訊這段 https://stackoverflow.com/questions/69013697/get-events-from-a-transaction-receipt-in-hardhat -- ## 先用[hardhat](https://hardhat.org/hardhat-runner/docs/getting-started)做fork,發交易,拿到資訊這段 ``` 創資料夾 cd 資料夾 npm install --save-dev hardhat npm install --save-dev @nomiclabs/hardhat-ethers ethers npx hardhat ``` hardhat.config.js ``` require("@nomicfoundation/hardhat-toolbox"); require('@nomiclabs/hardhat-ethers'); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { solidity: "0.8.18", networks: { hardhat: { forking: { url: "http://139.162.97.228:9545" } } } }; ``` -- ### 方法1: 創建一個範例的合約 Test.sol ``` // contracts/Box.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Test { uint256 private _value; // Emitted when the stored value changes event ValueChanged(uint256 value); // Stores a new value in the contract function store(uint256 value) public { _value = value; emit ValueChanged(value); } // Reads the last stored value function retrieve() public view returns (uint256) { return _value; } } ``` deploy.js ``` // scripts/deploy.js async function main() { // We get the contract to deploy const Test = await ethers.getContractFactory('Test'); const test = await Test.deploy(); await test.deployed(); console.log('Test deployed to:', test.address); } main() .then(() => process.exit(0)) .catch(error => { console.error(error); process.exit(1); }); ``` terminal1: ``` npx hardhat node ``` terminal2: ``` npx hardhat run --network localhost scripts/deploy.js npx hardhat console --network localhost const Test = await ethers.getContractFactory('Test'); const test = await Test.attach('0X........') await test.store(42) //這你可以嘗試合約內的function ``` ![](https://hackmd.io/_uploads/S1zvnH2D2.png) ![](https://hackmd.io/_uploads/Hk_uhShvn.png) ![](https://hackmd.io/_uploads/SkuFhBnw3.png) -- ### 方法2: <!-- https://ethereum.stackexchange.com/questions/95023/hardhat-how-to-interact-with-a-deployed-contract --> 先部署合約 ``` npx hardhat run --network localhost scripts/deploy.js ``` 將部署後的 address 帶到下面 ( 用 attach / getContractAt 得到結果一樣 ) ``` // scripts/call.js require('@nomiclabs/hardhat-ethers'); const main = async () => { const contractAddress = "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c"; -> 已部署的合約地址,可用上面方法 deploy const myContract = await hre.ethers.getContractAt("Test", contractAddress); console.log(await myContract.store(42)) }; main().catch((error) => { console.log(error); process.exit(1); }); ``` terminal1: ``` npx hardhat node ``` terminal2: ``` npx hardhat run scripts/call.js --network localhost ``` ![](https://hackmd.io/_uploads/BkNDR_hP3.png) 0626 更新成: ``` // scripts/call.js require('@nomiclabs/hardhat-ethers'); const main = async () => { const Test = await ethers.getContractFactory('Test'); const test = await Test.attach('0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690'); const transactionResponse = await test.approve('0x90F79bf6EB2c4f870365E785982E1f101E93b906', 100) const transactionReceipt = await transactionResponse.wait(); if(transactionReceipt.events[0].event == 'Transfer'){ let data = { function: 'Transfer', tokenAddress: transactionReceipt.events[0].address, balance: ethers.utils.formatUnits(transactionReceipt.events[0].args.value, 0), from: transactionReceipt.events[0].args.from, to: transactionReceipt.events[0].args.to, } console.log(data) // return data; }else if(transactionReceipt.events[0].event == 'Approval'){ let data = { function: 'Approval', tokenAddress: transactionReceipt.events[0].address, balance: ethers.utils.formatUnits(transactionReceipt.events[0].args.value, 0), owner: transactionReceipt.events[0].args.owner, spender: transactionReceipt.events[0].args.spender, } console.log(data) // return data; } }; main().catch((error) => { console.log(error); process.exit(1); }); ``` 獲得的 console.log ![](https://hackmd.io/_uploads/SkZUmQD_2.png) <!-- -- 再解析 log https://youtu.be/ClOATp_GuM4 https://codeburst.io/deep-dive-into-ethereum-logs-a8d2047c7371 --> -- https://gopluslabs.io/#token_detection <!-- abi 這欄放我們有興趣的 event 們,例如 Transfer( .. ), Approve( ..) --> <!-- let abi = [ "event newConnect (string indexed hashedName, string name, bytes32 connectId, string encrypted, address owner)" ]; let iface = new ethers.utils.Interface(abi) getLogs.then((logs) => { logs.forEach((log) => { console.log(iface.parseLog(log)); }); }); --> <!-- ![](https://hackmd.io/_uploads/SJbldSXv2.png) ``` 創建一個 test.js npx hardhat run scripts/test.js ``` ![](https://hackmd.io/_uploads/S1v9IH7vn.png) --> <!-- * https://github.com/EnsoFinance/transaction-simulator * https://github.com/ethereum/eth-tester * https://github.com/blocknative/web3-onboard * https://github.com/hashgraph/hedera-improvement-proposal/discussions/688 --> -- ## [transaction-simulator ](https://github.com/EnsoFinance/transaction-simulator) 安装 rustup ``` curl https://sh.rustup.rs -sSf | sh source $HOME/.cargo/env 或 export PATH="$HOME/.cargo/bin:$PATH" ``` 更新 body.json ``` { "chainId": 901, "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", -> 需要換成你fork後得到的測試account "to": "0x7fEA6786D291A87fC4C98aFCCc5A5d3cFC36bc7b", "data": "0xffa2ca3b44eea7c8e659973cbdf476546e9e6adfd1c580700537e52ba7124933a97904ea000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001d0e30db00300ffffffffffffc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a0", "gasLimit": 500000, "value": "100000", "blockNumber": 1164525, "formatTrace": true } ``` copy .env.example to .env, fill out required values and run: ``` cargo run ``` test > 用於測試api.rs結果是否符合預期expected.json ``` cargo test ``` `body.json` contains a simple request in the root of the project so once the API is running you can just run: ``` $ curl -H "Content-Type: application/json" --data @tests/body.json http://localhost:8080/api/v1/simulate ``` If you have jq installed, you can run this to see pretty traces: ``` $ curl -H "Content-Type: application/json" --data @tests/body.json http://localhost:8080/api/v1/simulate | jq -r ".formattedTrace" ``` -- 顯示還未支援該chainId ![](https://hackmd.io/_uploads/S1bDHI2vn.png) ![](https://hackmd.io/_uploads/SkenBI2w2.png) simulation.rs 裡面新增 chain 901 ``` fn chain_id_to_fork_url(chain_id: u64) -> Result<String, Rejection> { match chain_id { // nero 901 => Ok("http://139.162.97.228:9545".to_string()), _ => Err(NoURLForChainIdError.into()), } } ``` -- terminal1: ``` cargo run ``` terminal2: ``` $ curl -H "Content-Type: application/json" --data @tests/body.json http://localhost:8080/api/v1/simulate | jq -r ".formattedTrace" ``` ![](https://hackmd.io/_uploads/ByNeQ_hw3.png) -- * Future: Explorer 日文翻譯([教學](https://docs.blockscout.com/for-developers/configuration-options/internationalization)) To setup translation file. ``` cd apps/block_scout_web; mix gettext.extract --merge; cd - ``` ``` mix deps.update ex_cldr ``` <!-- ![](https://hackmd.io/_uploads/Hy5S1fRL2.png) --> <!-- Network name: Nero-L1 / Nero-L2 New RPC URL: http://139.162.97.228:8545 / http://139.162.97.228:9545 Chain ID: 900 / 901 Currency symbol: ETH -->