diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..a32855d --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,27 @@ +name: run + +on: + pull_request: + branches: [main] + workflow_dispatch: +jobs: + tests: + name: unit-tests + strategy: + matrix: + platform: [ubuntu-latest] + runs-on: ${{ matrix.platform }} + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Run Era Test Node + uses: dutterbutter/era-test-node-action@latest + + - name: Install Dependencies + run: yarn install + + - name: Run Tests + run: | + yarn ci:tests \ No newline at end of file diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index ac8001b..8cb3bc0 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -5,18 +5,23 @@ import "@matterlabs/hardhat-zksync-solc"; import "@matterlabs/hardhat-zksync-verify"; import "@nomiclabs/hardhat-etherscan"; -// dynamically changes endpoints for local tests -const zkSyncTestnet = - process.env.NODE_ENV == "test" - ? { +const getNetworkConfig = () => { + const env = process.env.DEPLOY_ENV || "local"; + switch (env) { + case "local": + return { url: "http://localhost:3050", ethNetwork: "http://localhost:8545", zksync: true, - // Verification endpoint for Goerli - verifyURL: - "https://zksync2-testnet-explorer.zksync.dev/contract_verification", - } - : { + }; + case "ci": + return { + url: "http://127.0.0.1:8011", + ethNetwork: "goerli", + zksync: true, + }; + case "testnet": + return { url: "https://zksync2-testnet.zksync.dev", ethNetwork: "goerli", zksync: true, @@ -24,10 +29,16 @@ const zkSyncTestnet = verifyURL: "https://zksync2-testnet-explorer.zksync.dev/contract_verification", }; + default: + throw new Error(`Unsupported DEPLOY_ENV: ${env}`); + } +}; + +const networkConfig = getNetworkConfig(); const config: HardhatUserConfig = { zksolc: { - version: "latest", // can be defined like 1.3.x + version: "latest", settings: {}, }, defaultNetwork: "zkSyncTestnet", @@ -35,7 +46,7 @@ const config: HardhatUserConfig = { hardhat: { zksync: false, }, - zkSyncTestnet, + zkSyncTestnet: networkConfig, }, solidity: { version: "0.8.17", diff --git a/contracts/package.json b/contracts/package.json index ce1ca6f..63d47cf 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -25,7 +25,8 @@ "zksync-web3": "^0.14.3" }, "scripts": { - "test": "NODE_ENV=test hardhat test --network zkSyncTestnet", + "test": "NODE_ENV=local hardhat test --network zkSyncTestnet", + "ci:tests": "DEPLOY_ENV=ci hardhat test --network zkSyncTestnet --show-stack-traces", "deploy": "hardhat deploy-zksync", "greeter": "hardhat deploy-zksync --script greeter.ts", "gasless": "hardhat deploy-zksync --script gaslessPaymaster.ts", diff --git a/contracts/test/allowlist.test.ts b/contracts/test/allowlist.test.ts index 161146c..244022c 100644 --- a/contracts/test/allowlist.test.ts +++ b/contracts/test/allowlist.test.ts @@ -1,17 +1,19 @@ import { expect } from "chai"; import { Wallet, Provider, Contract, utils } from "zksync-web3"; -import * as hre from "hardhat"; +import hardhatConfig from "../hardhat.config"; import { Deployer } from "@matterlabs/hardhat-zksync-deploy"; import * as ethers from "ethers"; -import { deployContract, fundAccount } from "./utils"; +import { deployContract, fundAccount, setupDeployer } from "./utils"; // load env file import dotenv from "dotenv"; dotenv.config(); // load wallet private key from env file -const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || ""; +const PRIVATE_KEY = + process.env.WALLET_PRIVATE_KEY || + "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110"; describe("AllowlistPaymaster", function () { let provider: Provider; @@ -24,10 +26,9 @@ describe("AllowlistPaymaster", function () { let greeter: Contract; before(async function () { + const deployUrl = hardhatConfig.networks.zkSyncTestnet.url; // setup deployer - provider = Provider.getDefaultProvider(); - wallet = new Wallet(PRIVATE_KEY, provider); - deployer = new Deployer(hre, wallet); + [provider, wallet, deployer] = setupDeployer(deployUrl, PRIVATE_KEY); // setup new wallet emptyWallet = Wallet.createRandom(); console.log(`Empty wallet's address: ${emptyWallet.address}`); @@ -99,7 +100,6 @@ describe("AllowlistPaymaster", function () { expect(e.message).to.include("Ownable: caller is not the owner"); } }); - it("should prevent non-allowed user from calling Greeter", async function () { const notAllowedWallet = Wallet.createRandom().connect(provider); try { diff --git a/contracts/test/erc20fixed.test.ts b/contracts/test/erc20fixed.test.ts index f02a86e..72f819a 100644 --- a/contracts/test/erc20fixed.test.ts +++ b/contracts/test/erc20fixed.test.ts @@ -1,17 +1,19 @@ import { expect } from "chai"; import { Wallet, Provider, Contract, utils } from "zksync-web3"; -import * as hre from "hardhat"; +import hardhatConfig from "../hardhat.config"; import { Deployer } from "@matterlabs/hardhat-zksync-deploy"; import * as ethers from "ethers"; -import { deployContract, fundAccount } from "./utils"; +import { deployContract, fundAccount, setupDeployer } from "./utils"; // load env file import dotenv from "dotenv"; dotenv.config(); // load wallet private key from env file -const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || ""; +const PRIVATE_KEY = + process.env.WALLET_PRIVATE_KEY || + "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110"; describe("ERC20fixedPaymaster", function () { let provider: Provider; @@ -24,10 +26,9 @@ describe("ERC20fixedPaymaster", function () { let token: Contract; before(async function () { + const deployUrl = hardhatConfig.networks.zkSyncTestnet.url; // setup deployer - provider = Provider.getDefaultProvider(); - wallet = new Wallet(PRIVATE_KEY, provider); - deployer = new Deployer(hre, wallet); + [provider, wallet, deployer] = setupDeployer(deployUrl, PRIVATE_KEY); // setup new wallet const emptyWallet = Wallet.createRandom(); console.log(`Empty wallet's address: ${emptyWallet.address}`); diff --git a/contracts/test/erc721gated.test.ts b/contracts/test/erc721gated.test.ts index 87143af..8a5e6a6 100644 --- a/contracts/test/erc721gated.test.ts +++ b/contracts/test/erc721gated.test.ts @@ -1,17 +1,19 @@ import { expect } from "chai"; import { Wallet, Provider, Contract, utils } from "zksync-web3"; -import * as hre from "hardhat"; import { Deployer } from "@matterlabs/hardhat-zksync-deploy"; import * as ethers from "ethers"; +import hardhatConfig from "../hardhat.config"; -import { deployContract, fundAccount } from "./utils"; +import { deployContract, fundAccount, setupDeployer } from "./utils"; // load env file import dotenv from "dotenv"; dotenv.config(); // load wallet private key from env file -const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || ""; +const PRIVATE_KEY = + process.env.WALLET_PRIVATE_KEY || + "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110"; describe("ERC721gatedPaymaster", function () { let provider: Provider; @@ -25,11 +27,9 @@ describe("ERC721gatedPaymaster", function () { let erc721: Contract; before(async function () { + const deployUrl = hardhatConfig.networks.zkSyncTestnet.url; // setup deployer - provider = Provider.getDefaultProvider(); - wallet = new Wallet(PRIVATE_KEY, provider); - deployer = new Deployer(hre, wallet); - + [provider, wallet, deployer] = setupDeployer(deployUrl, PRIVATE_KEY); // setup new wallet userWallet = Wallet.createRandom(); userWallet = new Wallet(userWallet.privateKey, provider); diff --git a/contracts/test/gasless.test.ts b/contracts/test/gasless.test.ts index ba20697..38e6e10 100644 --- a/contracts/test/gasless.test.ts +++ b/contracts/test/gasless.test.ts @@ -1,17 +1,19 @@ import { expect } from "chai"; import { Wallet, Provider, Contract, utils } from "zksync-web3"; -import * as hre from "hardhat"; +import hardhatConfig from "../hardhat.config"; import { Deployer } from "@matterlabs/hardhat-zksync-deploy"; import * as ethers from "ethers"; -import { deployContract, fundAccount } from "./utils"; +import { deployContract, fundAccount, setupDeployer } from "./utils"; // load env file import dotenv from "dotenv"; dotenv.config(); // load wallet private key from env file -const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || ""; +const PRIVATE_KEY = + process.env.WALLET_PRIVATE_KEY || + "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110"; describe("GaslessPaymaster", function () { let provider: Provider; @@ -24,10 +26,9 @@ describe("GaslessPaymaster", function () { let greeter: Contract; before(async function () { + const deployUrl = hardhatConfig.networks.zkSyncTestnet.url; // setup deployer - provider = Provider.getDefaultProvider(); - wallet = new Wallet(PRIVATE_KEY, provider); - deployer = new Deployer(hre, wallet); + [provider, wallet, deployer] = setupDeployer(deployUrl, PRIVATE_KEY); // setup new wallet emptyWallet = Wallet.createRandom(); console.log(`Empty wallet's address: ${emptyWallet.address}`); diff --git a/contracts/test/utils.ts b/contracts/test/utils.ts index 2cd5ba5..0511320 100644 --- a/contracts/test/utils.ts +++ b/contracts/test/utils.ts @@ -1,5 +1,6 @@ -import { Contract, Wallet } from "zksync-web3"; +import { Contract, Wallet, Provider } from "zksync-web3"; import { Deployer } from "@matterlabs/hardhat-zksync-deploy"; +import * as hre from "hardhat"; import * as ethers from "ethers"; async function deployContract( @@ -28,4 +29,16 @@ async function fundAccount(wallet: Wallet, address: string, amount: string) { console.log(`Account ${address} funded with ${amount}`); } -export { deployContract, fundAccount }; +function setupDeployer( + url: string, + privateKey: string, +): [Provider, Wallet, Deployer] { + // setup deployer + const provider = new Provider(url); + const wallet = new Wallet(privateKey, provider); + const deployer = new Deployer(hre, wallet); + + return [provider, wallet, deployer]; +} + +export { deployContract, fundAccount, setupDeployer }; diff --git a/frontend/src/components/PaymasterMessage.js b/frontend/src/components/PaymasterMessage.js index 958770d..b1d08e0 100644 --- a/frontend/src/components/PaymasterMessage.js +++ b/frontend/src/components/PaymasterMessage.js @@ -13,21 +13,99 @@ const PaymasterMessage = ({ switch (selectedPaymaster) { case "Allowlist Paymaster 📜": - message = - <>
You've selected the Allowlist Paymaster. Let's see if you are on the list! 📜
The Allowlist Paymaster uses the general paymaster flow which should be used if no prior actions are required from the user for the paymaster to operate. For more information, proceed to our docs here.
>; + message = ( + <> + {" "} ++ You've selected the Allowlist Paymaster. Let's see if you are on the + list! 📜 +
{" "} ++ The Allowlist Paymaster uses the{" "} + general paymaster flow which + should be used if no prior actions are required from the user for + the paymaster to operate. For more information, proceed to our docs{" "} + + here. + +
+ > + ); break; case "Gasless Paymaster 🆓": - message = - <>You've selected the Gasless Paymaster. Things are going to be cheap for you!
The Gasless Paymaster uses the general paymaster flow which should be used if no prior actions are required from the user for the paymaster to operate. For more information, proceed to our docs here.
>; + message = ( + <> ++ You've selected the Gasless Paymaster. Things are going to be cheap + for you! +
{" "} ++ The Gasless Paymaster uses the{" "} + general paymaster flow which + should be used if no prior actions are required from the user for + the paymaster to operate. For more information, proceed to our docs{" "} + + here. + +
+ > + ); break; case "ERC20Fixed Paymaster 🎫": - message = - <>You've selected the ERC20Fixed Paymaster. You will need to input the token contract address that is required for the paymaster.
The ERC20Fixed Paymaster uses the approval-based paymaster flow which should be used if the user is required to set certain allowance to a token for the paymaster to operate. For more information, proceed to our docs here.
>; + message = ( + <> ++ You've selected the ERC20Fixed Paymaster. You will need to input the + token contract address that is required for the paymaster. +
{" "} ++ The ERC20Fixed Paymaster uses the{" "} + approval-based paymaster flow{" "} + which should be used if the user is required to set certain + allowance to a token for the paymaster to operate. For more + information, proceed to our docs{" "} + + here. + +
+ > + ); additionalInputNeeded = true; break; case "ERC721Gated Paymaster 🎨": - message = - <>You've selected the ERC721Gated Paymaster. You will need to input the NFT contract address that is gating the paymaster.
The ERC721Gated Paymaster uses the general paymaster flow which should be used if no prior actions are required from the user for the paymaster to operate. For more information, proceed to our docs here.
>; + message = ( + <> ++ You've selected the ERC721Gated Paymaster. You will need to input + the NFT contract address that is gating the paymaster. +
{" "} ++ The ERC721Gated Paymaster uses the{" "} + general paymaster flow which + should be used if no prior actions are required from the user for + the paymaster to operate. For more information, proceed to our docs{" "} + + here. + +
+ > + ); additionalInputNeeded = true; break; default: diff --git a/frontend/src/components/TxDetails.js b/frontend/src/components/TxDetails.js index a1c28c2..1d0ef93 100644 --- a/frontend/src/components/TxDetails.js +++ b/frontend/src/components/TxDetails.js @@ -15,9 +15,23 @@ const TxDetails = ({ txHash, signer, initialSignerBalance }) => { return (Transaction Hash: {txHash}
-Signer Initial Balance: {initialSignerBalance}
-Signer Balance After: {signerBalanceAfter}
++ Transaction Hash:{" "} + + {txHash} + +
++ Signer Initial Balance:{" "} + {initialSignerBalance}{" "} +
++ Signer Balance After:{" "} + {signerBalanceAfter} +