feat: cheatcode to get recent deployments by contract name
Component
Forge
Describe the feature you would like
Add new methods that parse JSON files in the broadcast folder to find contract addresses.
// Returns the most recent deployment for the given contract on `chainId`
function getDeployment(string memory contractName, uint256 chainId) external returns (address);
// Returns the deployment given by `index` for the given contract on `chainId`,
// where index=0 is the first (oldest) deploy, index=1 is the second deploy,
// and index=`type(uint256).max` is the most recent deploy
function getDeployment(string memory contractName, uint256 chainId, uint256 index) external returns (address);
// Returns all deployments for the given contract on `chainId`
function getDeployments(string memory contractName, uint256 chainId) external returns (address[] memory);
// Returns deployments by index for the given contract on `chainId`.
// If the start index is `type(uint256).max`, the end index counts
// backwards to return the most recent contracts. End index is exclusive,
// similar to how most slice methods behave
function getDeployments(string memory contractName, uint256 chainId, uint256 startIndex, uint256 endIndex) external returns (address[] memory);
cc @PatrickAlphaC @karmacoma-eth for thoughts on syntax/UX/cheat names/etc
Additional context
No response
Would be cool to also add something like hardhat-deploy where I can run:
anvil --deploy
and it runs through a deploy script when you start up anvil. Much easier than having to roll your own makefile for UI stuff
I'm not sure if we have an issue for this, but a related idea I've had was: when running a forge script, if the RPC URL is localhost, instead of treating cheatcode calls like normal (i.e. they won't work, since they're forge vm specific) automatically change them to be the special RPC calls to the anvil node
As mentioned in this twitter thread: https://twitter.com/jj_ranalli/status/1656384664020434949
It would be nice to be able to pull in known deployments, as contract instances, from dependencies so we can easily interact with them in scripts.
For example, assuming we have run forge install someproject/somecoin, we can then easily access the deployed "somecoin" on chain 1 with scripts in our own project as follows:
import "forge-std/Script.sol";
import {Deployments} from "somecoin/deployed/1/Deployments.sol";
contract MyScript is Script {
function run() public {
vm.startBroadcast(me);
Deployments.somecoin.transfer(to, 1 ether);
vm.stopBroadcast();
}
}
or maybe this is better?
import "forge-std/Script.sol";
import {Deployments} from "somecoin/deployed/1/Deployments.sol";
contract MyScript is Script, Deployments {
function run() public {
vm.startBroadcast(me);
somecoin.transfer(to, 1 ether);
vm.stopBroadcast();
}
}
My proposal would be that we add a new command e.g. forge bind-sol (and then maybe rename forge bind to forge bind-rs) or maybe a flag on forge script? Or a better name altogether? :D
Regardless, this command would create a file such as src/deployed/<chainId>/Deployments.sol based on the most recent broadcast run, exposing contract instances ready to be invoked by scripts.
Happy to hear thoughts on this as an alternative to this design, or as a separate feature completely (because I also like the general idea here from @mds1).
That's also a nice UX, I. like the idea. It does feel like being able to pull in deployments/ABIs from dependencies like that is very related to package management ideas that @fubuloubu and @brockelmore have discussed (which I'm not too familiar with, so I have no summary or other info to share)
Chiming in here to add some thoughts on @devanoneth suggestion, originally shared in the twitter post.
I think it would be desirable to have deployments auto-generation:
- opt-in (for example with a
forge scriptflag as suggested) - configurable on a folder/contract basis (to pick which contracts to store deployments for)
- so that scripts and tests can easily import them based on chain
- ideally even allow leaving a script unchanged regardless of chain used, by picking correct deployments based on
--chain-idand reverting if they don't exist.
- ideally even allow leaving a script unchanged regardless of chain used, by picking correct deployments based on
I also like @mds1 proposed feature btw. Would be nice to have both, as they can be useful in different circumstances.
I feel like #3911 is too big an issue to ever be completed. But adding at least the API suggested above would allow users or foundary to iterate on solutions, solutions that could therefor be used as a specification to finish #3911
AFAICT it would also need a vm.getChainId() or some other way to lookup the currect chainID for the current connected RPC - That way, a forge script could know everything it needed from its execution context and not need any other command line args or env vars passed in, than those which are needed for the deployment of a given contract.
If it still makes sense to introduce this change maybe I can take on a challenge. Seems like a useful util to improve scripts UX