foundry icon indicating copy to clipboard operation
foundry copied to clipboard

feat: cheatcode to get recent deployments by contract name

Open mds1 opened this issue 2 years ago • 7 comments

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

mds1 avatar Apr 13 '23 13:04 mds1

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

PatrickAlphaC avatar Apr 13 '23 14:04 PatrickAlphaC

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

mds1 avatar Apr 13 '23 14:04 mds1

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).

devanoneth avatar May 11 '23 18:05 devanoneth

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)

mds1 avatar May 12 '23 17:05 mds1

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 script flag 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-id and reverting if they don't exist.

I also like @mds1 proposed feature btw. Would be nice to have both, as they can be useful in different circumstances.

jjranalli avatar May 12 '23 19:05 jjranalli

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.

nzjrs avatar Oct 29 '23 15:10 nzjrs

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

drinkius avatar Jul 18 '24 07:07 drinkius