diff --git a/.gitignore b/.gitignore index 485dee64..de03f380 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .idea +.env diff --git a/Makefile b/Makefile index 9d3cf070..92019ee1 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,12 @@ ethereum-test: ethereum-clean ethereum-deploy: ethereum-clean @./contracts/solidity/deploy.sh +ethereum-set-escrow: + @./contracts/solidity/set_escrow.sh + +ethereum-set-withdraw-selector: + @./contracts/solidity/set_withdraw_selector.sh + starknet-clean: @cd ./contracts/cairo/ && scarb clean @@ -34,4 +40,9 @@ starknet-test: starknet-clean @cd ./contracts/cairo/ && snforge test starknet-deploy: starknet-build - @./contracts/cairo/deploy.sh \ No newline at end of file + @./contracts/cairo/deploy.sh + +starknet-deploy-and-connect: starknet-build + @$(MAKE) starknet-deploy + @$(MAKE) ethereum-set-escrow + @$(MAKE) ethereum-set-withdraw-selector diff --git a/README.md b/README.md index dfa16843..33a75e79 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ Follow the steps below to set up a testnet smart wallet using `starkli`: ```bash export STARKNET_RPC="" ``` + 2. **Create a Keystore**: A Keystore is a encrypted `json` file that stores the private keys. @@ -57,6 +58,7 @@ Follow the steps below to set up a testnet smart wallet using `starkli`: ```bash mkdir -p ~/.starkli-wallets ``` + 2. **Generate a new Keystore file**: Run the following command to create a new private key stored in the file. It will **ask for a password** to encrypt the file: @@ -72,6 +74,7 @@ Follow the steps below to set up a testnet smart wallet using `starkli`: ```bash export STARKNET_KEYSTORE="~/.starkli-wallets/keystore.json" ``` + 3. **Account Creation**: In Starknet every account is a smart contract, so to create one it will need to be deployed. @@ -80,6 +83,7 @@ Follow the steps below to set up a testnet smart wallet using `starkli`: ```bash starkli account oz init --keystore ~/.starkli-wallets/keystore.json ~/.starkli-wallets/account.json ``` + 2. **Deploy the account by running**: ```bash @@ -101,6 +105,38 @@ Follow the steps below to set up a testnet smart wallet using `starkli`: ## Declare and Deploy Contracts in Testnet +### Ethereum smart contract + +First, the Ethereum smart contracts must be deployed. For Ethereum the deployment process you will need to: + +1. Create your `.env` file: you need to configure the following variables in your own .env file on the contracts/solidity/ folder. You can use the env.example file as a template for creating your .env file, paying special attention to the formats provided + + ```bash + ETH_RPC_URL = Infura or Alchemy RPC URL + ETH_PRIVATE_KEY = private key of your ETH wallet + ETHERSCAN_API_KEY = API Key to use etherscan to read the Ethereum blockchain + SN_MESSAGING_ADDRESS = Starknet Messaging address + ``` + + **NOTE**: + + - You can generate ETHERSCAN_API_KEY [following this steps](https://docs.etherscan.io/getting-started/creating-an-account). + - For the deploy, you will need some GoerliETH that you can get from this [faucet](https://goerlifaucet.com/). + - Current SN_MESSAGING_ADDRESS values: + - SN_MESSAGING_ADDRESS is for when a L1 contract initiates a message to a L2 contract on Starknet. It does so by calling the sendMessageToL2 function on the Starknet Core Contract with the message parameters. Starknet Core Contracts are the following: + - Goerli: `0xde29d060D45901Fb19ED6C6e959EB22d8626708e` + - Sepolia: `0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057` + - Mainnet: `0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4` + +2. Deploy Solidity contract + + ```bash + make ethereum-deploy + ``` + +### Starknet smart contracts + +After the Ethereum smart contract is deployed, the Starknet smart contracts must be declared and deployed. On Starknet, the deployment process is in two steps: - Declaring the class of your contract, or sending your contract’s code to the @@ -108,40 +144,79 @@ On Starknet, the deployment process is in two steps: - Deploying a contract or creating an instance of the previously declared code with the necessary parameters -1. Updated `.env` file: Please modify the variables with your Testnet account and your RPC provider. +For this, you will need to: + +1. Create your `.env` file: you need to configure the following variables in your own .env file on the contracts/solidity folder. You can use the env.example file as a template for creating your .env file, paying special attention to the formats provided + + ``` + STARKNET_ACCOUNT = Absolute path of your starknet testnet account, created at the start of this README + STARKNET_KEYSTORE = Absolute path of your starknet testnet keystore, created at the start of this README + SN_RPC_URL = Infura or Alchemy RPC URL + ETH_CONTRACT_ADDR = newly created ETH contract address + MM_SN_WALLET_ADDR = Starknet wallet of the MarketMaker + WITHDRAW_NAME = The exact name of the withdraw function that is called from L1, case sensitive. Example: withdraw_fallback + HERODOTUS_FACTS_REGISTRY = Herodotus' Facts Registry Smart Contract in Starknet + MM_ETHEREUM_WALLET = Ethereum wallet of the MArketMaker + NATIVE_TOKEN_ETH_STARKNET = Ethereum's erc20 token handler contract in Starkent + ESCROW_CONTRACT_ADDRESS = Address of the Starknet smart contract, this value should be empty, and is automatically updated after deploy.sh is run + ``` + + **Note** + - Herodotus Facts Registry: + - Starknet Goerli: `0x01b2111317EB693c3EE46633edd45A4876db14A3a53ACDBf4E5166976d8e869d` + - Starknet Sepolia: `0x07d3550237ecf2d6ddef9b78e59b38647ee511467fe000ce276f245a006b40bc` + - Starknet Mainnet: `0x014bf62fadb41d8f899bb5afeeb2da486fcfd8431852def56c5f10e45ae72765` + +2. Declare and Deploy: We sequentially declare and deploy the contracts, and connect it to our Ethereum smart contract. + +### First alternative: automatic deploy and connect of Escrow and YABTransfer. ```bash - // For the deploy, you just need to configure the following variables in the .env file on the mm-bot folder - .. - SN_RPC_URL= // Infura or Alchemy RPC URL - ETH_CONTRACT_ADDR=0xdd69db25f6d620a7bad3023c5d32761d353d3de9 // GoerliETH - SN_CONTRACT_ADDR= - .. + make starknet-deploy-and-connect ``` -2. Declare and Deploy: We sequentially declare and deploy the contracts. + + This make target consists of 4 steps: + + 1. make starknet-build; builds the project + 2. make starknet-deploy; deploys the smart contract on the blockchain + 3. make ethereum-set-escrow; sets the newly created Starknet contract address on the Ethereum smart contract, so that the L1 contract can communicate with the L2 contract + 4. make ethereum-set-withdraw-selector; sets the Starknet _withdraw_ function name on the Ethereum smart contract, so that the L1 contract can communicate with the L2 contract + +### Second alternative: manual deploy and connect of Escrow and YABTransfer + +This may be better suited for you if you plan to change some of the automatically declared .env vars, or if you simply want to make sure you understand the process. + +1. Declare and Deploy: We sequentially declare and deploy the contracts. ```bash make starknet-deploy ``` -For Ethereum the deployment process you will need: + This script also sets an important .env variable, **ESCROW_CONTRACT_ADDRESS** -3. Updated `.env` file: Please modify the variables with your Testnet account and your RPC provider. +2. Setting _EscrowAddress_ + + After the Starknet smart contracts are declared and deployed, the variable _EscrowAddress_ from the Ethereum smart contract must be updated with the newly created Starknet smart contract address. + + To do this, you can use - ```bash - // For the deploy, you just need to configure the following variables in the .env file on the contracts/solidity/ folder - .. - ETH_RPC_URL= // Infura or Alchemy RPC URL - ETH_PRIVATE_KEY= - ETHERSCAN_API_KEY= - .. ``` - **NOTE**: + make ethereum-set-escrow + ``` - - You can generate ETHERSCAN_API_KEY [following this steps](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics). - - For the deploy, you will need some GoerliETH that you can get from this [faucet](https://goerlifaucet.com/). -4. Deploy Solidity contract + This script uses the previously set .env variable, **ESCROW_CONTRACT_ADDRESS** - ```bash - make ethereum-deploy +3. Setting _EscrowWithdrawSelector_ + + Ethereum's smart contract has another variable that must be configured, _EscrowWithdrawSelector_, which is for specifying the _withdraw_ function's name in the Starknet Escrow smart contract. + You can set and change Ethereum's _EscrowWithdrawSelector_ variable, doing the following: + + ``` + make ethereum-set-withdraw-selector ``` + + This script uses the WITHDRAW_NAME .env variable to automatically generate the selector in the necesary format + +## Recap + +After following this complete README, we should have an ETH smart contract as well as a Starknet smart contract, both connected to act as a bridge between these two chains. diff --git a/contracts/cairo/.env.example b/contracts/cairo/.env.example new file mode 100644 index 00000000..34bfcff6 --- /dev/null +++ b/contracts/cairo/.env.example @@ -0,0 +1,10 @@ +STARKNET_ACCOUNT= +STARKNET_KEYSTORE= +SN_RPC_URL= +ETH_CONTRACT_ADDR= #in hexa with the 0x prefix, with upper and lower cases like shown by etherscan +MM_SN_WALLET_ADDR= #in lowercase hexa with the 0x prefix +WITHDRAW_NAME= #must match the exact name of the function that withdraws from the starknet smart contract +HERODOTUS_FACTS_REGISTRY=<0x01b2111317EB693c3EE46633edd45A4876db14A3a53ACDBf4E5166976d8e869d|0x07d3550237ecf2d6ddef9b78e59b38647ee511467fe000ce276f245a006b40bc|0x014bf62fadb41d8f899bb5afeeb2da486fcfd8431852def56c5f10e45ae72765> # Goerli | Sepolia | Mainnet +MM_ETHEREUM_WALLET= #in lowercase hexa with the 0x prefix +NATIVE_TOKEN_ETH_STARKNET= #in lowercase hexa with the 0x prefix +ESCROW_CONTRACT_ADDRESS= #this value is automatically updated after deploy.sh is run diff --git a/contracts/cairo/deploy.sh b/contracts/cairo/deploy.sh index a40eabba..e729abde 100755 --- a/contracts/cairo/deploy.sh +++ b/contracts/cairo/deploy.sh @@ -6,37 +6,39 @@ PURPLE='\033[1;34m' PINK='\033[1;35m' COLOR_RESET='\033[0m' -HERODOTUS_FACTS_REGISTRY=0x01b2111317EB693c3EE46633edd45A4876db14A3a53ACDBf4E5166976d8e869d -MM_ETHEREUM_WALLET=0xE8504996d2e25735FA88B3A0a03B4ceD2d3086CC -NATIVE_TOKEN_ETH_STARKNET=0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 - cd "$(dirname "$0")" load_env() { unamestr=$(uname) if [ "$unamestr" = 'Linux' ]; then - export $(grep -v '^#' ../../mm-bot/.env | xargs -d '\n') + export $(sed '/^#/d; s/#.*$//' .env | xargs -d '\n') elif [ "$unamestr" = 'FreeBSD' ] || [ "$unamestr" = 'Darwin' ]; then - export $(grep -v '^#' ../../mm-bot/.env | xargs -0) + export $(sed '/^#/d; s/#.*$//' .env | xargs -0) fi } load_env echo -e "${GREEN}\n=> [SN] Declare Escrow${COLOR_RESET}" -ESCROW_CLASS_HASH=$(starkli declare --watch --rpc $SN_RPC_URL target/dev/yab_Escrow.contract_class.json) +ESCROW_CLASS_HASH=$(starkli declare \ + --account $STARKNET_ACCOUNT --keystore $STARKNET_KEYSTORE \ + --watch target/dev/yab_Escrow.contract_class.json) echo -e "- ${PURPLE}[SN] Escrow ClassHash: $ESCROW_CLASS_HASH${COLOR_RESET}" echo -e "- ${PURPLE}[SN] Herodotus Facts Registry: $HERODOTUS_FACTS_REGISTRY${COLOR_RESET}" -echo -e "- ${PURPLE}[SN] Market Maker: $SN_WALLET_ADDR${COLOR_RESET}" +echo -e "- ${PURPLE}[SN] Market Maker: $MM_SN_WALLET_ADDR${COLOR_RESET}" echo -e "- ${PURPLE}[SN] Ethereum ContractAddress $NATIVE_TOKEN_ETH_STARKNET${COLOR_RESET}" echo -e "- ${PINK}[ETH] Ethereum ContractAddress: $ETH_CONTRACT_ADDR${COLOR_RESET}" echo -e "- ${PINK}[ETH] Market Maker: $MM_ETHEREUM_WALLET${COLOR_RESET}" echo -e "${GREEN}\n=> [SN] Deploy Escrow${COLOR_RESET}" -ESCROW_CONTRACT_ADDRESS=$(starkli deploy --watch --rpc $SN_RPC_URL $ESCROW_CLASS_HASH \ +ESCROW_CONTRACT_ADDRESS=$(starkli deploy \ + --account $STARKNET_ACCOUNT --keystore $STARKNET_KEYSTORE \ + --watch $ESCROW_CLASS_HASH \ $HERODOTUS_FACTS_REGISTRY \ $ETH_CONTRACT_ADDR \ $MM_ETHEREUM_WALLET \ - $SN_WALLET_ADDR \ + $MM_SN_WALLET_ADDR \ $NATIVE_TOKEN_ETH_STARKNET) echo -e "- ${PURPLE}[SN] Escrow ContractAddress: $ESCROW_CONTRACT_ADDRESS${COLOR_RESET}" + +sed -i "s/^ESCROW_CONTRACT_ADDRESS=.*/ESCROW_CONTRACT_ADDRESS=$ESCROW_CONTRACT_ADDRESS/" ".env" || echo "ESCROW_CONTRACT_ADDRESS=$ESCROW_CONTRACT_ADDRESS" >> ".env" \ No newline at end of file diff --git a/contracts/solidity/.env.example b/contracts/solidity/.env.example index c3b42c15..ea79dc80 100644 --- a/contracts/solidity/.env.example +++ b/contracts/solidity/.env.example @@ -1,3 +1,4 @@ -GOERLI_RPC_URL= -PRIVATE_KEY= -ETHERSCAN_API_KEY= +ETH_RPC_URL= +ETH_PRIVATE_KEY= #in lowercase hexa with the 0x prefix +ETHERSCAN_API_KEY= +SN_MESSAGING_ADDRESS=<0xde29d060D45901Fb19ED6C6e959EB22d8626708e|0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057|0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4> # Goerli | Sepolia | Mainnet diff --git a/contracts/solidity/deploy.sh b/contracts/solidity/deploy.sh index a397406d..053ce958 100755 --- a/contracts/solidity/deploy.sh +++ b/contracts/solidity/deploy.sh @@ -9,12 +9,12 @@ cd "$(dirname "$0")" load_env() { unamestr=$(uname) if [ "$unamestr" = 'Linux' ]; then - export $(grep -v '^#' ./.env | xargs -d '\n') + export $(sed '/^#/d; s/#.*$//' .env | xargs -d '\n') elif [ "$unamestr" = 'FreeBSD' ] || [ "$unamestr" = 'Darwin' ]; then - export $(grep -v '^#' ./.env | xargs -0) + export $(sed '/^#/d; s/#.*$//' .env | xargs -0) fi } load_env echo -e "${GREEN}\n=> [ETH] Deploy Escrow${COLOR_RESET}" -forge script ./script/Deploy.s.sol --fork-url $GOERLI_RPC_URL --broadcast --verify -vvvv \ No newline at end of file +forge script ./script/Deploy.s.sol --fork-url $ETH_RPC_URL --broadcast --verify -vvvv diff --git a/contracts/solidity/script/Deploy.s.sol b/contracts/solidity/script/Deploy.s.sol index 00c069c4..5005cf52 100644 --- a/contracts/solidity/script/Deploy.s.sol +++ b/contracts/solidity/script/Deploy.s.sol @@ -9,9 +9,10 @@ contract Deploy is Script { uint256 deployerPrivateKey = vm.envUint("ETH_PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); - address snMessagingAddress = 0xde29d060D45901Fb19ED6C6e959EB22d8626708e; - uint256 snEscrowAddress = 0x0; - uint256 snEscrowWithdrawSelector = 0x0; + address snMessagingAddress = vm.envAddress("SN_MESSAGING_ADDRESS"); + uint256 snEscrowAddress = 0x0; //this value is set in a call to the smart contract, once deployed + uint256 snEscrowWithdrawSelector = 0x0; //this value is set in a call to the smart contract, once deployed + new YABTransfer( snMessagingAddress, diff --git a/contracts/solidity/set_escrow.sh b/contracts/solidity/set_escrow.sh new file mode 100755 index 00000000..f76f532e --- /dev/null +++ b/contracts/solidity/set_escrow.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# ANSI format +GREEN='\e[32m' +COLOR_RESET='\033[0m' + + +echo -e "${GREEN}\n=> [ETH] Setting Starknet Escrow Address on ETH Smart Contract${COLOR_RESET}" + +if [ -f ./contracts/solidity/.env ]; then + echo "Sourcing solidity/.env file..." + source ./contracts/solidity/.env +else + echo "Error: solidity/.env file not found!" + exit 1 +fi +if [ -f ./contracts/cairo/.env ]; then + echo "Sourcing cairo/.env file..." + source ./contracts/cairo/.env +else + echo "Error: cairo/.env file not found!" + exit 1 +fi + +echo "Smart contract being modified:" $ETH_CONTRACT_ADDR +echo "New Escrow address:" $ESCROW_CONTRACT_ADDRESS + +cast send --rpc-url $ETH_RPC_URL --private-key $ETH_PRIVATE_KEY $ETH_CONTRACT_ADDR "setEscrowAddress(uint256)" $ESCROW_CONTRACT_ADDRESS diff --git a/contracts/solidity/set_withdraw_selector.sh b/contracts/solidity/set_withdraw_selector.sh new file mode 100755 index 00000000..bd4bdfaa --- /dev/null +++ b/contracts/solidity/set_withdraw_selector.sh @@ -0,0 +1,27 @@ +#!/bin/bash +if [ -f ./contracts/solidity/.env ]; then + echo "Sourcing solidity/.env file..." + source ./contracts/solidity/.env +else + echo "Error: solidity/.env file not found!" + exit 1 +fi +if [ -f ./contracts/cairo/.env ]; then + echo "Sourcing cairo/.env file..." + source ./contracts/cairo/.env +else + echo "Error: cairo/.env file not found!" + exit 1 +fi + +# ANSI format +GREEN='\e[32m' +COLOR_RESET='\033[0m' + +echo -e "${GREEN}\n=> [ETH] Setting Starknet Withdraw Selector on ETH Smart Contract${COLOR_RESET}" +echo "Smart contract being modified:" $ETH_CONTRACT_ADDR + +WITHDRAW_SELECTOR=$(starkli selector $WITHDRAW_NAME) +echo "New Withdraw Selector: ${WITHDRAW_SELECTOR}" + +cast send --rpc-url $ETH_RPC_URL --private-key $ETH_PRIVATE_KEY $ETH_CONTRACT_ADDR "setEscrowWithdrawSelector(uint256)" "${WITHDRAW_SELECTOR}" diff --git a/contracts/solidity/test/Transfer.sol b/contracts/solidity/test/Transfer.sol index 6f16df4d..96c4b99b 100644 --- a/contracts/solidity/test/Transfer.sol +++ b/contracts/solidity/test/Transfer.sol @@ -10,7 +10,7 @@ contract TransferTest is Test { function setUp() public { address snMessagingAddress = 0xde29d060D45901Fb19ED6C6e959EB22d8626708e; uint256 snEscrowAddress = 0x0; - uint256 snEscrowWithdrawSelector = 0x0; + uint256 snEscrowWithdrawSelector = 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77; yab = new YABTransfer(snMessagingAddress, snEscrowAddress, snEscrowWithdrawSelector); }