diff --git a/contracts/README.md b/contracts/README.md index 9da63e51..967a1503 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -116,7 +116,7 @@ For each network, the deployer contract can be deployed with the following scrip To run integration tests: -1. cd into `./contracts` and run `yarn start-hardhat` +1. cd into `./contracts` and run `yarn start` 2. cd into `./aggregator` and run `./programs/aggregator.ts` 3. from `./contracts`, run `yarn test-integration`. diff --git a/contracts/clients/test/BlsSigner.test.ts b/contracts/clients/test/BlsSigner.test.ts index 6c2cf63a..b8488c36 100644 --- a/contracts/clients/test/BlsSigner.test.ts +++ b/contracts/clients/test/BlsSigner.test.ts @@ -22,7 +22,7 @@ describe("BlsSigner", () => { rpcUrl = "http://localhost:8545"; network = { name: "localhost", - chainId: 0x7a69, + chainId: 0x539, }; privateKey = await BlsSigner.getRandomBlsPrivateKey(); diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 6ab58965..8abda34c 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -131,6 +131,7 @@ const config: HardhatUserConfig = { }, networks: { hardhat: { + chainId: 1337, initialBaseFeePerGas: 0, // workaround from https://github.com/sc-forks/solidity-coverage/issues/652#issuecomment-896330136 . Remove when that issue is closed. accounts, blockGasLimit: 30_000_000, diff --git a/docs/local_development.md b/docs/local_development.md index c5ef470f..a4f2a9c4 100644 --- a/docs/local_development.md +++ b/docs/local_development.md @@ -100,6 +100,7 @@ yarn run dev:chrome # or dev:firefox, dev:opera - pull latest from `main` and run the setup script from the root directory `./setup.ts`. - Restart the node and redeploy contracts +- Delete `aggregator.sqlite` in `./aggregator`. This is the local DB which will get regenerated when the aggregator is started. - Restart the aggregator and add the "-r" flag to the command e.g `./programs/aggregator.ts -r`. - Reset the Quill extension in your browser if you're developing with Quill. You can do this by removing the extension and then re-adding via "Load unpacked" again. Or run `debug.reset();` twice in the background page console. @@ -107,6 +108,9 @@ yarn run dev:chrome # or dev:firefox, dev:opera - In general, the bundle or submission issues we've encountered have been us misconfiguring the data in the bundle or not configuring the aggregator properly. - Be careful using Hardhat accounts 0 and 1 in your code when running a local aggregator. This is because the local aggregator config uses the same key pairs as Hardhat accounts 0 and 1 by default. You can get around this by not using accounts 0 and 1 elsewhere, or changing the default accounts that the aggregator uses locally. +- When packages are updated in the aggregator, you'll need to reload the deno cache as the setup script won't do this for you. You can do this with `deno cache -r deps.ts` in the `./aggregator` directory. +- If running Quill against a local node, and if you're using MetaMask to fund Quill, make sure the MetaMask +localhost network uses chainId `1337`. ### Tests diff --git a/extension/README.md b/extension/README.md index 78714442..6cc3147d 100644 --- a/extension/README.md +++ b/extension/README.md @@ -17,6 +17,19 @@ Interaction with web3 applications can be slow, costly, and risky. 3. transfer L2 erc20 tokens 4. use contract wallet with L2 dapps (coming soon) +## Getting started + +To run the dev server: + +```sh +yarn run dev:chrome # or dev:firefox etc, see scripts in package.json +``` + +Reset the extension. This is useful for getting the wallet to a clean slate in development. You can achieve this in your browser by either: + +- Removing the extension and then re-adding via "Load unpacked". +- Or run `debug.reset();` twice in the background page console. + ## Feature Summary ### MVP (uses Optimism) @@ -89,10 +102,3 @@ Interaction with web3 applications can be slow, costly, and risky. - method name - nonce - (send) - (aggregate) - (send all) -## Development - -To run the dev server: - -```sh -yarn run dev:chrome # or dev:firefox etc, see scripts in package.json -``` diff --git a/extension/config.example.json b/extension/config.example.json index e77a952c..4829790e 100644 --- a/extension/config.example.json +++ b/extension/config.example.json @@ -15,7 +15,7 @@ }, "local": { "blockExplorerUrl": "N/A", - "chainId": "0x7a69", + "chainId": "0x539", "displayName": "Local Network", "logo": "", "rpcTarget": "http://127.0.0.1:8545", diff --git a/extension/config.release.json b/extension/config.release.json index 36f593b0..f5ba248d 100644 --- a/extension/config.release.json +++ b/extension/config.release.json @@ -15,7 +15,7 @@ }, "local": { "blockExplorerUrl": "N/A", - "chainId": "0x7a69", + "chainId": "0x539", "displayName": "Local Network", "logo": "", "rpcTarget": "http://127.0.0.1:8545", diff --git a/extension/source/background/AggregatorController.ts b/extension/source/background/AggregatorController.ts index 0c71caa3..b106fecc 100644 --- a/extension/source/background/AggregatorController.ts +++ b/extension/source/background/AggregatorController.ts @@ -1,5 +1,10 @@ -import { Aggregator, BlsWalletWrapper } from 'bls-wallet-clients'; -import { ethers } from 'ethers'; +import { + Aggregator, + BlsWalletWrapper, + AggregatorUtilities__factory as AggregatorUtilitiesFactory, + ActionData, +} from 'bls-wallet-clients'; +import { BigNumber, ethers } from 'ethers'; import assert from '../helpers/assert'; import ensureType from '../helpers/ensureType'; @@ -71,12 +76,24 @@ export default class AggregatorController { ); const nonce = (await wallet.Nonce()).toString(); - const bundle = await wallet.sign({ nonce, actions }); const aggregatorUrl = this.preferredAggregators[providerId] ?? network.aggregatorUrl; const agg = new Aggregator(aggregatorUrl); + + const actionsWithFeePaymentAction = await this.addFeePaymentAction( + nonce, + actions, + wallet, + agg, + ); + + const bundle = wallet.sign({ + nonce, + actions: actionsWithFeePaymentAction, + }); + const result = await agg.add(bundle); assert(!('failures' in result), () => new Error(JSON.stringify(result))); @@ -158,4 +175,55 @@ export default class AggregatorController { this.preferredAggregators[providerId] = preferredAggregator; }, }); + + async addFeePaymentAction( + nonce: string, + actions: Array, + wallet: BlsWalletWrapper, + aggregator: Aggregator, + ) { + const network = await this.networkController.network.read(); + const netCfg = getNetworkConfig(network, this.multiNetworkConfig); + const ethersProvider = await this.ethersProvider.read(); + + const aggregatorUtilitiesAddress = netCfg.addresses.utilities; + const aggregatorUtilitiesContract = AggregatorUtilitiesFactory.connect( + aggregatorUtilitiesAddress, + ethersProvider, + ); + + const actionsWithFeePaymentAction = [ + ...actions, + { + ethValue: 1, + contractAddress: aggregatorUtilitiesAddress, + encodedFunction: + aggregatorUtilitiesContract.interface.encodeFunctionData( + 'sendEthToTxOrigin', + ), + }, + ]; + + const feeEstimateBundle = wallet.sign({ + nonce, + actions: [...actionsWithFeePaymentAction], + }); + + const feeEstimate = await aggregator.estimateFee(feeEstimateBundle); + const feeRequired = BigNumber.from(feeEstimate.feeRequired); + const safetyPremium = feeRequired.div(5); + const safeFee = feeRequired.add(safetyPremium); + + return [ + ...actions, + { + ethValue: safeFee, + contractAddress: aggregatorUtilitiesAddress, + encodedFunction: + aggregatorUtilitiesContract.interface.encodeFunctionData( + 'sendEthToTxOrigin', + ), + }, + ]; + } }