From d5bbb2b014850801bc7ff702d3400e054120e7c1 Mon Sep 17 00:00:00 2001 From: Jonathan LEI Date: Thu, 7 Mar 2024 10:53:38 +0000 Subject: [PATCH] wip --- .gitignore | 1 + README.md | 65 ++++++++++++++++++++++++++++++- cairo_project.toml | 3 ++ scripts/compile_l2.sh | 29 ++++++++++++++ scripts/compile_l2_with_docker.sh | 15 +++++++ 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 cairo_project.toml create mode 100755 scripts/compile_l2.sh create mode 100755 scripts/compile_l2_with_docker.sh diff --git a/.gitignore b/.gitignore index f49938e..cd4b338 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +/build/ /cache/ /out/ diff --git a/README.md b/README.md index 4fb53d9..5adf8c4 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,69 @@ **ZEND token implementation** +## L1 token + +The [L1 token contract](./l1/ZendToken.sol) is a simple child contract of the OpenZeppelin reference ERC20 implementation. + +### Prerequisites + +Install [Foundry](https://github.com/foundry-rs/foundry) for Solidity compilation. Check your Foundry installation with: + +```console +forge --version +``` + +### Building + +To build the contract simply run: + +```console +forge build +``` + +Built artifacts will be available in the `./out` folder. + +## L2 token + +The L2 token contract is _not_ manually deployed. Instead, it's automatically deployed by the [L2 token bridge contract](https://github.com/starknet-io/starkgate-contracts/blob/d62a255307d2f3de65665f18316766a2c69ead78/src/cairo/token_bridge.cairo) when a [permissionless token enrollment](https://docs.starknet.io/documentation/tools/starkgate-adding_a_token/) is triggered on the [L1 token bridge manager contract](https://github.com/starknet-io/starkgate-contracts/blob/d62a255307d2f3de65665f18316766a2c69ead78/src/solidity/StarkgateManager.sol). Therefore, the L2 token contract code to be deployed is completely up to the official StarkGate configuration. Any L2 token contract instance deployed this way is mintable only from the bridge contract. + +> [!NOTE] +> +> As of this writing, the L2 token _class hash_ deployed by StarkGate is [`0x05ffbcfeb50d200a0677c48a129a11245a3fc519d1d98d76882d1c9a1b19c6ed`](https://starkscan.co/class/0x05ffbcfeb50d200a0677c48a129a11245a3fc519d1d98d76882d1c9a1b19c6ed). + +Despite our lack of control over the implementation, the token contract is still [reproduced here](./l2/openzeppelin/token/erc20_v070/erc20.cairo) (along with dependencies) from its [upstream source](https://github.com/starknet-io/starkgate-contracts/blob/d62a255307d2f3de65665f18316766a2c69ead78/src/openzeppelin/token/erc20_v070/erc20.cairo) for reference. + +Additionally, due to the fact that none of the major Starknet block explorers offer Cairo 1 contract verification as of this writing, this repo provides tools for [deterministic compilation](#deterministic-compilation-with-docker) as a means of [verification](#verifying-class-hash). + +### Building directly + +With the `starknet-compile` command from [starkware-libs/cairo](https://github.com/starkware-libs/cairo) installed, run: + +```console +mkdir -p ./build +starknet-compile . -c openzeppelin::token::erc20_v070::erc20::ERC20 ./build/ERC20.json +``` + +> [!TIP] +> +> You must install versions newer than `v2.3.0` for `starknet-compile` to be able to compile successfully. + +The compiled contract is available at `./build/ERC20.json`. + +### Deterministic compilation with Docker + +To ensure deterministic compilation output, a [script](./scripts/compile_l2_with_docker.sh) is provided that generates the exact same class as the one used in production: + +```console +./scripts/compile_l2_with_docker.sh +``` + +The compiled contract is available at `./build/ERC20.json`. + +### Verifying class hash + +Either [built directly](#building-directly) or [with Docker](#deterministic-compilation-with-docker), you may verify that the class hash of the compiled contract artifact with the `starkli class-hash` command from [Starkli](https://github.com/xJonathanLEI/starkli). + ## License Licensed under either of @@ -11,4 +74,4 @@ Licensed under either of - Apache License, Version 2.0 ([LICENSE-APACHE](./LICENSE-APACHE) or ) - MIT license ([LICENSE-MIT](./LICENSE-MIT) or ) -at your option. +at your option, except the content in [`./l2/`](./l2/), which is licensed with its upstream source. diff --git a/cairo_project.toml b/cairo_project.toml new file mode 100644 index 0000000..b5505cf --- /dev/null +++ b/cairo_project.toml @@ -0,0 +1,3 @@ +[crate_roots] +src = "l2/src" +openzeppelin = "l2/openzeppelin" diff --git a/scripts/compile_l2.sh b/scripts/compile_l2.sh new file mode 100755 index 0000000..b77d4dc --- /dev/null +++ b/scripts/compile_l2.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname "$0" )" &> /dev/null && pwd ) +REPO_ROOT=$( cd -- "$( dirname $( dirname "$0" ) )" &> /dev/null && pwd ) + +compile () { + MODULE="$1" + NAME="$2" + OUTPUT="$REPO_ROOT/build/$NAME.json" + + echo "Compiling $MODULE::$NAME" + + # This is better than using the output option, which does not emit EOL at the end. + starknet-compile -c "$MODULE::$NAME" $REPO_ROOT > $OUTPUT + + if [ -n "$USER_ID" ] && [ -n "$GROUP_ID" ]; then + chown $USER_ID:$GROUP_ID $OUTPUT + fi +} + +mkdir -p "$REPO_ROOT/build" + +compile openzeppelin::token::erc20_v070::erc20 ERC20 + +if [ -n "$USER_ID" ] && [ -n "$GROUP_ID" ]; then + chown -R $USER_ID:$GROUP_ID "$REPO_ROOT/build" +fi diff --git a/scripts/compile_l2_with_docker.sh b/scripts/compile_l2_with_docker.sh new file mode 100755 index 0000000..072f5cf --- /dev/null +++ b/scripts/compile_l2_with_docker.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname "$0" )" &> /dev/null && pwd ) +REPO_ROOT=$( cd -- "$( dirname $( dirname "$0" ) )" &> /dev/null && pwd ) + +# Deterministically generate contract artifacts +docker run --rm \ + -v "$REPO_ROOT:/work" \ + --env "USER_ID=$(id -u)" \ + --env "GROUP_ID=$(id -g)" \ + --entrypoint sh \ + starknet/cairo:2.3.0 \ + -c "cd /work && ./scripts/compile_l2.sh"