-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: test daily spend limit tutorial (#56)
adds a test for the daily spend limit tutorial and minor fixes
- Loading branch information
1 parent
939b796
commit 3398dae
Showing
11 changed files
with
424 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,32 +42,51 @@ with the smart contracts in this project. | |
|
||
1. Initiate a new project by running the command: | ||
|
||
:test-action{actionId="initialize-project"} | ||
|
||
```sh | ||
npx zksync-cli create custom-spendlimit-tutorial --template hardhat_solidity | ||
``` | ||
|
||
This creates a new ZKsync Era project called `custom-spendlimit-tutorial` with a with a few example contracts. | ||
This creates a new ZKsync Era project called `custom-spendlimit-tutorial` with a few example contracts. | ||
|
||
1. Navigate into the project directory: | ||
|
||
:test-action{actionId="wait-for-init"} | ||
:test-action{actionId="move-into-project"} | ||
|
||
```sh | ||
cd custom-spendlimit-tutorial | ||
``` | ||
|
||
1. For the purposes of this tutorial, we don't need the example contracts related files. So, proceed by removing all the | ||
files inside the `/contracts` and `/deploy` folders manually or by running the following commands: | ||
:test-action{actionId="delete-template-files"} | ||
```sh | ||
rm -rf ./contracts/* | ||
rm -rf ./deploy/* | ||
``` | ||
1. Add the ZKsync and OpenZeppelin contract libraries: | ||
```sh | ||
yarn add -D @matterlabs/zksync-contracts @openzeppelin/[email protected] | ||
:test-action{actionId="install-deps"} | ||
::code-group | ||
```bash [npm] | ||
npm install -D @matterlabs/zksync-contracts @openzeppelin/[email protected] @matterlabs/[email protected] | ||
``` | ||
```bash [yarn] | ||
yarn add -D @matterlabs/zksync-contracts @openzeppelin/[email protected] @matterlabs/[email protected] | ||
``` | ||
:: | ||
:test-action{actionId="wait-for-install"} | ||
::callout{icon="i-heroicons-exclamation-triangle"} | ||
This project does not use the latest version available of | ||
`@openzeppelin/contracts`. Make sure you install the specific version mentioned above. | ||
|
@@ -76,6 +95,8 @@ with the smart contracts in this project. | |
1. Include the `isSystem: true` setting in the `zksolc` section of the `hardhat.config.ts` configuration file to allow | ||
interaction with system contracts: | ||
:test-action{actionId="hardhat-config"} | ||
```typescript [hardhat.config.ts] | ||
import { HardhatUserConfig } from "hardhat/config"; | ||
|
@@ -117,6 +138,9 @@ with the smart contracts in this project. | |
export default config; | ||
``` | ||
|
||
:test-action{actionId="start-local-node"} | ||
:test-action{actionId="deploy-to-local-node"} | ||
|
||
## Design | ||
|
||
Now let’s dive into the design and implementation of the daily spending limit feature. | ||
|
@@ -337,6 +361,12 @@ limit.available -= _amount; | |
1. In the folder `contracts`, add a file called `SpendLimit.sol` | ||
:test-action{actionId="add-spend-limit-file"} | ||
```sh | ||
touch contracts/SpendLimit.sol | ||
``` | ||
1. Copy/paste the complete code below. | ||
::callout{icon="i-heroicons-exclamation-triangle"} | ||
|
@@ -345,6 +375,9 @@ limit.available -= _amount; | |
forget to change the value before deploying the contract. | ||
:: | ||
:test-action{actionId="open-spend-limit-code-panel"} | ||
:test-action{actionId="spend-limit-contract"} | ||
::drop-panel | ||
::panel{label="SpendLimit.sol"} | ||
|
@@ -481,6 +514,12 @@ The main difference is that our account has a single signer. | |
1. Create a file `Account.sol` in the `contracts` folder. | ||
:test-action{actionId="account-contract-file"} | ||
```sh | ||
touch contracts/Account.sol | ||
``` | ||
2. Copy/paste the code below. | ||
The account implements the [IAccount](https://docs.zksync.io/build/developer-reference/account-abstraction/design#iaccount-interface) interface | ||
|
@@ -491,6 +530,9 @@ Since we are building an account with signers, we should also implement | |
The `isValidSignature` method will take care of verifying the signature and making sure the extracted address matches | ||
with the owner of the account. | ||
:test-action{actionId="open-account-code-panel"} | ||
:test-action{actionId="add-account-contract"} | ||
::drop-panel | ||
::panel{label="Account.sol"} | ||
|
@@ -749,7 +791,17 @@ bytes from transaction calldata. | |
The `AAFactory.sol` contract is responsible for deploying instances of the `Account.sol` contract. | ||
1. Create the `AAFactory.sol` file in the `contracts` folder and copy/paste the code below. | ||
1. Create the `AAFactory.sol` file in the `contracts` folder. | ||
:test-action{actionId="aa-factory-file"} | ||
```sh | ||
touch contracts/AAFactory.sol | ||
``` | ||
1. Copy/paste the code below. | ||
:test-action{actionId="aa-factory-contract"} | ||
```solidity [AAFactory.sol] | ||
// SPDX-License-Identifier: MIT | ||
|
@@ -795,16 +847,35 @@ contract AAFactory { | |
1. Compile the contracts from the project root. | ||
```sh | ||
yarn hardhat compile | ||
:test-action{actionId="compile"} | ||
::code-group | ||
```bash [npm] | ||
npm run compile | ||
``` | ||
```bash [yarn] | ||
yarn compile | ||
``` | ||
1. Create a file named `deploy/deployFactoryAccount.ts`. Then, copy and paste the following code into it. Remember to | ||
:: | ||
1. Create a file named `deploy/deploy.ts`. Then, copy and paste the following code into it. Remember to | ||
add your `DEPLOYER_PRIVATE_KEY` to the .env file. | ||
:test-action{actionId="create-deploy-factory-script-file"} | ||
```sh | ||
touch deploy/deploy.ts | ||
``` | ||
The script deploys the factory, creates a new smart contract account, and funds it with some ETH. | ||
```typescript [deploy/deployFactoryAccount.ts] | ||
:test-action{actionId="modify-env-file"} | ||
:test-action{actionId="deploy-factory-script"} | ||
```typescript [deploy/deploy.ts] | ||
import { utils, Wallet, Provider } from "zksync-ethers"; | ||
import * as ethers from "ethers"; | ||
import { HardhatRuntimeEnvironment } from "hardhat/types"; | ||
|
@@ -818,7 +889,7 @@ contract AAFactory { | |
export default async function (hre: HardhatRuntimeEnvironment) { | ||
// @ts-ignore target zkSyncSepoliaTestnet in config file which can be testnet or local | ||
const provider = new Provider(hre.config.networks.zkSyncSepoliaTestnet.url); | ||
const provider = new Provider(hre.network.config.url); | ||
const wallet = new Wallet(DEPLOYER_PRIVATE_KEY, provider); | ||
const deployer = new Deployer(hre, wallet); | ||
const factoryArtifact = await deployer.loadArtifact("AAFactory"); | ||
|
@@ -864,10 +935,20 @@ contract AAFactory { | |
1. Run the script. | ||
```sh | ||
yarn hardhat deploy-zksync --script deployFactoryAccount.ts | ||
:test-action{actionId="run-deploy-script"} | ||
::code-group | ||
```bash [npm] | ||
npm run deploy | ||
``` | ||
```bash [yarn] | ||
yarn deploy | ||
``` | ||
:: | ||
You should see the following: | ||
```txt | ||
|
@@ -886,12 +967,24 @@ address in order to track transactions and changes in the balance. | |
1. Create the file `setLimit.ts` in the `deploy` folder and copy/paste the example code below. | ||
:test-action{actionId="wait-for-script"} | ||
:test-action{actionId="create-set-limit-script"} | ||
```sh | ||
touch deploy/setLimit.ts | ||
``` | ||
1. Replace `<DEPLOYED_ACCOUNT_ADDRESS>` and `<DEPLOYED_ACCOUNT_OWNER_PRIVATE_KEY>` with the output from the previous | ||
section in your `.env` file. | ||
:test-action{actionId="get-deployed-account-address"} | ||
:test-action{actionId="get-private-key"} | ||
To enable the daily spending limit, we execute the `setSpendingLimit` function with two parameters: token address and limit amount. | ||
The token address is `ETH_ADDRESS` and the limit parameter is `0.0005` in the example below (and can be any amount). | ||
:test-action{actionId="set-limit-script"} | ||
```typescript [setLimit.ts] | ||
import { utils, Wallet, Provider, Contract, EIP712Signer, types } from "zksync-ethers"; | ||
import * as ethers from "ethers"; | ||
|
@@ -908,7 +1001,7 @@ address in order to track transactions and changes in the balance. | |
export default async function (hre: HardhatRuntimeEnvironment) { | ||
// @ts-ignore target zkSyncSepoliaTestnet in config file which can be testnet or local | ||
const provider = new Provider(hre.config.networks.zkSyncSepoliaTestnet.url); | ||
const provider = new Provider(hre.network.config.url); | ||
const owner = new Wallet(DEPLOYED_ACCOUNT_OWNER_PRIVATE_KEY, provider); | ||
|
@@ -956,10 +1049,20 @@ address in order to track transactions and changes in the balance. | |
1. Run the script. | ||
```sh | ||
:test-action{actionId="run-set-limit-script"} | ||
::code-group | ||
```bash [npx] | ||
npx hardhat deploy-zksync --script setLimit.ts | ||
``` | ||
```bash [yarn] | ||
yarn hardhat deploy-zksync --script setLimit.ts | ||
``` | ||
:: | ||
You should see the following output: | ||
```text | ||
|
@@ -977,10 +1080,19 @@ Let's test the `SpendLimit` contract works to make it refuse ETH transfers that | |
1. Create `transferETH.ts` and copy/paste the example code below, replacing the placeholder constants as before and | ||
adding an account address for `RECEIVER_ACCOUNT`. | ||
```typescript [transferETH.ts] | ||
:test-action{actionId="add-receiver-account"} | ||
:test-action{actionId="create-transfer-script"} | ||
```sh | ||
touch deploy/transferETH.ts | ||
``` | ||
:test-action{actionId="add-transfer-script"} | ||
```typescript [deploy/transferETH.ts] | ||
import { utils, Wallet, Provider, Contract, EIP712Signer, types } from "zksync-ethers"; | ||
import * as ethers from "ethers"; | ||
import { HardhatRuntimeEnvironment } from "hardhat/types"; | ||
import type { HardhatRuntimeEnvironment } from "hardhat/types"; | ||
// load env file | ||
import dotenv from "dotenv"; | ||
|
@@ -994,7 +1106,7 @@ Let's test the `SpendLimit` contract works to make it refuse ETH transfers that | |
export default async function (hre: HardhatRuntimeEnvironment) { | ||
// @ts-ignore target zkSyncSepoliaTestnet in config file which can be testnet or local | ||
const provider = new Provider(hre.config.networks.zkSyncSepoliaTestnet.url); | ||
const provider = new Provider(hre.network.config.url); | ||
const owner = new Wallet(DEPLOYED_ACCOUNT_OWNER_PRIVATE_KEY, provider); | ||
|
@@ -1034,11 +1146,13 @@ Let's test the `SpendLimit` contract works to make it refuse ETH transfers that | |
console.log("Available today: ", limitData.available.toString()); | ||
// L1 timestamp tends to be undefined in latest blocks. So it should find the latest L1 Batch first. | ||
let l1BatchRange = await provider.getL1BatchBlockRange(await provider.getL1BatchNumber()); | ||
let l1TimeStamp = (await provider.getBlock(l1BatchRange[1])).l1BatchTimestamp; | ||
if (hre.network.config.ethNetwork !== 'localhost') { | ||
let l1BatchRange = await provider.getL1BatchBlockRange(await provider.getL1BatchNumber()); | ||
let l1TimeStamp = (await provider.getBlock(l1BatchRange[1])).l1BatchTimestamp; | ||
console.log("L1 timestamp: ", l1TimeStamp); | ||
console.log("Limit will reset on timestamp: ", limitData.resetTime.toString()); | ||
console.log('L1 timestamp: ', l1TimeStamp); | ||
console.log('Limit will reset on timestamp: ', limitData.resetTime.toString()); | ||
} | ||
// actually do the ETH transfer | ||
console.log("Sending ETH transfer from smart contract account"); | ||
|
@@ -1064,10 +1178,20 @@ Let's test the `SpendLimit` contract works to make it refuse ETH transfers that | |
1. Run the script to attempt to make a transfer. | ||
```shell | ||
:test-action{actionId="run-transfer-script"} | ||
::code-group | ||
```bash [npx] | ||
npx hardhat deploy-zksync --script transferETH.ts | ||
``` | ||
```bash [yarn] | ||
yarn hardhat deploy-zksync --script transferETH.ts | ||
``` | ||
:: | ||
You should see an error message with the following content so we know it failed because the amount exceeded the limit. | ||
```shell | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.