diff --git a/docs/build/quick-start/best-practices.md b/docs/build/quick-start/best-practices.md index 6020b55946..5866204bba 100644 --- a/docs/build/quick-start/best-practices.md +++ b/docs/build/quick-start/best-practices.md @@ -114,3 +114,7 @@ We provide [two different testing environments](../../build/test-and-debug/getti By incorporating local testing into your development workflow, you can effectively verify the behavior and functionality of your contracts in a controlled environment, ensuring a smooth deployment process to the mainnet. For detailed instructions on configuring the local testing environment and performing tests using Mocha and Chai, refer to the dedicated [Testing](../../build/test-and-debug/getting-started.md) page. + +## Always use encrypted private keys + +Be sure to see [private key best practices](../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. diff --git a/docs/build/support/private-key-management.md b/docs/build/support/private-key-management.md new file mode 100644 index 0000000000..e09e64411a --- /dev/null +++ b/docs/build/support/private-key-management.md @@ -0,0 +1,98 @@ +--- +head: + - - meta + - name: "twitter:title" + content: Private Key Management | zkSync Docs +--- + +# Working with Private Keys + +In all our tutorials and guides, we use private keys to interact with zkSync. Most tutorials use `.env` files to store private keys in "plaintext", which [is considered bad practice](https://github.com/Cyfrin/foundry-full-course-f23/discussions/5). In this guide, we'll teach you a few safer ways to manage your keys. + +You can take a look at the [.env pledge](https://github.com/Cyfrin/foundry-full-course-f23/discussions/5) which is an oath developers should take before working with private keys in their development files. + +The main rule of thumb, is that you should never have a private key associated with real funds in plaintext. By "in plaintext" we mean unencrypted. If you are sure that a private key has no funds and will never have funds associated with it, feel free to put that key in a `.env` file. Otherwise, head the suggestions below. + +## Hardhat + +For the hardhat framework, there is no built-in encryption methods for private keys, and for this reason alone foundry is preferred. They have [configuration variables](https://hardhat.org/hardhat-runner/docs/guides/configuration-variables), however, these keep your private key in plain text and just move the file location to somewhere else in your directory. + +Instead, we can use javascript (or typescript) to encrypt and decrypt our keys ourselves according to [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335). + +You can see the full example with [deployment in Ethers here.](https://github.com/PatrickAlphaC/ethers-simple-storage-fcc/blob/main/encryptKey.js) + +`encryptKey.js`: + +```javascript +const ethers = require("ethers"); // ^6.2.3 of ethers +const fs = require("fs-extra"); +require("dotenv").config(); + +async function main() { + const wallet = new ethers.Wallet(process.env.PRIVATE_KEY); + + const encryptedJsonKey = await wallet.encrypt(process.env.PRIVATE_KEY_PASSWORD); + console.log(encryptedJsonKey); + fs.writeFileSync("./.encryptedKey.json", encryptedJsonKey); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); +``` + +This is a `nodejs` script you can run to encrypt your key and save it to `.encryptedKey.json`. Once you have your key encrypted, you can then decrypt it in your scripts like so: + +```javascript +const ethers = require("ethers"); +const fs = require("fs-extra"); +require("dotenv").config(); + +async function main() { + const encryptedJson = fs.readFileSync("./.encryptedKey.json", "utf8"); + let wallet = new ethers.Wallet.fromEncryptedJsonSync(encryptedJson, process.env.PRIVATE_KEY_PASSWORD); +} +``` + +::: warning +If you do this, remember to add `.encryptedKey.json` to your `.gitignore` file! +::: + +## Foundry + +Foundry supports [encrypting keys by default](https://www.youtube.com/watch?v=VQe7cIpaE54) by using the `cast wallet import` command. Normally, to run a foundry script, you'd run a command like so to deploy a smart contract: + +```bash +forge script script/Deploy.sol --private-key $PRIVATE_KEY --rpc-url $RPC_URL +``` + +Where `PRIVATE_KEY` is your private key from a `.env` file. This is of course not good because once again our private key is in plaintext. + +However, we can encrypt our key by running: + +``` +cast wallet import account_name --interactive +``` + +And it will drop you into a shell to import your private key. Once it's imported, you'll be able to see it with `cast wallet list`. + +Then, you can run your script like so: + +```bash +forge script script/Deploy.sol --account account_name --sender $WALLET_ADDRESS --rpc-url $RPC_URL +``` + +The [foundry documentation](https://book.getfoundry.sh/tutorials/best-practices?highlight=patrick#private-key-management) has additional notes on secure private key management. + +## Your own + +And of course, you can always roll your own private key solution if you choose to do so. + +# Summary + +1. Never have a private key associated with real funds in plaintext. +2. Ideally, use a separate wallet for testing and development. +3. If you accidentally expose a private key, consider the whole thing compromised and try to move funds to a new wallet. diff --git a/docs/build/tooling/foundry/getting-started.md b/docs/build/tooling/foundry/getting-started.md index 833c413591..379edf3710 100644 --- a/docs/build/tooling/foundry/getting-started.md +++ b/docs/build/tooling/foundry/getting-started.md @@ -184,6 +184,12 @@ contract Greeter { forge create src/Greeter.sol:Greeter --constructor-args "Hello zkSync" --private-key --rpc-url https://sepolia.era.zksync.dev --chain 300 --zksync ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + ### Deploying Factory Contracts To deploy contracts like `GreeterFactory.sol`, use the `is-system` flag. diff --git a/docs/build/tooling/hardhat/getting-started.md b/docs/build/tooling/hardhat/getting-started.md index f357e37038..f5830697d9 100644 --- a/docs/build/tooling/hardhat/getting-started.md +++ b/docs/build/tooling/hardhat/getting-started.md @@ -159,6 +159,12 @@ Rename `.env.example` to `.env` and input your private key: WALLET_PRIVATE_KEY=YourPrivateKeyHere... ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + Your private key will be used for paying the costs of deploying the smart contract. ## Compile and deploy a contract diff --git a/docs/build/tooling/hardhat/hardhat-zksync-deploy.md b/docs/build/tooling/hardhat/hardhat-zksync-deploy.md index 27c9dd4c54..37a28b7e74 100644 --- a/docs/build/tooling/hardhat/hardhat-zksync-deploy.md +++ b/docs/build/tooling/hardhat/hardhat-zksync-deploy.md @@ -214,6 +214,12 @@ const config: HardhatUserConfig = { }; ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + - `accounts` represents a list of the private keys or mnemonic object for the account used in the deployment process. :::tip Accounts on zkSync Era Test Node or zksync-cli Local Node diff --git a/docs/build/tutorials/dapp-development/gated-nft-paymaster-tutorial.md b/docs/build/tutorials/dapp-development/gated-nft-paymaster-tutorial.md index 3fbb87fe3b..b6f645652a 100644 --- a/docs/build/tutorials/dapp-development/gated-nft-paymaster-tutorial.md +++ b/docs/build/tutorials/dapp-development/gated-nft-paymaster-tutorial.md @@ -104,6 +104,12 @@ The template provides a ready-to-use `hardhat.config.ts` file that targets zkSyn WALLET_PRIVATE_KEY=YourPrivateKeyHere... ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + Your private key will be used for paying the costs of deploying the smart contract. ::: warning diff --git a/docs/build/tutorials/how-to/deploy-contract.md b/docs/build/tutorials/how-to/deploy-contract.md index eacb31ff25..ca349296e2 100644 --- a/docs/build/tutorials/how-to/deploy-contract.md +++ b/docs/build/tutorials/how-to/deploy-contract.md @@ -217,6 +217,12 @@ export default async function (hre: HardhatRuntimeEnvironment) { } ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + To deploy contract on `zkSync Sepolia Testnet` that we already specified as default network in our **hardhat.config.ts**, run command: ```bash diff --git a/docs/build/tutorials/how-to/deposit-erc-20-to-l2.md b/docs/build/tutorials/how-to/deposit-erc-20-to-l2.md index 3c1833e4b2..5ee8473f2d 100644 --- a/docs/build/tutorials/how-to/deposit-erc-20-to-l2.md +++ b/docs/build/tutorials/how-to/deposit-erc-20-to-l2.md @@ -64,6 +64,12 @@ WALLET_PRIV_KEY= L1_RPC_ENDPOINT= ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + ### Step 3: Create the Deposit Script Create a new file `deposit-erc20.ts` and insert the below code: diff --git a/docs/build/tutorials/how-to/deposit-eth-to-l2.md b/docs/build/tutorials/how-to/deposit-eth-to-l2.md index 1aa37ad542..d8ef1bf940 100644 --- a/docs/build/tutorials/how-to/deposit-eth-to-l2.md +++ b/docs/build/tutorials/how-to/deposit-eth-to-l2.md @@ -64,6 +64,12 @@ WALLET_PRIV_KEY= L1_RPC_ENDPOINT= ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + ### Step 3: Create the Deposit Script Create a new file `deposit.ts` and insert the below code: diff --git a/docs/build/tutorials/how-to/send-message-l2-l1.md b/docs/build/tutorials/how-to/send-message-l2-l1.md index 448658e1d3..190196a77b 100644 --- a/docs/build/tutorials/how-to/send-message-l2-l1.md +++ b/docs/build/tutorials/how-to/send-message-l2-l1.md @@ -72,6 +72,12 @@ yarn add zksync-ethers@5 ethers@5 typescript @types/node ts-node "RICH_WALLET_PRIV_KEY=0x.."; ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + 6. Create a `file.ts` file in the root directory with the next script: ```ts diff --git a/docs/build/tutorials/how-to/send-transaction-l1-l2.md b/docs/build/tutorials/how-to/send-transaction-l1-l2.md index 5625b70076..e4f645dd8b 100644 --- a/docs/build/tutorials/how-to/send-transaction-l1-l2.md +++ b/docs/build/tutorials/how-to/send-transaction-l1-l2.md @@ -249,6 +249,12 @@ User needs to perform next steps: "RICH_WALLET_PRIV_KEY=0x.."; ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + 4. Add script to package.json file next script: ```js diff --git a/docs/build/tutorials/how-to/test-contracts.md b/docs/build/tutorials/how-to/test-contracts.md index eeda629b8d..8184e59838 100644 --- a/docs/build/tutorials/how-to/test-contracts.md +++ b/docs/build/tutorials/how-to/test-contracts.md @@ -292,6 +292,12 @@ describe("Greeter", function () { }); ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + Execute the following command in your terminal to run the tests: ```bash diff --git a/docs/build/tutorials/how-to/transfer-token-l2.md b/docs/build/tutorials/how-to/transfer-token-l2.md index 3a6bdffdd2..94363d5082 100644 --- a/docs/build/tutorials/how-to/transfer-token-l2.md +++ b/docs/build/tutorials/how-to/transfer-token-l2.md @@ -61,6 +61,12 @@ const zkSyncProvider = new zksync.Provider("https://sepolia.era.zksync.dev"); const zkSyncWallet = new zksync.Wallet("", zkSyncProvider); ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + ### 4. Store the recipient's public key Save the recipient's wallet address to a variable, replacing `` with their public key. diff --git a/docs/build/tutorials/how-to/verify-contracts.md b/docs/build/tutorials/how-to/verify-contracts.md index 8d708bb94e..574869a212 100644 --- a/docs/build/tutorials/how-to/verify-contracts.md +++ b/docs/build/tutorials/how-to/verify-contracts.md @@ -136,6 +136,10 @@ To configure your private key, copy the `.env.example` file, rename the copy to WALLET_PRIVATE_KEY=YourPrivateKeyHere.... ``` +::: warning +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. +::: + Your private key will be used for paying the costs of deploying the smart contract. Initiate contract deployment using this command: diff --git a/docs/build/tutorials/how-to/withdraw-erc-20-to-l1.md b/docs/build/tutorials/how-to/withdraw-erc-20-to-l1.md index 3295606716..ede437b036 100644 --- a/docs/build/tutorials/how-to/withdraw-erc-20-to-l1.md +++ b/docs/build/tutorials/how-to/withdraw-erc-20-to-l1.md @@ -63,6 +63,12 @@ WALLET_PRIV_KEY= L1_RPC_ENDPOINT= ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + ### Step 3: Create the Withdrawal Script Create a new file `withdraw-erc20.ts` and insert the following code. This script utilizes the `withdraw` method from the `Wallet` class of the zkSync Javascript SDK to withdraw ETH. Adjust the `AMOUNT` and `TOKEN_ADDRESS` variable if necessary. diff --git a/docs/build/tutorials/how-to/withdraw-eth-to-l1.md b/docs/build/tutorials/how-to/withdraw-eth-to-l1.md index f8cdbdfb4e..a75e60a6d6 100644 --- a/docs/build/tutorials/how-to/withdraw-eth-to-l1.md +++ b/docs/build/tutorials/how-to/withdraw-eth-to-l1.md @@ -63,6 +63,12 @@ WALLET_PRIV_KEY= L1_RPC_ENDPOINT= ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + ### Step 3: Create the Withdrawal Script Create a new file `withdraw.ts` and insert the following code. This script utilizes the `withdraw` method from the `Wallet` class of the zkSync Javascript SDK to withdraw ETH. Adjust the `AMOUNT` variable if necessary. diff --git a/docs/build/tutorials/smart-contract-development/account-abstraction/custom-aa-tutorial.md b/docs/build/tutorials/smart-contract-development/account-abstraction/custom-aa-tutorial.md index 0fe12c58db..eee5109dff 100644 --- a/docs/build/tutorials/smart-contract-development/account-abstraction/custom-aa-tutorial.md +++ b/docs/build/tutorials/smart-contract-development/account-abstraction/custom-aa-tutorial.md @@ -842,6 +842,12 @@ Make sure you deposit funds on zkSync Era using [one of the available bridges](h 1. In the `deploy` folder, create the file `deploy-factory.ts` and copy/paste the following code, replacing `` with your private key. +::: warning + +Be sure to see [private key best practices](../../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + ```ts import { utils, Wallet } from "zksync-ethers"; import * as ethers from "ethers"; diff --git a/docs/build/tutorials/smart-contract-development/account-abstraction/daily-spend-limit.md b/docs/build/tutorials/smart-contract-development/account-abstraction/daily-spend-limit.md index 04950b0867..b351466243 100644 --- a/docs/build/tutorials/smart-contract-development/account-abstraction/daily-spend-limit.md +++ b/docs/build/tutorials/smart-contract-development/account-abstraction/daily-spend-limit.md @@ -765,6 +765,12 @@ yarn hardhat compile 2. Create a file named `deploy/deployFactoryAccount.ts`. Then, copy and paste the following code into it. Remember to add your `DEPLOYER_PRIVATE_KEY` to the .env file. +::: warning + +Be sure to see [private key best practices](../../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + The script deploys the factory, creates a new smart contract account, and funds it with some ETH. ```typescript @@ -825,7 +831,7 @@ export default async function (hre: HardhatRuntimeEnvironment) { } ``` -3. Run the script. +1. Run the script. ```sh yarn hardhat deploy-zksync --script deployFactoryAccount.ts diff --git a/docs/build/tutorials/smart-contract-development/cross-chain-tutorial.md b/docs/build/tutorials/smart-contract-development/cross-chain-tutorial.md index 49fbe0b3ec..17bac921d8 100644 --- a/docs/build/tutorials/smart-contract-development/cross-chain-tutorial.md +++ b/docs/build/tutorials/smart-contract-development/cross-chain-tutorial.md @@ -140,6 +140,12 @@ contract Governance { } ``` +::: warning + +Be sure to see [private key best practices](../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + 2. Replace the code in `hardhat.config.ts` with the following: ```ts diff --git a/docs/build/tutorials/smart-contract-development/paymasters/allowlist.md b/docs/build/tutorials/smart-contract-development/paymasters/allowlist.md index 186b7a4bc8..9e16e029c8 100644 --- a/docs/build/tutorials/smart-contract-development/paymasters/allowlist.md +++ b/docs/build/tutorials/smart-contract-development/paymasters/allowlist.md @@ -184,8 +184,12 @@ export default async function (hre: HardhatRuntimeEnvironment) { } ``` -:::info -Be sure to add your private key to the `.env` file.; +::: warning + +Be sure to see [private key best practices](../../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +For this tutorial, we need to add your private key to a `.env` file. Please do not use a private key associated with live funds when your key is unencrypted. + ::: The provided script takes care of loading environment variables, setting up a deployment wallet with the private key specified in an `.env` file, contract deployment and funding the paymaster. You can adjust the amount of ETH to fund the paymaster to your needs.; diff --git a/docs/build/tutorials/smart-contract-development/paymasters/erc20fixed.md b/docs/build/tutorials/smart-contract-development/paymasters/erc20fixed.md index 53baea0cf2..7424aa9c79 100644 --- a/docs/build/tutorials/smart-contract-development/paymasters/erc20fixed.md +++ b/docs/build/tutorials/smart-contract-development/paymasters/erc20fixed.md @@ -300,6 +300,12 @@ describe.only("ERC20fixedPaymaster", function () { }); ``` +::: warning + +Be sure to see [private key best practices](../../../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + This particular script assesses the paymaster's ability to cover gas expenses for accounts, provided they hold a balance in the designated ERC20 token. To execute test: diff --git a/docs/build/tutorials/smart-contract-development/paymasters/gasless.md b/docs/build/tutorials/smart-contract-development/paymasters/gasless.md index 62b83db011..b8501607ab 100644 --- a/docs/build/tutorials/smart-contract-development/paymasters/gasless.md +++ b/docs/build/tutorials/smart-contract-development/paymasters/gasless.md @@ -120,6 +120,12 @@ export default async function (hre: HardhatRuntimeEnvironment) { } ``` +::: warning + +Be sure to see [private key best practices](../../../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + :::info Be sure to add your private key to the `.env` file.; ::: diff --git a/docs/build/tutorials/smart-contract-development/paymasters/timebased.md b/docs/build/tutorials/smart-contract-development/paymasters/timebased.md index dbffb0edae..753dfb36e7 100644 --- a/docs/build/tutorials/smart-contract-development/paymasters/timebased.md +++ b/docs/build/tutorials/smart-contract-development/paymasters/timebased.md @@ -140,6 +140,12 @@ export default async function (hre: HardhatRuntimeEnvironment) { } ``` +::: warning + +Be sure to see [private key best practices](../../../support/private-key-management.md) before working with private keys associated with real funds so you don't accidentally expose your private key. + +::: + :::info Be sure to add your private key to the `.env` file. :::