Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli,world): add user defined salt in WorldFactory.deployWorld() #2219

Merged
merged 23 commits into from
Feb 6, 2024

Conversation

partylikeits1983
Copy link
Contributor

@partylikeits1983 partylikeits1983 commented Jan 31, 2024

This PR adds user-defined salt functionality to the WorldFactory.deployWorld() function.

Resolves #2214

The modified WorldFactory.deployWorld() function allows the world creator to pass in an arbitrary salt value. This makes it easier for developers to have deterministic addresses across chains.

The edited function still increments worldCounts when creating a new world, but the worldCount nonce is not used to create a unique salt.

The salt value still uses msg.sender as a parameter to generate a salt. If msg.sender calls deployWorld() a second time with the same bytes _salt value, the transaction will revert.

function deployWorld(bytes memory _salt) public returns (address worldAddress) {
    // Deploy a new World and increase the WorldCount
    bytes memory bytecode = type(World).creationCode;
    uint256 salt = uint256(keccak256(abi.encode(msg.sender, _salt)));
    worldCounts[msg.sender]++;
    
    worldAddress = Create2.deploy(bytecode, salt);
    IBaseWorld world = IBaseWorld(worldAddress);

    // Initialize the World and transfer ownership to the caller
    world.initialize(coreModule);
    world.transferOwnership(ROOT_NAMESPACE_ID, msg.sender);

    emit WorldDeployed(worldAddress);
}

This PR also updates the Factories.t.sol test.

In the test, the calculated address matches the deployed address via Create2.

Additionally the test expects revert when attempting to deploy a second world with the same _salt value.

Please let me know if I need to edit the PR.

Copy link

changeset-bot bot commented Jan 31, 2024

🦋 Changeset detected

Latest commit: c98bd03

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 30 packages
Name Type
@latticexyz/cli Major
@latticexyz/world Major
@latticexyz/dev-tools Major
@latticexyz/store-sync Major
@latticexyz/world-modules Major
@latticexyz/store-indexer Major
@latticexyz/abi-ts Major
@latticexyz/block-logs-stream Major
@latticexyz/common Major
@latticexyz/config Major
create-mud Major
@latticexyz/ecs-browser Major
@latticexyz/faucet Major
@latticexyz/gas-report Major
@latticexyz/network Major
@latticexyz/noise Major
@latticexyz/phaserx Major
@latticexyz/protocol-parser Major
@latticexyz/react Major
@latticexyz/recs Major
@latticexyz/schema-type Major
@latticexyz/services Major
@latticexyz/solecs Major
solhint-config-mud Major
solhint-plugin-mud Major
@latticexyz/std-client Major
@latticexyz/std-contracts Major
@latticexyz/store-cache Major
@latticexyz/store Major
@latticexyz/utils Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

@yonadaa yonadaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Just a couple comments.

packages/world/src/WorldFactory.sol Outdated Show resolved Hide resolved
packages/world/test/Factories.t.sol Outdated Show resolved Hide resolved
testWorldFactory(address(this), 0);
}

