Open chpiatt opened 3 years ago
Issue Status: 1. Open 2. Started 3. Submitted 4. Done
This issue now has a funding of 0.2 ETH (329.46 USD @ $1647.32/ETH) attached to it as part of the archerdao fund.
Stack trace for the error:
(node:72111) UnhandledPromiseRejectionWarning: HardhatError: HH103: Account 0x2d4bb9a783583875f8b0b86cbcad09ce87523497 is not managed by the node you are connected to.
at LocalAccountsProvider._getPrivateKeyForAddress (./node_modules/hardhat/internal/core/providers/accounts.js:104:19)
at LocalAccountsProvider.request (./node_modules/hardhat/internal/core/providers/accounts.js:83:37)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async EthersProviderWrapper.send (./node_modules/hardhat-deploy-ethers/dist/src/ethers-provider-wrapper.js:10:24)
Hi @chpiatt. I created a simple example where I fork the mainnet and start a node in one terminal, and then call the impersonate account method and send a transaction from another (connecting via the localhost
network) and it works fine. So your problem must be elsewhere.
If you create a minimal repo that reproduces the problem, I can take a deeper look.
I'm using hardhat-deploy and hardhat-deploy-ethers. My suspicion is something is going wrong there, but I will try to throw together a demo repo tomorrow
hi @chpiatt this worked for me https://github.com/andreiashu/archer-dao-hardhat/blob/main/test/archer-dao.test.js
There were some things I had to change. The original account provided (0x2d4bb9a783583875f8b0b86cbcad09ce87523497
) is not the admin one and setPendingProxyImplementation
was reverting with Prism::setPendingProxyImp: caller must be admin
. So I just used getStorageAt
to find the actual admin address.
Then I had to fund that admin account with some eth since it didn't have enough for gas costs. After that everything worked. See whether you spot any differences between our hardhat.config.js or the code I wrote.
Issue Status: 1. Open 2. Started 3. Submitted 4. Done
Work has been started.
These users each claimed they can complete the work by 4 weeks, 1 day ago. Please review their action plans below:
1) andreiashu has been approved to start work.
first time using gitcoin. seems I should have started here rather than posting straight on github. oh well :)
Learn more on the Gitcoin Issue Details page.
hi @chpiatt this worked for me https://github.com/andreiashu/archer-dao-hardhat/blob/main/test/archer-dao.test.js
There were some things I had to change. The original account provided (
0x2d4bb9a783583875f8b0b86cbcad09ce87523497
) is not the admin one andsetPendingProxyImplementation
was reverting withPrism::setPendingProxyImp: caller must be admin
. So I just usedgetStorageAt
to find the actual admin address.Then I had to fund that admin account with some eth since it didn't have enough for gas costs. After that everything worked. See whether you spot any differences between our hardhat.config.js or the code I wrote.
Thanks for putting this together. It was really helpful for isolating the issue. I forked your demo repo and added the code that is giving the issue here: https://github.com/chpiatt/archer-dao-hardhat
I figured out the issue happens only when I also pass in an array of accounts to the network config, see: https://github.com/chpiatt/archer-dao-hardhat/blob/1cce6268cf1ff8cf9de64296f8d56731b9476ab4/hardhat.config.js#L40
For now, I can get around this issue by just impersonating every account that I might want to pass as an account to this array, but leaving the bounty open in case someone can address the underlying issue of being able to both pass in accounts to this array and impersonate other accounts.
underlying issue of being able to both pass in accounts to this array and impersonate other accounts @chpiatt I believe It's not the accounts that's creating your issue.
in your config file for localhost
you have both url: 'http://localhost:8545',
and forking.url
specified.
please remove url
and leave the forking.url
and that should fix the issue. I've started getting strange errors when I specified both of them.
I've pushed and update that demos this working here https://github.com/andreiashu/archer-dao-hardhat/commit/d81f8cda8f266cb7f804b50f00124764d39b2b87 let me know what you think and if that solves the issue
ps: live
& saveDeployments
are not in the config docs?
Unfortunately, I don't think this solves the issue. In your update you moved the "accounts" array inside of the "forking" object, which I think is why the tests now pass: https://github.com/andreiashu/archer-dao-hardhat/blob/d81f8cda8f266cb7f804b50f00124764d39b2b87/hardhat.config.js#L27
At first, I thought maybe this actually was the solution, but then when I tried to sign a transaction with that account (without first impersonating it), I get a different error:
Error: no signer for 0x4F8f512Dab59F227EA70B1D8A0044aFa95CC80C3
Oh haha, oops. This is what happens if I try to rush it
On Sat, Feb 6, 2021, 20:26 Chris Piatt notifications@github.com wrote:
Unfortunately, I don't think this solves the issue. In your update you moved the "accounts" array inside of the "forking" object, which I think is why the tests now pass: https://github.com/andreiashu/archer-dao-hardhat/blob/d81f8cda8f266cb7f804b50f00124764d39b2b87/hardhat.config.js#L27
At first, I thought maybe this actually was the solution, but then when I tried to sign a transaction with that account (without first impersonating it), I get a different error:
Error: no signer for 0x4F8f512Dab59F227EA70B1D8A0044aFa95CC80C3
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/nomiclabs/hardhat/issues/1226#issuecomment-774477301, or unsubscribe https://github.com/notifications/unsubscribe-auth/AACTU3QGKKOWO2ORU53UDCLS5U7O3ANCNFSM4XEEFLLQ .
Hi @chpiatt, thanks for reporting this. And thanks @andreiashu for your effort investigating it, it helped me realize what's going on.
When you define a set of local accounts using an array of private keys or HD config, those accounts are used instead of the ones you are connecting to. This is conflating with the hardhat_impersonateAccount
, cause that affects the remote accounts, not the local ones.
I guess you could run a hardhat_imporsonateAccount
with the DEPLOYER_PRIVATE_KEY
's address as a workaround.
Hi @chpiatt, thanks for reporting this. And thanks @andreiashu for your effort investigating it, it helped me realize what's going on.
When you define a set of local accounts using an array of private keys or HD config, those accounts are used instead of the ones you are connecting to. This is conflating with the
hardhat_impersonateAccount
, cause that affects the remote accounts, not the local ones.I guess you could run a
hardhat_imporsonateAccount
with theDEPLOYER_PRIVATE_KEY
's address as a workaround.
I see the issue. Maybe there could be a method that you add to the client that when you call it: 1) keeps track of these accounts locally (i.e. in a map called impersonated_accounts) 2) forwards hardhat_impersonateAccount to the node?
And then when a signer tries to sign something you: 1) check if the private key is in your local accounts - if so, sign locally 2) if not, check if address is in impersonated_accounts - if so, forward to node to sign
@andreiashu Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!
Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days
Makes sense, @chpiatt. WDYT @fvictorio ?
@chpiatt, are you willing to fund this through gitcoin? We don't have a lot of bandwidth right now to prioritize implementing it internally.
@alcuadrado yes, happy to fund
Hello, I just hit this issue. I am using a mnemonic seed in my config. It all works correctly on the hardhat network. However I am running hardhat node externally so that I can work inside eth remix and use a local blockchain explorer.
I have the node on the hardhat network, and a copy as hardhat_external
which is used by hardhat test
(I use env vars to flag what to use).
Doing this causes the error reported above. I can confirm using ganache-cli
works expected so this seems to be an due to a possible assumption with the tight integration between the node, client, and test runner.
Until this is fixed, I would recommend to other developers to use hardhat node for debugging, and then use ganache once tests pass if you need to use a separate node process.
Hope this information helps :).
I was having the same issue on our project (which is why I found this issue). We were running from inside a Hardhat task and using the existing provider from Ethers as you are. We also tried running a Ganache (with the evm_unlockUnknownAccount
method instead) node instead, but we received the same error; the error was coming from the Hardhat task, not the node.
However, when we tried running it from a separate script using the following to instantiate a new provider, it worked.
const provider = new ethers.providers.JsonRpcProvider(
"http://localhost:8545"
);
await provider.send("hardhat_impersonateAccount", [ADDRESS]);
const account = provider.getSigner(ADDRESS);
So my guess is that the issue is with the EthersProviderWrapper
(which is the class name of ethers.provider
given by Hardhat)
Not sure if anyone is still having this issue; but you could try if using JsonRpcProvider
directly solves it.
I was having the same issue on our project (which is why I found this issue). We were running from inside a Hardhat task and using the existing provider from Ethers as you are. We also tried running a Ganache (with the
evm_unlockUnknownAccount
method instead) node instead, but we received the same error; the error was coming from the Hardhat task, not the node.However, when we tried running it from a separate script using the following to instantiate a new provider, it worked.
const provider = new ethers.providers.JsonRpcProvider( "http://localhost:8545" ); await provider.send("hardhat_impersonateAccount", [ADDRESS]); const account = provider.getSigner(ADDRESS);
So my guess is that the issue is with the
EthersProviderWrapper
(which is the class name ofethers.provider
given by Hardhat)Not sure if anyone is still having this issue; but you could try if using
JsonRpcProvider
directly solves it.
This actually works, even within a hardhat task. To generalize and make it backwards compatible I added this as the first line in my task function:
hre.ethers.provider = new ethers.providers.JsonRpcProvider(hre.ethers.provider.connection.url)
After that I stopped receiving the Error HH103: Account 0x29b7efda7c08773f9eadbc7443a23758e35eac2d is not managed by the node you are connected to.
error when trying to send a transaction from an impersonated account. I think the impersonation is succeeding but the EthersProviderWrapper
provided by the HRE somehow does an additional check it shouldn't do when sending transactions.
hre.ethers.provider = new ethers.providers.JsonRpcProvider(hre.ethers.provider.connection.url)
This won't work for other networks right now because that value is always (incorrectly) set to http://localhost:8545
.
I am still having an issue, getting an error:
HardhatError: HH103: Account 0x8894e0a0c962cb723c1976a4421c95949be2d4e3 is not managed by the node you are connected to.
When running hardhat node
externally. In hardhat.config.ts
I have:
const config: HardhatUserConfig = {
networks: {
hardhat: {
saveDeployments: true,
chainId: 56,
gasPrice: 20e9,
gas: 25e6,
allowUnlimitedContractSize: true,
accounts: { mnemonic },
forking: {
url: "https://speedy-nodes-nyc.moralis.io/2d2926c3e761369208fba31f/bsc/mainnet/archive",
blockNumber: 15641803
},
},
bscfork: {
accounts: { mnemonic },
chainId: 56,
gasPrice: 20e9,
gas: 7_000_000,
allowUnlimitedContractSize: true,
url: "http://localhost:8545",
},
...
I am running the impersonate script like:
import { providers } from "ethers";
import { ethers } from "hardhat";
const WHALE_ACCOUNTS = {
56: "0x8894E0a0c962CB723c1976a4421c95949bE2D4E3", // binance hot wallet 6
};
export const whaleSigner = async (): Promise<providers.JsonRpcSigner | undefined> => {
const { chainId } = await ethers.provider.getNetwork();
const account = WHALE_ACCOUNTS[chainId];
if (account) {
const provider = new providers.JsonRpcProvider("http://localhost:8545");
try {
await provider.send("hardhat_impersonateAccount", [account]);
} catch (e) {
console.log("Error in hardhat_impersonateAccount", e);
}
return provider.getSigner(account);
}
};
My tests run fine with npx hardhat test
. However when I run npx hardhat node
then I run npx hardhat test --network bscfork
I get the above error. Am I doing something wrong? It seems from above that this should work.
another way to make this work is to use getDefaultProvider
.
Step 1. Impersonate a whale's account on localhost
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: ["0x8894E0a0c962CB723c1976a4421c95949bE2D4E3"],
});
Step2. Get a provider to localhost where the whale has been impersonated
const provider = ethers.getDefaultProvider("http://localhost:8545");
Step3. Get whale's wallet & make transactions
const signer = await provider.getSigner(
"0x8894E0a0c962CB723c1976a4421c95949bE2D4E3"
);
await signer.sendTransaction({
to: "0x0000000000000000000000000000000000000000",
value: ethers.utils.parseEther("0.01"),
});
Summary of this thread so far.
This code works in the hardhat network (that is, running just hh run script.js
):
const helpers = require("@nomicfoundation/hardhat-network-helpers");
async function main() {
const randomAddress = "0x9998b9fa6836d840c901860512c2082f8d6eb536"
await helpers.setBalance(randomAddress, 10n**18n);
await helpers.impersonateAccount(randomAddress);
const s = await ethers.getSigner(randomAddress);
await s.sendTransaction({
to: s.address
});
}
main();
If you start an hh node
in another terminal and run hh run script.js --network localhost
, it will also work fine.
But if you configure the accounts array of the localhost
network:
networks: {
localhost: {
url: "http://localhost:8545",
accounts: []
}
},
and you run the script in the localhost network again, you'll get this error:
HardhatError: HH103: Account 0x9998b9fa6836d840c901860512c2082f8d6eb536 is not managed by the node you are connected to.
The error is thrown here if accounts
is not undefined:
The easiest solution is to just remove that check. I don't think this is a terrible idea if it fixes this problem. If the check is not there, and you send a transaction from a non-impersonated account that is not part of your local accounts, you get this error:
ProviderError: unknown account 0x9998b9fa6836d840c901860512c2082f8d6eb536
Which is not that bad, although it could be better.
The alternative solution is to modify the LocalAccountsProvider
middleware to intercept all hardhat_impersonateAccount
s calls, keep a list of all the impersonated accounts (removing them if someone uses hardhat_stopImpersonatingAccount
), and only forward the transactions from accounts that are not local but that are impersonated. This is what @chpiatt suggested here. Taking the complexity into account, I'm not sure if this is better than just removing the check.
Since this is caused by our provider, one workaround is to manually create a provider, as suggested by @Zequez here:
const provider = new ethers.providers.JsonRpcProvider(
"http://localhost:8545"
);
await provider.send("hardhat_impersonateAccount", [ADDRESS]);
const account = provider.getSigner(ADDRESS);
This assumes you are connecting to localhost. A slightly better option is:
let provider;
if (network.config.url !== undefined) {
provider = new ethers.providers.JsonRpcProvider(
network.config.url
);
} else {
// if network.config.url is undefined, then this is the hardhat network
provider = hre.ethers.provider;
}
await provider.send("hardhat_impersonateAccount", [ADDRESS]);
const account = provider.getSigner(ADDRESS);
I faced the same issue when forking and trying to take funds form a holder of USDC. Earlier in the thread I saw then this error occurs when specifying the list of accounts in the network. I have to specify a list of accounts in the network config because public accounts from hardhat may have some activities on the main net which could interrupt my testing. I got around this issue by specifying my accounts in the hardhat config in the network section and not in the network config. Impersonation seems to work correctly this way and I can also specify a list of accounts for my local network. Here's my hardhat.config.ts file:
defaultNetwork: "fork",
networks: {
hardhat: {
accounts: [
{
privateKey: `0x${PRIVATE_KEY1}`,
balance: "10000000000000000000000"
},
{
privateKey: `0x${PRIVATE_KEY2}`,
balance: "10000000000000000000000"
},
{
privateKey: `0x${PRIVATE_KEY3}`,
balance: "10000000000000000000000"
},
{
privateKey: `0x${PRIVATE_KEY4}`,
balance: "10000000000000000000000"
}
]
},
fork: {
url: "http://127.0.0.1:8545/",
// accounts: [`0x${PRIVATE_KEY1}`, `0x${PRIVATE_KEY2}`, `0x${PRIVATE_KEY3}`, `0x${PRIVATE_KEY4}`]
},
Hi, @chpiatt @rhlsthrm @Philogy
You can try this workaround.
// hardhat.config.ts
import { extendEnvironment } from "hardhat/config";
import { HardhatRuntimeEnvironment, HttpNetworkUserConfig } from "hardhat/types";
extendEnvironment((hre: HardhatRuntimeEnvironment) => {
const config = hre.network.config as HttpNetworkUserConfig;
if (config?.url) {
hre.ethers.provider = new hre.ethers.providers.JsonRpcProvider(config.url);
}
});
Now you can use ethers
everywhere in your project to impersonate an account.
import { ethers } from "hardhat";
// for easily way
const impersonatedSigner = await ethers.getImpersonatedSigner(address);
// and for a advance way
await ethers.provider.send("hardhat_impersonateAccount", [address]);
const impersonatedSigner = ethers.provider.getSigner(address);
You can try this workaround.
yes worked with ethers v5, I'm unable to find a way to instantiate a v6 compatible HardhatEthersProvider
forcing the url
for reference hardhat fork does work but I'm using buildbear, I'm able to make it work with ethers v5 and the suggested trick, I've not found so far a solution for updated v6
ok sort of found, you must set accounts to 'remote', something like
const config = hre.network.config as HttpNetworkUserConfig;
config.accounts = 'remote';
FWIW I had this problem and found that the issue was the presence of a mnemonic
key in the hardhat config for the network in question. It was fixed by removing the mnemonic, which I didn't need anyway since the code in question was only using impersonated accounts.
removing mnemonic caused an invalid type to be thrown for me @aspiers . i found that using the helpers import worked well
if you are using mnemonic, setup in hardhat network, not in localhost
Edit by @fvictorio: see this comment for a summary of this issue.
Original issue:
I'm running into an issue when I try impersonating an account on a forked mainnet running in separate terminal window (i.e. localhost network). I'm able to successfully impersonate this account when I just fork mainnet on the "hardhat" network to run tests, but on the "localhost" network I keep running into this issue:
Example code:
Configs: