---
# System prepended metadata

title: Nero 實習 （vera）

---

# 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 -->

