Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sma 46 multichain validation module #257

Merged

Conversation

livingrockrises
Copy link
Contributor

@livingrockrises livingrockrises commented Aug 20, 2023

Description

Multichain validation module implementation for multi chain userops signing.
Actual test script would be part of test cases soon - and also in backend scripts modulat-SA-v2 playground.

can change the base later if other PRs are merged first.

EDIT: This is done

I am trying to send one tx on bnb + polygon testnets soon using this module.
later we can send the ops which actually makes uses of enabled session.

Fixes # (issue)

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

I have tested from backend-node scripts in sdk-examples repo here

let provider = new ethers.providers.JsonRpcProvider(config.rpcUrl);
  let signer = new ethers.Wallet(config.privateKey, provider);
  const eoa = await signer.getAddress();
  console.log(chalk.blue(`EOA address: ${eoa}`));

  // create bundler and paymaster instances
  const bundler1 = new Bundler({
    bundlerUrl: config.bundlerUrl,
    chainId: config.chainId,
    entryPointAddress: DEFAULT_ENTRYPOINT_ADDRESS,
  });

  const paymaster = new BiconomyPaymaster({
    paymasterUrl: config.biconomyPaymasterUrl
  });

  const multiChainModule = new MultiChainValidationModule({
    signer: signer,
    chainId: config.chainId, // to be removed
    moduleAddress: '0x2E817fe3749B81dA801fc08B247E081ec20eB080'
  })
  
  const biconomySmartAccountConfig1 = {
    signer: signer,
    chainId: config.chainId,
    rpcUrl: config.rpcUrl,
    paymaster: paymaster, 
    bundler: bundler1, 
    entryPointAddress: DEFAULT_ENTRYPOINT_ADDRESS,
    defaultValidationModule: multiChainModule,
    activeValidationModule: multiChainModule
  };

  // create biconomy smart account instance
  const biconomyAccount1 = new BiconomySmartAccountV2(biconomySmartAccountConfig1);

  // passing accountIndex is optional, by default it will be 0. You may use different indexes for generating multiple counterfactual smart accounts for the same user
  const biconomySmartAccount1 = await biconomyAccount1.init();


// For another chain instance

const bundler2 = new Bundler({
    bundlerUrl: "https://bundler.biconomy.io/api/v2/97/A5CBjLqSc.0dcbc53e-anPe-44c7-b22d-21071345f76a",
    chainId: 97,
    entryPointAddress: DEFAULT_ENTRYPOINT_ADDRESS,
  });

  const biconomySmartAccountConfig2 = {
    signer: signer,
    chainId: 97,
    rpcUrl: 'https://data-seed-prebsc-1-s2.binance.org:8545',
    // paymaster: paymaster, 
    bundler: bundler2, 
    entryPointAddress: DEFAULT_ENTRYPOINT_ADDRESS,
    defaultValidationModule: multiChainModule,
    activeValidationModule: multiChainModule
  };


  // create biconomy smart account instance
  const biconomyAccount2 = new BiconomySmartAccountV2(biconomySmartAccountConfig2);

  // passing accountIndex is optional, by default it will be 0. You may use different indexes for generating multiple counterfactual smart accounts for the same user
  const biconomySmartAccount2 = await biconomyAccount2.init();
  
  // Building user ops
  
  // any transaction object (say mintNFT)
  // or maybe enableModule (session key manager address)
  // or maybe enableModule and createSession batch 
  // createSession() tx data
  
  let partialUserOp1 = await biconomySmartAccount1.buildUserOp([transaction1]);
  
  let partialUserOp2 = await biconomySmartAccount2.buildUserOp([transaction2]);
  
  const returnedOps = await multiChainModule.signUserOps([{userOp: partialUserOp1, chainId: 80001}, {userOp: partialUserOp2, chainId: 97}]);
  
  // Sending individual ops with common multichain sig
  
  // Mumbai
  
  const userOpResponse1 = await biconomySmartAccount1.sendSignedUserOp(returnedOps[0] as any);
  console.log(chalk.green(`userOp Hash: ${userOpResponse1.userOpHash}`));
  const transactionDetails1 = await userOpResponse1.wait();
  
  
  // BNB testnet
  
  const userOpResponse2 = await biconomySmartAccount2.sendSignedUserOp(returnedOps[1] as any);
  console.log(chalk.green(`userOp Hash: ${userOpResponse2.userOpHash}`));
  const transactionDetails2 = await userOpResponse2.wait();
  

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@linear
Copy link

linear bot commented Aug 20, 2023

Comment on lines 32 to 34
// TODO: Actually depends on the module address so maybe we can make it dynamic
getDummySignature(): string {
return '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000002E817fe3749B81dA801fc08B247E081ec20eB080000000000000000000000000000000000000000000000000000000000000004181d4b4981670cb18f99f0b4a66446df1bf5b204d24cfcb659bf38ba27a4359b5711649ec2423c5e1247245eba2964679b6a1dbb85c992ae40b9b00c6935b02ff1b00000000000000000000000000000000000000000000000000000000000000'
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this needed, what needs to be updated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

smartAccount.buildUserOp() makes a call to the bundler where need to provide one dummySignature for one of the enabled modules. so each module is supposed to provide dummy mock sig.

but I think as MultiChain is extension of ECDSA and can verifying ECDSA sigs as well the default ECDSA module sig also works on bundler side, when I was just calling sa.buildUserOp()

and the TODO note is specific to making above sig dynamic so that module address becomes a param. I will push this change now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

ModuleVersion,
MultiChainUserOpDto
} from './utils/Types'
export class MultiChainValidationModule extends ECDSAOwnershipValidationModule {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@AmanRaj1608 @tomarsachin2271 since it extends the ECDSAModule chainId becomes mandatory but in real sense this module itself doesn't need to maintain chainId as it will receive it as part of dto (array of objects - userop + chainId) in singUserOps method.
what should I do?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can remove the extend part as the MultiChainValidationModule is different module and not really depends on ECDSAOwnershipValidationModule

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok let me do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@livingrockrises
Copy link
Contributor Author

also updated sample client side code.

Comment on lines 46 to 49
// TODO
const validUntil = 0 // unlimited
const validAfter = 0

Copy link
Contributor

Choose a reason for hiding this comment

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

these should be taken by the user as param

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Contributor

@AmanRaj1608 AmanRaj1608 left a comment

Choose a reason for hiding this comment

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

Can refactor the commented codes and merge

@livingrockrises livingrockrises merged commit d38c207 into SMA-58-BSA-V2-class Aug 22, 2023
@AmanRaj1608 AmanRaj1608 deleted the SMA-46-Multichain-Validation-Module branch September 29, 2023 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants