Skip to content

Commit

Permalink
feat(pg): Register projects via the website
Browse files Browse the repository at this point in the history
  • Loading branch information
RPate97 committed May 7, 2024
1 parent 6d6c1fa commit a978b3b
Show file tree
Hide file tree
Showing 54 changed files with 775 additions and 634 deletions.
8 changes: 8 additions & 0 deletions .changeset/short-cycles-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@sphinx-labs/contracts': minor
'@sphinx-labs/plugins': minor
'@sphinx-labs/core': minor
'@sphinx-labs/demo': minor
---

Move project registration onto website
57 changes: 57 additions & 0 deletions docs/breaking/registration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Project Registration Update
Sphinx is updating the way that you register projects. Instead of specifying your Gnosis Safe owners, threshold and salt nonce in your Solidity scripts, you will now register your projects via the Sphinx UI. In your script, you will simply specify the name of your project.

This change is intended to improve the UX of using Sphinx and to open the door for us to implement other feature requests such as sharing Gnosis Safes between Sphinx projects and importing Gnosis Safes that were deployed using alternative interfaces (such as the Gnosis Safe UI) into Sphinx.

## Update Guide
These steps will walk you through the process of getting upgraded to the new version. It should only take a few minutes for you to complete.

### 1. Update your Sphinx Plugin and Sphinx Solidity Library

Update the Sphinx plugin version by bumping the version in your `package.json` file to the latest version `0.32.0`.

Then update the Sphinx Solidity library by running `sphinx install`:
```
npx sphinx install
```

### 2. Fetch your `sphinx.lock` file and commit it to version control
Sphinx now stores information about your projects in a `sphinx.lock` file. This is an autogenerated file. You should not modify it manually. To generate this file for the first time run:
```
npx sphinx sync --org-id <ORG_ID>
```

Whenever you register a new project with Sphinx, you'll want to update your `sphinx.lock` file by running the following command:
```
npx sphinx sync
```

Commit the file to version control:
```
git add sphinx.lock
git commit -m "maint: Creating Sphinx lock file"
```

### 4. Remove legacy configuration options
Sphinx now only requires that you specify the `sphinxConfig.projectName` field in your script. You will need to remove the following configuration options from your deployment scripts:
- `sphinxConfig.orgId`
- `sphinxConfig.owners`
- `sphinxConfig.threshold`
- `sphinxConfig.saltNonce`

If you are using the `sphinxConfig.mainnets` or `sphinxConfig.testnets` options, you can leave both of them as they are.

### 5. Allow read access to the sphinx.lock file
Add the following option to the `fs_permissions` field in your foundry.toml file:
`{access="read", path="./sphinx.lock"}`

After you are done, it should look something like this:
```
fs_permissions=[{access="read", path="./out"}, {access="read-write", path="./cache"}, {access="read", path="./sphinx.lock"}]
```

### 6. Try proposing with your updated script
```
npx sphinx propose ./path/to/Script.s.sol --networks sepolia --dry-run
```

