Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
"Tokendecimals",
"zyfi",
"addrsSlot",
"NODLNS"
"NODLNS",
"solhint",
"mixedcase"
]
}
14 changes: 4 additions & 10 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM mcr.microsoft.com/devcontainers/base:jammy

USER vscode

ENV NODE_VERSION=20.18.1
ENV NODE_VERSION=22.13.0
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash && \
export NVM_DIR="$HOME/.nvm" && \
[ -s "$NVM_DIR/nvm.sh" ] && \
Expand All @@ -17,12 +17,6 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | zsh -s -- -y &&

ENV PATH="${PATH}:/home/vscode/.cargo/bin:/home/vscode/.yarn/bin:/home/vscode/.foundry/bin:/home/vscode/.nvm/versions/node/v${NODE_VERSION}/bin:/home/vscode/.solc"

ENV SOLC_VERSION=v0.8.23+commit.f704f362
RUN mkdir -p /home/vscode/.solc && \
curl https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-${SOLC_VERSION} -o /home/vscode/.solc/solc-linux-amd64-${SOLC_VERSION} && \
chmod +x /home/vscode/.solc/solc-linux-amd64-${SOLC_VERSION} && \
ln -s /home/vscode/.solc/solc-linux-amd64-${SOLC_VERSION} /home/vscode/.solc/solc

RUN sudo apt update && \
sudo apt install --yes \
pkg-config build-essential cmake \
Expand All @@ -33,12 +27,12 @@ RUN sudo apt update && \

RUN yarn global add zksync-cli && yarn global add @graphprotocol/graph-cli

ARG KNOWN_GOOD_FORGE_COMMIT=33b81acf8688f8cc1fc839b7e4a07ec58b347cb4
ARG KNOWN_GOOD_FORGE_COMMIT=574943e798a1351735e6535453141fdddf123808
RUN git clone https://github.com/matter-labs/foundry-zksync.git /tmp/foundry-zksync && \
cd /tmp/foundry-zksync && \
git checkout ${KNOWN_GOOD_FORGE_COMMIT} && \
cargo install --path ./crates/forge --profile local --force --locked && \
cargo install --path ./crates/cast --profile local --force --locked && \
cargo install --path ./crates/forge --force --locked && \
cargo install --path ./crates/cast --force --locked && \
rm -rf /tmp/foundry-zksync

ENTRYPOINT [ "zsh" ]
4 changes: 2 additions & 2 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ jobs:

- name: Lint
run: yarn lint

- name: Run tests
run: forge test --zksync
run: forge test --zksync
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.13
12 changes: 10 additions & 2 deletions .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,15 @@
}
],
"constructor-syntax": "error",
"immutable-vars-naming": "off",
"gas-custom-errors": "error"
"immutable-vars-naming": "warn",
"gas-custom-errors": "error",
"use-natspec": "off",
"import-path-check": "off",
"gas-struct-packing": "warn",
"gas-calldata-parameters": "warn",
"gas-increment-by-one": "warn",
"gas-small-strings": "warn",
"gas-strict-inequalities": "warn",
"gas-indexed-events": "warn"
}
}
8 changes: 8 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"servers": {
"OpenZeppelinSolidityContracts": {
"type": "http",
"url": "https://mcp.openzeppelin.com/contracts/solidity/mcp"
}
}
}
8 changes: 6 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
"solidity.formatter": "forge",
"github.copilot.chat.scopeSelection": true,
"github.copilot.chat.localeOverride": "en",
"github.copilot.chat.temporalContext.enabled": true,
"github.copilot.chat.generateTests.codeLens": true,
"github.copilot.chat.inlineChatCompletionTrigger.enabled": true,
"github.copilot.chat.inlineChatHint.enabled": true,
"github.copilot.chat.search.semanticTextResults": true,
"editor.defaultFormatter": null
"editor.defaultFormatter": null,
"github.copilot.chat.editor.temporalContext.enabled": true,
"editor.formatOnSave": true,
"[solidity]": {
"editor.defaultFormatter": "JuanBlanco.solidity"
}
}
59 changes: 40 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
# Nodle's Eth L2 rollup powered by zkSync stack

