foundry
foundry copied to clipboard
Keystores exported from brownie could not be used
Component
Forge
Have you ensured that all of these are up to date?
- [X] Foundry
- [X] Foundryup
What version of Foundry are you on?
forge 0.2.0 (d4f626b 2023-08-09T00:21:28.739489228Z)
What command(s) is the bug in?
forge create; forge script
Operating System
Linux
Describe the bug
forge script as well as forge create doesn't seem to work with keystores exported/generated by brownie.
This is quite unfortunate, as there's no option to export a keystore using cast wallet and a custom private key, at least until https://github.com/foundry-rs/foundry/pull/5551 is implemented.
Generating a Brownie keystore
First, import any private key into Brownie and export a keystore. We'll be using a known private key for this.
$ brownie accounts new ones- Type this not very secure private key:
1111111111111111111111111111111111111111111111111111111111111111 - Type this not very secure password for encryption
ones. - You should see
SUCCESS: A new account '0x19E7E376E7C213B7E7e7e46cc70A5dD086DAff2A' has been generated with the id 'ones' $ brownie accounts export ones ./ones.jsonThis should get you the keystore with the "encrypted" "private" key.
Pasting the resulting ones.json as is
{"address": "19e7e376e7c213b7e7e7e46cc70a5dd086daff2a", "crypto": {"cipher": "aes-128-ctr", "cipherparams": {"iv": "e5b40cf278493c6f30bdf6f09c479665"}, "ciphertext": "1681df71af78f6b2a4b1f586af06572e7a45a8409284f1af225d53ccd0f9275c", "kdf": "scrypt", "kdfparams": {"dklen": 32, "n": 262144, "r": 1, "p": 8, "salt": "9f49ee3d090dd70f01de9562278b0971"}, "mac": "9e8eb87ebb16491a04f9aef9912c6145a024a22ea68ff7abdd92180a3e937ed2"}, "id": "3373aad8-f07c-48b5-b617-52d82f3154f5", "version": 3}
Deploying using brownie keystore
Now, try using this keystore. Obviously, don't send any funds to this address, we're only interested in whether the keystore could be decrypted.
Clone any Foundry-based repo. I usually use minimalistic Multicall3 repo: https://github.com/mds1/multicall/
Try deploying anything using this keystore:
forge create -r https://eth.llamarpc.com --keystore ones.json --password ones Multicall3
Error:
Failed to decrypt keystore "ones.json"
Context:
- scrypt InvalidParams
Deploying using cast wallet keystore
Compare this to using the keystore for a random address, generated by cast wallet new . This one is protected by not a secure password by any means ripped.
Pasting the resulting ripped.json as is
{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"163575c56116453d4a297d3c1565ff66"},"ciphertext":"f6fce3db1fdb3b7a5dfebb83f768b4feba31b1cbf2f1540109dc379493c6309b","kdf":"scrypt","kdfparams":{"dklen":32,"n":8192,"p":1,"r":8,"salt":"c6b1b9504ec0b070ac97d56802de529de028b7f6dea67bfcb99c6c237c821584"},"mac":"a2121b79cb5dc1df9b72da32df97f6f488a780850fe45ea2c51bddd2ab4f0cc9"},"id":"f63c2ab2-0a5c-4daa-806b-9ec2a2388420","version":3}
forge create -r https://eth.llamarpc.com --keystore ripped.json --password ripped Multicall3
In this case keystore is successfully decrypted:
Error:
(code: -32000, message: insufficient funds for gas * price + value: address 0xE65Bc689E5ef8205d710f7B5E2477Daa6F23c5E8 have 0 want 29039692383000000000, data: None)
Deploying using brownie keystore with address field removed
You may have noticed that brownie keystore json file has as extra address field, but the error remains even if you rip it out.
jq 'del(.address)' ones.json > onesCleared.json
Pasting the resulting onesCleared.json as is
{
"crypto": {
"cipher": "aes-128-ctr",
"cipherparams": {
"iv": "e5b40cf278493c6f30bdf6f09c479665"
},
"ciphertext": "1681df71af78f6b2a4b1f586af06572e7a45a8409284f1af225d53ccd0f9275c",
"kdf": "scrypt",
"kdfparams": {
"dklen": 32,
"n": 262144,
"r": 1,
"p": 8,
"salt": "9f49ee3d090dd70f01de9562278b0971"
},
"mac": "9e8eb87ebb16491a04f9aef9912c6145a024a22ea68ff7abdd92180a3e937ed2"
},
"id": "3373aad8-f07c-48b5-b617-52d82f3154f5",
"version": 3
}
forge create -r https://eth.llamarpc.com --keystore onesCleared.json --password ones Multicall3
The very same error happens
Error:
Failed to decrypt keystore "onesCleared.json"
Context:
- scrypt InvalidParams
@ChiTimesChi i face same problem. But I have more wide issue so could you please dm me in Telegram? https://t.me/msmobile
Same problem, moving from an old Brownie project onto Foundry.
hmm, this indeed fails because the settings violate a scrypt check:
https://github.com/RustCrypto/password-hashes/blob/b289d5a96192a2478dfe46c66bf964bf7d368eba/scrypt/src/params.rs#L67-L72
maybe exported blocksize (r) and parallelism factor (p) are switched, defaults are r=8,p=1
indeed, this does not happen with newer eth_account python library (tested with 0.13.14), but confirmed it does with the one used in brownie
>>> from eth_account import Account, messages
>>> import json
>>> encrypted = Account.encrypt(0x1111111111111111111111111111111111111111111111111111111111111111,'ones')
>>> json.dumps(encrypted)
'{"address": "19E7E376E7C213B7E7e7e46cc70A5dD086DAff2A", "crypto": {"cipher": "aes-128-ctr", "cipherparams": {"iv": "d7f6c757772d4c63cb38fff292126880"}, "ciphertext": "27874ebcb7e49fc9f914e5ae920b473ce00148ea2d6160786664719846c3965a", "kdf": "scrypt", "kdfparams": {"dklen": 32, "n": 262144, "r": 8, "p": 1, "salt": "b200fb63b1c4ae4c75208ce6801a8682"}, "mac": "9e2ed43d374c4dcf8699c757739812f49e046bec693b247b7198995ace8103f6"}, "id": "8259c483-eafa-48d9-95bb-e28af35db03d", "version": 3}'
the "r": 8, "p": 1 are properly generated and cast can decode
cast wallet address --keystore ones.json
Enter keystore password:
0x19E7E376E7C213B7E7e7e46cc70A5dD086DAff2A
Not much we could do here, we though have now the option to import from private key, so going to close the ticket. thank you