62 changes: 32 additions & 30 deletions docs/cli-existing-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ In this guide, you'll propose the deployment on the command line and then approv
4. [Install Sphinx Foundry library](#4-install-sphinx-foundry-library)
5. [Update `.gitignore`](#5-update-gitignore)
6. [Add remapping](#6-add-remapping)
7. [Update your deployment script](#7-update-your-deployment-script)\
7. [Create a new Sphinx project](#7-create-a-new-sphinx-project)
8. [Generate your sphinx.lock file](#8-generate-your-sphinxlock-file)
9. [Update your deployment script](#9-update-your-deployment-script)\
a. [Import Sphinx](#a-import-sphinx)\
b. [Inherit from `Sphinx`](#b-inherit-from-sphinx)\
c. [Add the `sphinx` modifier](#c-add-the-sphinx-modifier)\
d. [Remove broadcasts](#d-remove-broadcasts)\
e. [Handle new sender address](#e-handle-new-sender-address)\
f. [Add configuration options](#e-add-configuration-options)
8. [Add environment variables](#8-add-environment-variables)
9. [Update `foundry.toml` settings](#9-update-foundrytoml-settings)
10. [Run tests](#10-run-tests)
11. [Propose on testnets](#11-propose-on-testnets)
12. [Next steps](#12-next-steps)
f. [Configure project name](#f-configure-project-name)
10. [Add environment variables](#10-add-environment-variables)
11. [Update `foundry.toml` settings](#11-update-foundrytoml-settings)
12. [Propose on testnets](#12-propose-on-testnets)
13. [Next steps](#13-next-steps)

## 1. Prerequisites

Expand Down Expand Up @@ -103,7 +104,22 @@ Configure the following remapping in either your `foundry.toml` file or `remappi
@sphinx-labs/contracts/=lib/sphinx/packages/contracts/contracts/foundry
```

## 7. Update your deployment script
## 7. Create a new Sphinx project
Go to the [Sphinx website](https://sphinx.dev), sign up, and click the "Create Project" button. After you've finished creating the project, you'll see your Org ID, API Key, and Project Name on the website. You'll need these values for the rest of the guide.

## 8. Generate your `sphinx.lock` file
Sphinx uses a lock file to track your project configuration options. To generate this file, run the command:
```
npx sphinx sync --org-id <ORG_ID>
```

Commit the file to version control:
```
git add sphinx.lock
git commit -m "maint: Creating Sphinx lock file"
```

## 9. Update your deployment script

Navigate to your deployment script. In this section, we'll update it to be compatible with Sphinx.

Expand Down Expand Up @@ -153,28 +169,21 @@ For example, you may need to:
- Update hardcoded contract addresses
- Assign permissions using your Gnosis Safe address

### f. Add configuration options

There are a few configuration options that you must specify inside a `configureSphinx()` function in your deployment script. The options all exist on the `sphinxConfig` struct, which is inherited from `Sphinx.sol`.
### f. Configure Project Name

Copy and paste the following `configureSphinx()` function template into your script:

```sol
function configureSphinx() public override {
sphinxConfig.owners = [<your address>];
sphinxConfig.orgId = <Sphinx org ID>;
sphinxConfig.projectName = "My_First_Project";
sphinxConfig.threshold = 1;
sphinxConfig.projectName = <your_project_name>;
}
```

You'll need to update the following fields in this template:
* Enter your address in the `owners` array.
* Enter your Sphinx Organization ID in the `orgId` field. It's a public field, so you don't need to keep it secret. You can find it in the Sphinx UI.
You'll need to update the `projectName` field to match the Project Name you created in the Sphinx UI.

## 8. Add environment variables
## 10. Add environment variables

Get your Sphinx API Key from the Sphinx UI, then enter it as an environment variable:
Get your Sphinx API Key from the Sphinx UI and add it as an environment variable:
```
SPHINX_API_KEY=<your_api_key>
```
Expand All @@ -184,22 +193,15 @@ Also, if you haven't added your node provider API key as an environment variable
ALCHEMY_API_KEY=<your_api_key>
```

## 9. Update `foundry.toml` settings
## 11. Update `foundry.toml` settings

Update your `foundry.toml` file to include a few settings required by Sphinx. We recommend putting them in `[profile.default]`.

```
extra_output = ['storageLayout']
fs_permissions = [{ access = "read-write", path = "./"}]
```

## 10. Run tests

You've finished integrating Sphinx! Your next step is to check that your existing tests are passing. Go ahead and run your Forge tests.

If you can't get your test suite to pass, we're more than happy to help! Reach out to us in our [Discord](https://discord.gg/7Gc3DK33Np).

## 11. Propose on testnets
## 12. Propose on testnets

Use one of the command templates below to propose your deployment. Make sure to update the following parts of the command:
* Replace `<PATH_TO_FORGE_SCRIPT>` with the path to your Forge script.
Expand All @@ -225,6 +227,6 @@ Here are the steps that occur when you run this command:

When the proposal is finished, go to the [Sphinx UI](https://sphinx.dev) to approve the deployment. After you approve it, you can monitor the deployment's status in the UI while it's executed.

## 12. Next steps
## 13. Next steps

Before you use Sphinx in production, we recommend reading the [Writing Deployment Scripts with Sphinx guide](https://github.com/sphinx-labs/sphinx/blob/main/docs/writing-scripts.md), which covers essential information for using Sphinx.
23 changes: 10 additions & 13 deletions docs/cli-quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ In this guide, you'll create a sample project, propose it on the command line, a
2. [Create a new directory](#2-create-a-new-directory)
3. [Update Foundry](#3-update-foundry)
4. [Install dependencies](#4-install-dependencies)
5. [Initialize a project](#5-initialize-a-project)
6. [Test the deployment](#6-test-the-deployment)
5. [Create a new Sphinx project](#5-create-a-new-sphinx-project)
6. [Initialize Sphinx](#6-initialize-sphinx)
7. [Propose on testnets](#7-propose-on-testnets)
8. [Next steps](#8-next-steps)

Expand Down Expand Up @@ -66,27 +66,30 @@ pnpm:
pnpm add -D @sphinx-labs/plugins https://github.com/foundry-rs/forge-std.git#v1.7.1 https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0
```

## 5. Initialize a project
## 5. Create a new Sphinx project
Go to the [Sphinx website](https://sphinx.dev), sign up, and click the "Create Project" button. After you've finished creating the project, you'll see your Org ID, API Key, and Project Name on the website. You'll need these values for the rest of the guide.

## 6. Initialize Sphinx

Run one of the following commands on your command line, replacing the placeholders with your values. We've included a description of each command line argument below.

Using Yarn or npm:

```
npx sphinx init --org-id <SPHINX_ORG_ID> --sphinx-api-key <API_KEY> --alchemy-api-key <API_KEY> --owner <YOUR_ADDRESS>
npx sphinx init --org-id <ORG_ID> --sphinx-api-key <API_KEY> --project <PROJECT_NAME> --alchemy-api-key <API_KEY>
```

Using pnpm:

```
pnpm sphinx init --org-id <SPHINX_ORG_ID> --sphinx-api-key <API_KEY> --alchemy-api-key <API_KEY> --owner <YOUR_ADDRESS> --pnpm
pnpm sphinx init --org-id <ORG_ID> --sphinx-api-key <API_KEY> --project <PROJECT_NAME> --alchemy-api-key <API_KEY> --pnpm
```

Command line argument descriptions:
* `--org-id <SPHINX_ORG_ID>`: Your organization ID from the Sphinx UI (under "Options" -> "API Credentials").
* `--org-id <ORG_ID>`: Your organization ID from the Sphinx UI (under "Options" -> "API Credentials").
* `--sphinx-api-key <API_KEY>`: Your API key from the Sphinx UI (under "Options" -> "API Credentials").
* `--alchemy-api-key <API_KEY>`: Your Alchemy API Key.
* `--owner <YOUR_ADDRESS>`: The address of an account you own on live networks.
* `--project <PROJECT_NAME>`: Your project name from the Sphinx UI.
* `--pnpm`: An optional flag that creates remappings for pnpm.

After you run the command, you'll notice several new files:
Expand All @@ -97,12 +100,6 @@ After you run the command, you'll notice several new files:
- `.env`: A sample `.env` file that contains your credentials.
- `.gitignore`: A sample `.gitignore` file that contains files and directories generated by Sphinx, Foundry, and Node.

## 6. Test the deployment

```
forge test
```

## 7. Propose on testnets

Copy and paste one of the following commands to propose your deployment with the DevOps Platform.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"clean": "yarn workspaces run clean",
"lint": "yarn workspaces run lint",
"lint:fix": "yarn workspaces run lint:fix",
"changeset:version:custom": "yarn changeset version && yarn workspace @sphinx-labs/contracts run write-version"
"changeset:version:custom": "yarn changeset version && yarn workspace @sphinx-labs/contracts run write-version && yarn workspace @sphinx-labs/plugins run write-version"
},
"devDependencies": {
"@babel/eslint-parser": "^7.18.2",
Expand Down
17 changes: 8 additions & 9 deletions packages/contracts/contracts/foundry/Sphinx.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ import {
SphinxMerkleTree,
HumanReadableAction,
Network,
SphinxConfig,
FoundryDeploymentInfo,
NetworkInfo,
Wallet,
GnosisSafeTransaction,
ExecutionMode,
SystemContractInfo,
ParsedAccountAccess
UserSphinxConfig
} from "./SphinxPluginTypes.sol";
import { SphinxUtils } from "./SphinxUtils.sol";
import { SphinxConstants } from "./SphinxConstants.sol";
Expand Down Expand Up @@ -53,7 +52,7 @@ abstract contract Sphinx {
* @dev The configuration options for the user's project. This variable must have `internal`
* visibility so that the user can set fields on it.
*/
SphinxConfig public sphinxConfig;
UserSphinxConfig public sphinxConfig;

SphinxConstants private constants;

Expand Down Expand Up @@ -99,7 +98,7 @@ abstract contract Sphinx {
* When fetching the config for normal usage in this contract, we should use the
* `sphinxUtils.fetchAndValidateConfig()` function.
*/
function sphinxFetchConfig() external view returns (SphinxConfig memory) {
function sphinxFetchConfig() external view returns (UserSphinxConfig memory) {
return sphinxConfig;
}

Expand Down Expand Up @@ -158,7 +157,7 @@ abstract contract Sphinx {
) external {
address deployer;
if (_executionMode == ExecutionMode.LiveNetworkCLI) {
sphinxUtils.validateLiveNetworkCLI(sphinxConfig, IGnosisSafe(safeAddress()));
sphinxUtils.validateLiveNetworkCLI(IGnosisSafe(safeAddress()), address(this));
deployer = vm.addr(vm.envUint("PRIVATE_KEY"));
} else if (_executionMode == ExecutionMode.LocalNetworkCLI) {
// Set the `ManagedService` contract as the deployer. Although this isn't strictly
Expand Down Expand Up @@ -212,8 +211,8 @@ abstract contract Sphinx {
// This also also ensures that the safe's nonce is incremented as a contract instead of an EOA.
if (address(safe).code.length == 0) {
sphinxUtils.deployModuleAndGnosisSafe(
sphinxConfig.owners,
sphinxConfig.threshold,
deploymentInfo.newConfig.owners,
deploymentInfo.newConfig.threshold,
safe
);
}
Expand Down Expand Up @@ -353,8 +352,8 @@ abstract contract Sphinx {
* off-chain. We ABI encode the config because it's difficult to decode complex
* data types that are returned by invoking Forge scripts.
*/
function sphinxConfigABIEncoded() public returns (bytes memory) {
SphinxConfig memory config = sphinxUtils.fetchAndValidateConfig(address(this));
function userSphinxConfigABIEncoded() public returns (bytes memory) {
UserSphinxConfig memory config = sphinxUtils.fetchAndValidateConfig(address(this));
return abi.encode(config, safeAddress(), sphinxModule());
}
}
37 changes: 34 additions & 3 deletions packages/contracts/contracts/foundry/SphinxPluginTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct FoundryDeploymentInfo {
uint256 blockNumber;
bytes safeInitData;
bool requireSuccess;
SphinxConfig newConfig;
InternalSphinxConfig newConfig;
ExecutionMode executionMode;
InitialChainState initialState;
bool arbitraryChain;
Expand Down Expand Up @@ -135,7 +135,13 @@ struct InitialChainState {
bool isExecuting;
}

struct SphinxConfig {
struct UserSphinxConfig {
string projectName;
string[] mainnets;
string[] testnets;
}

struct InternalSphinxConfig {
string projectName;
address[] owners;
uint256 threshold;
Expand Down Expand Up @@ -192,6 +198,27 @@ struct SystemContractInfo {
address expectedAddress;
}

/**
* @notice The DefaultSafe is the Gnosis Safe that is used by default when deploying with a project.
* In the future, we will likely support having multiple Safes that can be shared between different
* projects.
*
* Currently, we only support a 1-to-1 relationship between projects and Safes, so we only track the
* default Safe for each project.
*/
struct DefaultSafe {
address[] owners;
string safeName;
uint saltNonce;
uint threshold;
}

struct SphinxLockProject {
DefaultSafe defaultSafe;
string projectName;
string orgId;
}

/**
* @notice Provides an easy way to get complex data types off-chain (via the ABI) without
* needing to hard-code them.
Expand Down Expand Up @@ -236,7 +263,11 @@ contract SphinxPluginTypes {
returns (FoundryDeploymentInfo[] memory deploymentInfoArray)
{}

function sphinxConfigType() external view returns (SphinxConfig memory sphinxConfig) {}
function userSphinxConfigType()
external
view
returns (UserSphinxConfig memory userSphinxConfig)
{}

function systemContractInfoArrayType()
external
Expand Down
Loading

0 comments on commit a978b3b

Please sign in to comment.