![Banner](https://github.com/NodleCode/rollup/assets/10683430/b50803ff-41d1-4faa-99eb-72c9eeaf3194)

# Development setup

> [!NOTE]
> We recommend you run within the provided [devcontainer](https://code.visualstudio.com/remote/advancedcontainers/overview) to ensure you have all the necessary tooling installed such `zksync-cli`, and `forge`.

For subquery utilization refer to [Nodle-zksync-subquery](/subquery/README.md)

## Repo organization
- `./` contains foundry contracts for Nodle and Click on ZkSync:

- `./` contains Nodle's constellation of smart contracts, tools and services for L1 Ethereum and L2 ZkSync operations.
- `./lib` contains libraries we depend on.
- `./src` contains contract sources.
- `./script` contains deployment scripts.
- `./script` contains forge scripts.
- `./hardhat-deploy` contains typescript deployment scripts compiled and run by hardhat.
- `./test` contains unit tests.
- `./subquery` contains a custom subquery for this project.
- ...more to come
- `./subquery` contains a custom subquery for this project.
- `./utils` contains typescript utilities such as batch-register for clk names.
- `./ops` contains shell scripts for operational tasks like deployment orchestration, maintenance, and chain interaction

## Conventions

- all files should be licensed under the BSD 3 Clear Clause license with the required file header `// SPDX-License-Identifier: BSD-3-Clause-Clear`
- when writing scripts, ensure that:
- input environment variables are prefixed with `N_` to differentiate them from `forge` environment variables
Expand Down Expand Up @@ -59,6 +65,7 @@ Please see scripts in `./scripts` and refer to the [forge documentation](https:/
### Deploying Click contracts

Please define the following environment variables:

- `N_WHITELIST_ADMIN`: address of the whitelist admin on the paymaster whitelist contract (typically the onboard or sponsorship API address).
- `N_WITHDRAWER`: address of the account allowed to withdraw ETH from the paymaster contract.
- deployer address will be set as super admin.
Expand All @@ -83,12 +90,14 @@ If you wish to simulate on-chain transactions pass a RPC URL.
### Deploying ContentSign Enterprise contracts

Please define the following environment variables:

- `N_NAME`: name of the NFT contract deployed.
- `N_SYMBOL`: symbol of the NFT contract deployed.

Here is a full example for a Sepolia deployment: `N_NAME=ExampleContentSign N_SYMBOL=ECS forge script script/DeployContentSignEnterprise.s.sol --zksync --rpc-url https://sepolia.era.zksync.dev --zk-optimizer -i 1 --broadcast`.

Once deployed, the script will output the contract address, and the account you deployed with will be set as the administrator of this contract with the possibility to grant other users minting access. You may onboard a new user with `cast` via the following command template:

```shell
export ETH_RPC_URL=https://sepolia.era.zksync.dev # use the appropriate RPC here
export NFT=0x195e4E251c41e8Ae9E9E961366C73e2CFbfB115A # use your own contract address here
Expand All @@ -100,10 +109,12 @@ cast send -i $NFT "grantRole(bytes32,address)" $ROLE 0x68e3981280792A19cC03B5A77
```

### Deploying NODL and NODLMigration contract

In the following example `N_VOTER1_ADDR` is the public address of the bridge oracle whose role is going to be a voter for funds coming from
the parachain side. Similarly `N_VOTER2_ADDR` and `N_VOTER3_ADDR` are addresses of the other two voter oracles.
the parachain side. Similarly `N_VOTER2_ADDR` and `N_VOTER3_ADDR` are addresses of the other two voter oracles.
The closer oracle does not need special permissions and thus need not to be mentioned.
NOTE: `i` flag in the command will make the tool prompt you for the private key of the deployer. So remember to have that handy but you don't need to define it in your environment.

```shell
N_VOTER1_ADDR="0x18AB6B4310d89e9cc5521D33D5f24Fb6bc6a215E" \
N_VOTER2_ADDR="0x571C969688991C6A35420C62d44666c47eB3F752" \
Expand All @@ -114,16 +125,19 @@ forge script script/DeployNodlMigration.sol --zksync --rpc-url https://sepolia.e
Afterwards the user you onboarded should be able to mint NFTs as usual via the `safeMint(ownerAddress, metadataUri)` function.

### Deploying MigrationNFT contract

The `MigrationNFT` contract allows the minting of a reward SoulBound NFT when users bridge enough tokens through `NODLMigration`. Users can "level up" depending on the amount of tokens they bring in, with each levels being a sorted list of bridged amounts.

You will need to set the following environment variables:

- `N_MIGRATION`: address of the `NODLMigration` contract
- `N_MAX_HOLDERS`: maximum number of participants
- `N_LEVELS`: number of levels to set
- `N_LEVELS_x` where `x` is an integer from `0` to `N_LEVELS - 1`: actual number of tokens for each level
- `N_LEVELS_URI_x` where `x` is an integer from `0` to `N_LEVELS - 1`: actual metadata URL for the NFTs

You can then run the script `script/DeployMigrationNFT.s.sol` very similarly to the below:

```shell
N_MIGRATION=0x1427d38B967435a3F8f476Cda0bc4F51fe66AF4D \
N_MAX_HOLDERS=10000 \
Expand All @@ -140,15 +154,19 @@ forge script script/DeployMigrationNFT.s.sol --zksync --rpc-url https://sepolia.
## Scripts

### Checking on bridging proposals

Given a tracker id (`proposal`) and the bridge address you may run the script available in `./script/CheckBridge.s.sol`. The script will output proposal details and outline expectations as to the proposal's execution timeline. Here is a simple example:

```shell
N_PROPOSAL_ID=c43005c880cad7b699122b403607187a78251b9850d387521ffb123c473e3392 \
N_BRIDGE=0x5de7fe085ee66Fb48447e75AA8fb0598a080AEe0 \
forge script script/CheckBridge.s.sol --zksync --rpc-url https://mainnet.era.zksync.io
```

### Whitelisting new users on ContentSign contracts

Given a user and contract address, you can whitelist new users on contracts derived from `EnterpriseContentSign` with the `ContentSignWhitelist` script. Note that this assumes your own key has been granted admin permissions on this same contract. Here is a simple example for a testnet contract:

```shell
N_CONTENTSIGN=0x195e4E251c41e8Ae9E9E961366C73e2CFbfB115A \
N_WHITELIST=0x732e40223f57d7a1dbf340f5c0cc5b363b60428b \
Expand All @@ -161,22 +179,25 @@ forge script script/ContentSignWhitelist.s.sol -i 1 --zksync --rpc-url https://s
> The below steps are **not** for the faint of heart. Contract verification is technically not supported yet by the zkSync foundry fork, and the instructions below are likely to break (in which case feel free to update them via a PR).

Verification on Etherscan is best done via the Solidity Json Input method as it is the least error prone and most reliable. To do so, you will need a few elements:

1. Contract address, which you typically get from script outputs.
2. `solc` and `zksolc` versions, which you can identify based on the pragma header of the solidity contracts, or by checking what binaries are on your system:
```shell
$ ls ~/.zksync/
solc-macosx-arm64-0.8.23-1.0.0 zksolc-macosx-arm64-v1.4.1
```
In the sample case above, we are using `solc` `0.8.23` and `zksolc` `1.4.1`.
3. The Solidity Json Input file, which you can get by following the below instructions
1. Build the contracts and ask for the `build-info` via `forge build --zksync --zk-optimizer --build-info`
2. Access the said `build-info` at path `./out/build-info`, you will find there a JSON file (if you have more than one, take the most recent one)
3. Open the JSON file and select the value under the `input` key
4. Due to some incompatibilities, normalize the JSON value by removing the keys `settings.metadata` and `settings.viaIR`
4. The contract inputs, which you can regenerate if you know the input values you deployed the contract with. Or that you can fetch by viewing your deployment transaction on [explorer.zksync.io](https://explorer.zksync.io). To do, you will need to:
1. Open your deployment transaction on [explorer.zksync.io](https://explorer.zksync.io) (make sure to select the testnet if you are using the zkSync Era testnet)
2. Look for the input data variable named `_input`
3. Copy paste its value and **strip the `0x prefix** as Etherscan will throw an error otherwise

```shell
$ ls ~/.zksync/
solc-macosx-arm64-0.8.23-1.0.0 zksolc-macosx-arm64-v1.4.1
```

In the sample case above, we are using `solc` `0.8.23` and `zksolc` `1.4.1`. 3. The Solidity Json Input file, which you can get by following the below instructions

1. Build the contracts and ask for the `build-info` via `forge build --zksync --zk-optimizer --build-info`
2. Access the said `build-info` at path `./out/build-info`, you will find there a JSON file (if you have more than one, take the most recent one)
3. Open the JSON file and select the value under the `input` key
4. Due to some incompatibilities, normalize the JSON value by removing the keys `settings.metadata` and `settings.viaIR`
5. The contract inputs, which you can regenerate if you know the input values you deployed the contract with. Or that you can fetch by viewing your deployment transaction on [explorer.zksync.io](https://explorer.zksync.io). To do, you will need to:
6. Open your deployment transaction on [explorer.zksync.io](https://explorer.zksync.io) (make sure to select the testnet if you are using the zkSync Era testnet)
7. Look for the input data variable named `_input`
8. Copy paste its value and **strip the `0x prefix** as Etherscan will throw an error otherwise

Use all these artifacts on the contract verification page on Etherscan for your given contract (open your contract on Etherscan, select `Contract` and the link starting with `Verify`). When prompted, enter the compiler versions, the license (we use BSD-3 Clause Clear). Then on the next page, enter your normalized JSON input file, and the contract constructor inputs.

Expand Down
4 changes: 2 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.23"
solc = "0.8.26"

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

# necessary as some of the zksync contracts are big
via_ir = true
via_ir = true
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
83 changes: 42 additions & 41 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import { HardhatUserConfig } from "hardhat/config";

import "hardhat-storage-layout";
Expand All @@ -9,50 +8,52 @@ import "@matterlabs/hardhat-zksync-verify";
import "@nomicfoundation/hardhat-foundry";

const config: HardhatUserConfig = {
defaultNetwork: "zkSyncSepoliaTestnet",
networks: {
zkSyncSepoliaTestnet: {
url: "https://sepolia.era.zksync.dev",
ethNetwork: "sepolia",
zksync: true,
verifyURL: "https://explorer.sepolia.era.zksync.dev/contract_verification",
},
zkSyncMainnet: {
url: "https://mainnet.era.zksync.io",
ethNetwork: "mainnet",
zksync: true,
verifyURL: "https://zksync2-mainnet-explorer.zksync.io/contract_verification",
},
localDockerNode: {
url: "http://localhost:3050",
ethNetwork: "http://localhost:8545",
zksync: true,
},
inMemoryNode: {
url: "http://127.0.0.1:8011",
ethNetwork: "localhost", // in-memory node doesn't support eth node; removing this line will cause an error
zksync: true,
},
hardhat: {
zksync: true,
},
defaultNetwork: "zkSyncSepoliaTestnet",
networks: {
zkSyncSepoliaTestnet: {
url: "https://sepolia.era.zksync.dev",
ethNetwork: "sepolia",
zksync: true,
verifyURL:
"https://explorer.sepolia.era.zksync.dev/contract_verification",
},
zkSyncMainnet: {
url: "https://mainnet.era.zksync.io",
ethNetwork: "mainnet",
zksync: true,
verifyURL:
"https://zksync2-mainnet-explorer.zksync.io/contract_verification",
},
localDockerNode: {
url: "http://localhost:3050",
ethNetwork: "http://localhost:8545",
zksync: true,
},
zksolc: {
version: "1.4.1",
settings: {
// find all available options in the official documentation
// https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-solc.html#configuration
},
inMemoryNode: {
url: "http://127.0.0.1:8011",
ethNetwork: "localhost", // in-memory node doesn't support eth node; removing this line will cause an error
zksync: true,
},
solidity: {
version: "0.8.23",
hardhat: {
zksync: true,
},
paths: {
sources: "src",
},
zksolc: {
version: "1.5.1",
settings: {
// find all available options in the official documentation
// https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-solc.html#configuration
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
}
},
solidity: {
version: "0.8.26",
},
paths: {
sources: "src",
},
etherscan: {
apiKey: process.env.ETHERSCAN_API_KEY,
},
};

export default config;
2 changes: 1 addition & 1 deletion lib/openzeppelin-contracts
Loading