function testFuzzWorldDeploy(address account, uint _salt) public {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added fuzzing test for salt.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You actually don't need a separate testFuzzWorldDeploy test, Foundry will automatically run testWorldFactory as a property-based test because it has parameters.

So we only need testWorldFactory(address account, uint256 salt) and testWorldFactoryGas()

image

// Address we expect for World
// unchecked for the fuzzing test
bytes memory _salt1;
unchecked {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added unchecked here so that the test doesn't revert on overflow/underflow during the fuzzing test.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the overall intention here just to generate two different salts?

A more clear way to do this would be to have two salt parameters in the fuzz test, and discard them if the fuzzer generates two that are equal. You can do this with a Foundry assume at the start of the test:

function testWorldFactory(address account, uint256 salt1, uint256 salt2) public {
  vm.assume(salt1 != salt2);
  ...
)

Copy link
Contributor Author

@partylikeits1983 partylikeits1983 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved issues brought up in review.

Copy link
Contributor

@yonadaa yonadaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there, just remove worldCounts and a couple nits 🙌

testWorldFactory(address(this), 0);
}

function testFuzzWorldDeploy(address account, uint _salt) public {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You actually don't need a separate testFuzzWorldDeploy test, Foundry will automatically run testWorldFactory as a property-based test because it has parameters.

So we only need testWorldFactory(address account, uint256 salt) and testWorldFactoryGas()

image

packages/world/test/Factories.t.sol Outdated Show resolved Hide resolved
packages/world/src/WorldFactory.sol Outdated Show resolved Hide resolved
// Address we expect for World
// unchecked for the fuzzing test
bytes memory _salt1;
unchecked {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the overall intention here just to generate two different salts?

A more clear way to do this would be to have two salt parameters in the fuzz test, and discard them if the fuzzer generates two that are equal. You can do this with a Foundry assume at the start of the test:

function testWorldFactory(address account, uint256 salt1, uint256 salt2) public {
  vm.assume(salt1 != salt2);
  ...
)

@partylikeits1983
Copy link
Contributor Author

partylikeits1983 commented Feb 2, 2024

Removed worldCounts from WorldFactory and simplified the testWorldFactory test.

* @return worldAddress The address of the newly deployed World contract.
*/
function deployWorld() public returns (address worldAddress) {
function deployWorld(bytes memory _salt) public returns (address worldAddress) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small API thing: because Solidity supports calling functions with named parameters now, it might make sense to call this salt and internally we can call the combined one _salt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

@yonadaa
Copy link
Contributor

yonadaa commented Feb 2, 2024

@partylikeits1983 are you good to fix the last suggestion (and get CI to pass)? Otherwise I'm happy to get this over the finish line, but you'll need to enable commits on your branches so I can push to your fork:
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork

@partylikeits1983
Copy link
Contributor Author

@holic @yonadaaa lmk if there is anything else to fix on this PR. All tests passed on this branch locally.

@partylikeits1983
Copy link
Contributor Author

@partylikeits1983 are you good to fix the last suggestion (and get CI to pass)? Otherwise I'm happy to get this over the finish line, but you'll need to enable commits on your branches so I can push to your fork: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork

Screenshot 2024-02-02 at 9 31 27 PM

Edits by maintainers are turned on for this branch.

Is there something specific for repositories with GitHub actions that have secrets?

@yonadaa
Copy link
Contributor

yonadaa commented Feb 5, 2024

Edits by maintainers are turned on for this branch.

@partylikeits1983 thanks for pointing that out, seems my gh CLI was misconfigured but I was able to push by cloning your repo instead.

This PR is almost done - I will take this over and get it over the finish line!

@yonadaa yonadaa requested a review from holic February 5, 2024 17:55
Copy link
Contributor

@yonadaa yonadaa Feb 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alvrs @holic should/do we test CLI commands?

For example, we have contract tests for this salt but that doesn't tell us if the CLI option actually works.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we sort of do in that our e2e tests lean on deploying a world with the mud cli (I think)

@partylikeits1983
Copy link
Contributor Author

Edits by maintainers are turned on for this branch.

@partylikeits1983 thanks for pointing that out, seems my gh CLI was misconfigured but I was able to push by cloning your repo instead.

This PR is almost done - I will take this over and get it over the finish line!

Lmk if there is anything else I should fix.

@holic holic changed the title feat: add user defined salt in WorldFactory.deployWorld() feat(cli,world): add user defined salt in WorldFactory.deployWorld() Feb 6, 2024
@@ -58,7 +61,7 @@ export async function deploy<configInput extends ConfigInput>({

const worldDeploy = existingWorldAddress
? await getWorldDeploy(client, existingWorldAddress)
: await deployWorld(client);
: await deployWorld(client, salt ? salt : `0x${randomBytes(32).toString("hex")}`);
Copy link
Member

@holic holic Feb 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we might want to check isHex here (edit: need to check where this is called, not here)

@@ -89,6 +89,7 @@ const commandModule: CommandModule<typeof devOptions, InferredOptionTypes<typeof
saveDeployment: true,
worldAddress,
srcDir,
salt: undefined,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be nice to do our own internally incrementing counter for this process here, so that restarting the dev process always results in the same contract address.

Copy link
Member

@holic holic Feb 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, this might be harder than I initially thought it would be. Since we already pass the worldAddress in to upgrade worlds, this should be fine.

Just a note that this means that our tests that generate data, snapshots, etc. will be non-deterministic for now (unless we update them to pass in a consistent salt)

@holic holic merged commit 618dd0e into latticexyz:main Feb 6, 2024
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

WorldFactory: allow creator to pass in salt
3 participants