Skip to content

Commit

Permalink
fix: update plugins readme and demo
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-goldman committed Dec 12, 2022
1 parent ba24573 commit ad6a5be
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 157 deletions.
6 changes: 6 additions & 0 deletions .changeset/dull-crabs-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@chugsplash/demo': patch
'@chugsplash/plugins': patch
---

Update plugins README and demo
16 changes: 2 additions & 14 deletions packages/demo/chugsplash/SimpleStorage.config.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,21 @@
import { UserChugSplashConfig } from '@chugsplash/core'
import { ChugSplashConfig } from '@chugsplash/core'

const config: UserChugSplashConfig = {
const config: ChugSplashConfig = {
// Configuration options for the project:
options: {
projectName: 'My First Project',
},
// Below, we define all of the contracts in the deployment along with their state variables.
contracts: {
// First contract config:
FirstSimpleStorage: {
contract: 'SimpleStorage',
variables: {
number: 1,
stored: true,
storageName: 'First',
otherStorage: { '!Ref': 'SecondSimpleStorage' }, // Reference to SecondSimpleStorage
},
},
// Second contract config:
SecondSimpleStorage: {
contract: 'SimpleStorage',
variables: {
number: 2,
stored: true,
storageName: 'Second',
otherStorage: '0x1111111111111111111111111111111111111111',
},
},
},
}

export default config
27 changes: 4 additions & 23 deletions packages/demo/contracts/SimpleStorage.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

contract SimpleStorage {
// Define immutable variables
uint8 internal immutable number;
bool internal immutable stored;
address internal immutable otherStorage;
uint8 public immutable number;
bool public immutable stored;
address public immutable otherStorage;
// Leave `storageName` unchanged since Solidity doesn't support immutable strings
string internal storageName;
string public storageName;

// We must instantiate the immutable variables in the constructor so that
// Solidity doesn't throw an error.
Expand All @@ -16,20 +13,4 @@ contract SimpleStorage {
stored = _stored;
otherStorage = _otherStorage;
}

function getNumber() external view returns (uint8) {
return number;
}

function isStored() external view returns (bool) {
return stored;
}

function getStorageName() external view returns (string memory) {
return storageName;
}

function getOtherStorage() external view returns (address) {
return otherStorage;
}
}
12 changes: 5 additions & 7 deletions packages/demo/test/SimpleStorage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@ import { Contract } from 'ethers'

describe('SimpleStorage', () => {
let FirstSimpleStorage: Contract
let SecondSimpleStorage: Contract
beforeEach(async () => {
// You must reset your ChugSplash deployments to their initial state here
await chugsplash.reset()

FirstSimpleStorage = await chugsplash.getContract('FirstSimpleStorage')
SecondSimpleStorage = await chugsplash.getContract('SecondSimpleStorage')
})

it('initializes correctly', async () => {
expect(await FirstSimpleStorage.getNumber()).equals(1)
expect(await FirstSimpleStorage.getOtherStorage()).equals(
SecondSimpleStorage.address
expect(await FirstSimpleStorage.number()).equals(1)
expect(await FirstSimpleStorage.stored()).equals(true)
expect(await FirstSimpleStorage.storageName()).equals('First')
expect(await FirstSimpleStorage.otherStorage()).equals(
'0x1111111111111111111111111111111111111111'
)
expect(await SecondSimpleStorage.isStored()).equals(true)
expect(await SecondSimpleStorage.getStorageName()).equals('Second')
})
})
165 changes: 53 additions & 112 deletions packages/plugins/README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
# ChugSplash Hardhat plugin
# ChugSplash Tutorial

ChugSplash is a modern smart contract deployment system that lets you to define your deployments inside of a configuration file instead of writing scripts. ChugSplash automatically verifies your source code on Etherscan and generates deployment artifacts in the same format as hardhat-deploy.
This tutorial will walk you through the process of deploying your first smart contract using the ChugSplash Hardhat plugin.

## Installation
Install the ChugSplash packages.

With Yarn:
```
yarn add --dev @chugsplash/plugins @chugsplash/core
```
With NPM:
With npm:
```
npm install --save-dev @chugsplash/plugins @chugsplash/core
```

## Setup
Import the ChugSplash plugin in your `hardhat.config.ts` file:
```
In `hardhat.config.ts`, import `chugsplash/plugins`:
```ts
import '@chugsplash/plugins'
```

Update the `outputSelection` setting in your `hardhat.config.ts` file:
```typescript
Update the `outputSelection` setting in `hardhat.config.ts`:
```ts
const config: HardhatUserConfig = {
...
solidity: {
Expand All @@ -46,114 +45,48 @@ export default config
pragma solidity ^0.8.9;
contract SimpleStorage {
uint8 internal number;
bool internal stored;
address internal otherStorage;
string internal storageName;
function getNumber() external view returns (uint8) {
return number;
}
function isStored() external view returns (bool) {
return stored;
}
function getOtherStorage() external view returns (address) {
return otherStorage;
}
function getStorageName() external view returns (string memory) {
return storageName;
}
uint8 public number;
bool public stored;
address public otherStorage;
string public storageName;
}
```

2. Compile your contract:
```
npx hardhat compile
```

3. Make a `chugsplash/` folder in your project root:
2. Create a `chugsplash/` folder, and a ChugSplash config file inside it. We'll call the config file `SimpleStorage.config.ts`.
```
mkdir chugsplash
mkdir chugsplash && echo > chugsplash/SimpleStorage.config.ts
```

4. In your `chugsplash/` folder, create a config file for your first ChugSplash project. We'll call it `SimpleStorage.config.ts`.
```
echo > chugsplash/MyFirstProject.config.ts
```

5. Copy and paste the following deployment information into your ChugSplash config file. You will deploy two instances of the `SimpleStorage` contract.
3. Copy and paste the following into your ChugSplash config file:
```typescript
import { ChugSplashConfig } from '@chugsplash/core'

const config: ChugSplashConfig = {
// Configuration options for the project:
options: {
projectName: 'My First Project',
projectOwner: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
},
// Below, we define all of the contracts in the deployment along with their state variables.
contracts: {
// First contract config:
FirstSimpleStorage: {
contract: 'SimpleStorage',
variables: {
number: 1,
stored: true,
storageName: 'First',
storageName: 'First',
otherStorage: { '!Ref': 'SecondSimpleStorage' }, // Reference to SecondSimpleStorage
},
},
// Second contract config:
SecondSimpleStorage: {
contract: 'SimpleStorage',
variables: {
number: 2,
stored: true,
storageName: 'Second',
otherStorage: '0x1111111111111111111111111111111111111111',
},
},
},
}
}
export default config
```

Take a moment to familiarize yourself with the layout of the ChugSplash config file. Notice that we assign values directly to the state variables, so there is no need for a constructor or initializer function in the contract.

6. Deploy the contracts locally:
```
npx hardhat chugsplash-deploy
4. Deploy the contracts locally:
```

### Immutable variables
ChugSplash supports all immutable variables except for [user defined value types](https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types). You can define immutable variables in your ChugSplash config file the exact same way that you define regular state variables. However, there is one caveat: you must instantiate the immutable variables in your constructor or else the Solidity compiler will throw an error. If we wanted to change the state variables in our `SimpleStorage` example to be immutable, we can keep the ChugSplash config file unchanged and update `SimpleStorage.sol` to include the following:
```solidity
contract SimpleStorage {
// Define immutable variables
uint8 internal immutable number;
bool internal immutable stored;
address internal immutable otherStorage;
// Leave `storageName` unchanged since Solidity doesn't support immutable strings
string internal storageName;
// We must instantiate the immutable variables in the constructor so that
// Solidity doesn't throw an error.
constructor(
uint8 _number,
bool _stored,
address _otherStorage
) {
number = _number;
stored = _stored;
otherStorage = _otherStorage;
}
...
}
npx hardhat chugsplash-deploy chugsplash/SimpleStorage.config.ts
```

### Testing your deployments
Expand All @@ -167,20 +100,18 @@ import { Contract } from 'ethers'

describe('SimpleStorage', () => {
let FirstSimpleStorage: Contract
let SecondSimpleStorage: Contract
beforeEach(async () => {
// You must reset your ChugSplash deployments to their initial state here
await chugsplash.reset()

FirstSimpleStorage = await chugsplash.getContract('FirstSimpleStorage')
SecondSimpleStorage = await chugsplash.getContract('SecondSimpleStorage')
})

it('initializes correctly', async () => {
expect(await FirstSimpleStorage.getNumber()).equals(1)
expect(await FirstSimpleStorage.getOtherStorage()).equals(SecondSimpleStorage.address)
expect(await SecondSimpleStorage.isStored()).equals(true)
expect(await SecondSimpleStorage.getStorageName()).equals('Second')
expect(await FirstSimpleStorage.number()).equals(1)
expect(await FirstSimpleStorage.stored()).equals(true)
expect(await FirstSimpleStorage.storageName()).equals('First')
expect(await FirstSimpleStorage.otherStorage()).equals('0x1111111111111111111111111111111111111111')
})
})
```
Expand All @@ -190,27 +121,37 @@ describe('SimpleStorage', () => {
npx hardhat test test/SimpleStorage.spec.ts
```

### Immutable variables
You can define immutable variables in your ChugSplash config file the exact same way that you define regular state variables. However, there is one caveat: you must instantiate the immutable variables in your constructor or else the Solidity compiler will throw an error. If we wanted to change the state variables in our `SimpleStorage` example to be immutable, we can keep the ChugSplash config file unchanged and update `SimpleStorage.sol`:
```solidity
contract SimpleStorage {
// Define immutable variables
uint8 public immutable number;
bool public immutable stored;
address public immutable otherStorage;
// Leave `storageName` unchanged since Solidity doesn't support immutable strings
string public storageName;
// We must instantiate the immutable variables in the constructor so that
// Solidity doesn't throw an error.
constructor(
uint8 _number,
bool _stored,
address _otherStorage
) {
number = _number;
stored = _stored;
otherStorage = _otherStorage;
}
}
```

## How it works

ChugSplash uses deterministic proxies to deploy contracts and set their state variables. An important point to mention is that the values of state variables are set in the proxy, **not** in the implementation contract. For example, the `number` variable from the `FirstSimpleStorage` contract is set to `1` **only** in the proxy contract. If you call `getNumber` on the implementation contract, it would return the default value, `0`. This is standard behavior for proxies, but it can be surprising if you haven't used proxies before. If you want the proxy to be non-upgradeable, you can set the `projectOwner` parameter in the ChugSplash config file to the zero-address. If this is confusing or problematic for your use case, please reach out to [@samgoldman0](https://t.me/samgoldman0) on Telegram.

## Supported variable types
* Booleans
* Integers (signed and unsigned)
* Addresses
* Contract types
* Structs
* Enums
* Mappings
* Arrays (including dynamic and nested arrays)
* Bytes value types, i.e. bytes1, bytes2, …, bytes32
* Dynamic bytes that are <= 31 bytes
* Strings that are <= 31 characters

## Current limitations
* ChugSplash does not currently support the following variable types:
* Strings that are > 31 characters
* You cannot call contracts inside the constructor of any of your deployed contracts.
* References to contracts in other ChugSplash config files are not supported (i.e. `{"!Ref: MyOtherProject.OtherContract "}`)

These features will be supported in the near future. If you need any of these features before you can start using ChugSplash for your projects, please reach out to [@samgoldman0](https://t.me/samgoldman0) on Telegram and it will be prioritized.
ChugSplash allows you to assign values to your state variables directly (without using a constructor) by compiling your config file down to individual SSTORE actions. These actions are then executed in a standard EIP-1967 proxy.

An important point to mention is that the values of state variables are set in the proxy, **not** in the implementation contract. For example, the `number` variable from the `FirstSimpleStorage` contract is set to `1` **only** in the proxy contract. If you call `number` on the implementation contract, it would return the default value, `0`. This is standard behavior for proxies, but it can be surprising if you haven't used proxies before. You can always set the owner of the proxy to be `address(0)` if you want the proxy to be non-upgradeable.

## Reach out

If you need anything before you can start using ChugSplash for your projects, please reach out to [@samgoldman0](https://t.me/samgoldman0) on Telegram and it will be prioritized.
1 change: 0 additions & 1 deletion packages/plugins/src/hardhat/deployments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ ${configsWithFileNames.map(
const { config: cfg } = configsWithFileNames[0]

const proxyAddress = cfg.contracts[referenceName].proxy
console.log(proxyAddress)
if ((await isContractDeployed(proxyAddress, hre.ethers.provider)) === false) {
throw new Error(`You must first deploy ${referenceName}.`)
}
Expand Down

0 comments on commit ad6a5be

Please sign in to comment.