Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Add multi-action send transaction method to bls signer #540

Merged
merged 12 commits into from
Mar 14, 2023

Conversation

JohnGuilding
Copy link
Collaborator

@JohnGuilding JohnGuilding commented Feb 21, 2023

What is this PR doing?

Adds multi-action transactions to bls provider and bls signer.

New methods were added as to not break the ethers provider base-class function signatures:

async sendTransactionBatch(transactionBatch: TransactionBatch): Promise<TransactionBatchResponse> {}

async constructTransactionBatchResponse(actions: Array<ActionData>, hash: string, from: string, nonce?: BigNumber): Promise<TransactionBatchResponse> {}

async signTransactionBatch(transactionBatch: TransactionBatch): Promise<string> {}

async sendTransactionBatch(signedTransactionBatch: string): Promise<TransactionBatchResponse> {}

multi-action standards

TLDR ended up going for the wallet_batchTransactions standard. It was the simplest option and we can easily build upon it as future requirements come up.
TLDR: Gut feeling is EIP 5792 is the option to go for. But after reading the discussion on eth magicians, it feels like there is some pushback which makes me think it won't get adopted in it's current state. e.g. disagreements about standardisation of bundle identifiers and disagreement about level of 'atomicity'.

New types:

export type TransactionBatch = {
  transactions: Array<Transaction>;
  batchOptions?: BatchOptions;
};

These were based on this draft batch transaction standard - wallet_batchTransactions JSON-RPC method. The idea was to ensure our code abides by a spec if one exists. There is no formal standard and it was a choice between the wallet_batchTransactions draft and EIP 5792 (draft). While the draft EIP is further along in it's journey towards becoming a standard (by this, I mean it's an actual draft EIP with discussion, as opposed to an informal draft), it's had some pushback in it's eth magicians thread. I've gone for the wallet_batchTransactions option for simplicity.

I've also created a new response type, this isn't based on any of the above standards, but it was easy to implement.

interface TransactionBatchResponse {
  transactions: Array<ethers.providers.TransactionResponse>;
  awaitBatchReceipt: (
    confirmations?: number,
  ) => Promise<ethers.providers.TransactionReceipt>;
}

Further notes and other changes

  1. Preliminary decision with signer.sendTransactionBatch was to only add transactions to a single operation. This means that all transactions in the batch will be atomic. Another option may be to give the developer a choice on whether to add transactions to different operations, and thus permit non-atomic transaction flows. Non-atomic tx flows are out of scope for this work.

  2. provider.sendTransactionBatch operates on an already signed bundle, so could theoretically receive multiple operations. I've added some code to support this in case of that scenario:

    const actionData: Array<ActionData> = bundle.operations
      .map((operation) => operation.actions)
      .flat();
  1. Abstracted common fee estimate code into helper functions:
    • Provider. _addFeePaymentActionForFeeEstimation
    • Provider. _addFeePaymentActionWithSafeFee
    • addSafetyDivisorToFee

How can these changes be manually tested?

  • run integration tests in workflow or locally

Does this PR resolve or contribute to any issues?

Resolves #375

Checklist

  • I have manually tested these changes
  • Post a link to the PR in the group chat

Guidelines

  • If your PR is not ready, mark it as a draft
  • The resolve conversation button is for reviewers, not authors
    • (But add a 'done' comment or similar)

