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

getAccountFromAddress not working if account not deployed

Open FabijanC opened this issue 2 years ago • 2 comments

When doing

starknet.OpenZeppelinAccount.getAccountFromAddress(address, privateKey);

the plugin performs an internal validation that the provided private key matches the deployed public key. Source code: OpenZeppelinAccount, ArgentAccount

Since starknet-hardhat-plugin v0.7.0, it is a problem if the account contract hasn't yet been deployed (so there is no public key deployed to check against). When can this happen? Assume the following use-case:

const account = await starknet.OpenZeppelinAccount.createAccount(...);
console.log("Account address:", account.address);
// you exit the script to fund the account

Then a new script is run which first tries to get the account:

const account = await starknet.OpenZeppelinAccount.getAccountFromAddress(...);
// FAILS with reporting an UNINITIALIZED_CONTRACT

Originally reported on Discord.

FabijanC avatar Dec 16 '22 11:12 FabijanC

Currently there are two approaches to solving this:

1. Creating and deploying in the same script

You need to wait between these two steps. This can be achieved in a few ways:

  1. sleep
  2. wait for keypress
const account = await starknet.OpenZeppelinAccount.createAccount(...);
await yourSelectedWayOfWaiting(); // fund during this step
await account.deployAccount(...);

2. Creating and deploying in separate executions

For this to work, you need to use the same private key and the same salt, e.g. via env vars (accessible with process.env).

First create the account to log the address:

const account = await starknet.OpenZeppelinAccount.createAccount({
  salt: process.env.SALT,
  privateKey: process.env.PRIVATE_KEY
});
console.log("Account address:", account.address);

If your script successfully exited, after funding the address you can recreate the same account again:

const account = await starknet.OpenZeppelinAccount.createAccount({
  // the same input data as in the last execution
});
await account.deployAccount(...);

FabijanC avatar Dec 16 '22 11:12 FabijanC

The question remains how we want to treat this long-term:

  1. Keep the above described method as the recommended way.
  2. Introduce an input parameter to getAccountFromAddress indicating whether the account being retrieved is deployed or not.
  3. Remove the private-public key validation completely.
  4. Introduce an input parameter to createAccount indicating whether to wait for funding or not (adding the keypress solution under the hood).

Personally, I'm leaning towards option 4.

FabijanC avatar Dec 16 '22 11:12 FabijanC