starknet-hardhat-plugin icon indicating copy to clipboard operation
starknet-hardhat-plugin copied to clipboard

Support custom Accounts

Open ivpavici opened this issue 3 years ago • 5 comments

Currently only OpenZeppelin and ArgentX are supported: as discussed here with Lauri: https://discord.com/channels/793094838509764618/961564209387282453 and here: https://discord.com/channels/793094838509764618/965952148418490418

ivpavici avatar Jul 08 '22 11:07 ivpavici

Relevant: https://github.com/PhilippeR26/Account-Abstraction-for-Starknet-Hardhat

FabijanC avatar Nov 11 '22 14:11 FabijanC

Maybe we can simply expose our existing Account abstract class (with potential modifications to make it more user-firendly). So far we didn't know how to expose classes in hre (so we did everything via functions, e.g. providing getContractFactory instead of exposing the StarknetContractFactory class with its constructor). It can probably be done as with Web3 in this example.

FabijanC avatar Nov 24 '22 15:11 FabijanC

So, this happens to work, some things could be improved from the UX side, but if you are in need, by extending the Account abstract class you can instantiate custom objects with deploy and invoke functionalities.

import { Account } from "@shardlabs/starknet-hardhat-plugin/dist/src/account";
import { TransactionHashPrefix, StarknetChainId } from "@shardlabs/starknet-hardhat-plugin/dist/src/constants";

class MyAccount extends Account {
    // alternatively replace the constructor with a static initialize method if you need async code
    public constructor(...) {
        super(...);
    }

    protected getMessageHash(
        transactionHashPrefix: TransactionHashPrefix,
        accountAddress: string,
        callArray: Call[],
        nonce: string,
        maxFee: string,
        version: string,
        chainId: StarknetChainId
    ): string {
        throw new Error("Method not implemented.");
    }
    protected getSignatures(messageHash: string): bigint[] {
        throw new Error("Method not implemented.");
    }
    deployAccount(options?: DeployAccountOptions | undefined): Promise<string> {
        throw new Error("Method not implemented.");
    }
}

Usage example:

const myAccount = new MyAccount(...);
// fund the account before deploying it
// ...
await myAccount.deployAccount();

// declare and deploy
const contractFactory = starknet.getContractFactory(...);
await myAccount.declare(contractFactory);
const contract = await myAccount.deploy(contractFactory);

await myAccount.invoke(contract, ...);

For more info see how OpenZeppelinAccount is implemented (link).

FabijanC avatar Dec 14 '22 12:12 FabijanC

As discussed with a user (Phil26 on Discord), the approach suggested in the previous post has bad UX.

Here is what exactly Phil said in the Discord thread:

Hello, I made some tests with this concept of support of account abstraction. It works, but to have all the inputs necessary to perform a new MyAccount() is too complicated ; the UX is really problematic. The best way is to have something similar to OZaccounts and ArgentXaccount : a protected constructor, and a static createAccount method. The dev has 2 steps : const myAccount=await MyAccount.createAccount(...), followed by myAccount.deployAccount(). I have also created 2 static methods, for standard signatures and hash : standardGetMessageHash() and standardGetSignatures(). By this way, a dev who is not working to customize these 2 points, has just to call these standard methods. They should be located in abstract Account class.

https://github.com/PhilippeR26/Account-Abstraction-for-Starknet-Hardhat/tree/main/scripts AAaccount.ts for the account definition testMyAA.ts for use example

FabijanC avatar Jan 18 '23 08:01 FabijanC

Can work on this one

irisdv avatar Jan 18 '23 11:01 irisdv