@github-actions github-actions bot added clients contracts Smart contract related labels Feb 21, 2023
@JohnGuilding JohnGuilding force-pushed the 375-add-multi-action-transactions-to-bls-provider branch from 9bcab53 to 982b417 Compare February 23, 2023 14:40
*/
export type TransactionBatch = {
transactions: Array<Transaction>;
batchOptions?: BatchOptions;
Copy link
Collaborator Author

@JohnGuilding JohnGuilding Feb 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really utilising this optional property. Tbh slightly confused by what it's purpose is from the draft standard. My interpretation is that these values help smart contract wallets deal with figuring out batch transaction options from multiple transactions, but not sure if that's correct

Copy link
Collaborator

@jacque006 jacque006 Feb 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using this spec we need to accept them, but some of them we will be unable to pass forward to the agg. gas can be used with latest contract changes in contract-updates.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added a helper function (_validateBatchOptions) that validates the batch options if they are passed as an argument. It checks the chain id is correct and ensures the nonce is the correct type.

@JohnGuilding JohnGuilding marked this pull request as ready for review February 24, 2023 13:53
@JohnGuilding JohnGuilding marked this pull request as draft February 24, 2023 17:32
Copy link
Collaborator

@jacque006 jacque006 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, think this is a great start on batch txn handling for provider (nice tests btw). Also sets us up well to add additional batch specs. Let's sync offline on how to handle some of the batch options.

To start, I think we can assume that all actions (batched txns) are atomic. We can add more logic later to split actions across multiple operations later.

Comment on lines 30 to 40
export type Transaction = {
to?: string;
value?: BigNumberish;
gas?: BigNumberish;
maxPriorityFeePerGas?: BigNumberish;
maxFeePerGas?: BigNumberish;
data?: BytesLike;
nonce?: BigNumberish;
chainId?: number;
accessList?: Array<AccessListish>;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to import this from ethers.js

*/
export type TransactionBatch = {
transactions: Array<Transaction>;
batchOptions?: BatchOptions;
Copy link
Collaborator

@jacque006 jacque006 Feb 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using this spec we need to accept them, but some of them we will be unable to pass forward to the agg. gas can be used with latest contract changes in contract-updates.

Comment on lines 178 to 182
const actions: Array<ActionData> = transactionBatch.transactions.map(
(transaction) => {
if (!transaction.to) {
throw new TypeError(
"Transaction.to should be defined for all transactions",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const actions: Array<ActionData> = transactionBatch.transactions.map(
(transaction) => {
if (!transaction.to) {
throw new TypeError(
"Transaction.to should be defined for all transactions",
const actions: Array<ActionData> = transactionBatch.transactions.map(
(transaction, i) => {
if (!transaction.to) {
throw new TypeError(
`Transaction.to missing on txn {i}`,

Comment on lines 382 to 385
(transaction) => {
if (!transaction.to) {
throw new TypeError(
"Transaction.to should be defined for all transactions",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@github-actions github-actions bot added the automation CI/CD related label Mar 1, 2023
@JohnGuilding JohnGuilding force-pushed the 375-add-multi-action-transactions-to-bls-provider branch from 157790b to b257437 Compare March 1, 2023 17:02
@github-actions github-actions bot removed the automation CI/CD related label Mar 3, 2023
@JohnGuilding JohnGuilding force-pushed the 375-add-multi-action-transactions-to-bls-provider branch from 0f15fad to edd67d1 Compare March 3, 2023 11:27
// Assert
expect(result).to.deep.equal(batchOptions);
expect(result.nonce).to.equal(BigNumber.from("39"));
expect(result.nonce).to.have.property("add");
Copy link
Collaborator Author

@JohnGuilding JohnGuilding Mar 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expect(result.nonce).to.equal(BigNumber.from("39")); can result in false positives, so these 2 extra assertions test "BigNumber.from" worked.
(e.g. before these extra assertions, the test will still pass if "BigNumber.from" is removed in the method which is incorrect behaviour)

@@ -161,6 +161,9 @@ describe("Provider tests", function () {
.transfer(recipient, amountToTransfer);
await tx.wait();

// wait 1 second to ensure listener count updates
await new Promise((resolve) => setTimeout(resolve, 1000));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When running the whole test suite locally, the expect(blsProvider.listenerCount(filter)).to.equal(0); assertion would periodically fail as the event listener was still subscribed. Seems a bit hacky for testing a function that is supposed to be synchronous, but the timer appears to fix that issue.

@JohnGuilding JohnGuilding marked this pull request as ready for review March 3, 2023 11:38
@JohnGuilding JohnGuilding force-pushed the 375-add-multi-action-transactions-to-bls-provider branch from edd67d1 to ee17357 Compare March 14, 2023 14:08
Copy link
Collaborator

@jacque006 jacque006 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 We we decide to promote this for general usage, we should make sure to document the batch function & spec so people are aware they can use that in addition to the normal provider/signer APIs

@jacque006 jacque006 merged commit b203072 into main Mar 14, 2023
@jacque006 jacque006 deleted the 375-add-multi-action-transactions-to-bls-provider branch March 14, 2023 23:50
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
clients contracts Smart contract related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add multi-action transactions to BlsProvider & BlsSigner
2 participants