Skip to content

Commit

Permalink
Feature: Add deploy-all task to passkeys (#387)
Browse files Browse the repository at this point in the history
I needed to deploy the passkeys contracts and found out that there's no
deploy command/task

This PR:
- Adds a `deploy-all` task to the passkey package, similarly to how its
used in other packages (4337 and safe-smart-account)

The command works (doesn't include output from failed attempts where I
had to increase gas price):
```
npm run deploy-all sepolia -w modules/passkey

> @safe-global/safe-passkey@0.2.0-alpha.1 deploy-all
> hardhat deploy-contracts --network sepolia

Nothing to compile
No need to generate any newer typings.
reusing "SafeSignerLaunchpad" at 0xf9E93EfBF37B588f9c79d509c48b87A26c3DfEB9
reusing "DaimoP256Verifier" at 0xc2b78104907F722DABAc4C69f826a522B2754De4
reusing "FCLP256Verifier" at 0xcA89CBa4813D5B40AeC6E57A30d0Eeb500d6531b
reusing "SafeWebAuthnSignerFactory" at 0xc40156AbFEE908E2e3269DA84fa9609bcCDDec60
Verification status for DaimoP256Verifier: SKIPPED
Verification status for FCLP256Verifier: SUCCESS
Verification status for SafeSignerLaunchpad: SUCCESS
Verification status for SafeWebAuthnSignerFactory: SUCCESS
already verified: DaimoP256Verifier (0xc2b78104907F722DABAc4C69f826a522B2754De4), skipping.
verifying FCLP256Verifier (0xcA89CBa4813D5B40AeC6E57A30d0Eeb500d6531b) ...
waiting for result...
 => contract FCLP256Verifier is now verified
verifying SafeSignerLaunchpad (0xf9E93EfBF37B588f9c79d509c48b87A26c3DfEB9) ...
waiting for result...
 => contract SafeSignerLaunchpad is now verified
verifying SafeWebAuthnSignerFactory (0xc40156AbFEE908E2e3269DA84fa9609bcCDDec60) ...
waiting for result...
 => contract SafeWebAuthnSignerFactory is now verified
 ```
  • Loading branch information
mmv08 authored Apr 18, 2024
1 parent 055cbd8 commit 761333c
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 0 deletions.
50 changes: 50 additions & 0 deletions modules/passkey/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,56 @@ npm test
npm run test:4337
```

### Deployments

### Deploy

> :warning: **Make sure to use the correct commit when deploying the contracts.** Any change (even comments) within the contract files will result in different addresses. The tagged versions used by the Safe team can be found in the [releases](https://github.com/safe-global/safe-modules/releases).
This will deploy the contracts deterministically and verify the contracts on etherscan and sourcify.

Preparation:

- Set `MNEMONIC` or `PK` in `.env`
- Set `ETHERSCAN_API_KEY` in `.env`

```bash
npm run deploy-all <network>
```

This will perform the following steps

```bash
npm run build
npx hardhat --network <network> deploy
npx hardhat --network <network> etherscan-verify
npx hardhat --network <network> local-verify
```

#### Custom Networks

It is possible to use the `NODE_URL` env var to connect to any EVM-based network via an RPC endpoint. This connection can then be used with the `custom` network.

E.g. to deploy the contract suite on that network, you would run `npm run deploy-all custom`.

The resulting addresses should be on all networks the same.

Note: The address will vary if the contract code changes or a different Solidity version is used.

### Verify contract

This command will use the deployment artifacts to compile the contracts and compare them to the onchain code.

```bash
npx hardhat --network <network> local-verify
```

This command will upload the contract source to Etherscan.

```bash
npx hardhat --network <network> etherscan-verify
```

## Security and Liability

All contracts are WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Expand Down
2 changes: 2 additions & 0 deletions modules/passkey/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import type { HardhatUserConfig } from 'hardhat/config'
import 'hardhat-deploy'
import { HttpNetworkUserConfig } from 'hardhat/types'
import './src/tasks/codesize'
import './src/tasks/deployContracts'
import './src/tasks/localVerify'

dotenv.config()
const { CUSTOM_NODE_URL, MNEMONIC, ETHERSCAN_API_KEY, PK } = process.env
Expand Down
2 changes: 2 additions & 0 deletions modules/passkey/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
"build:ts": "rimraf dist && tsc",
"coverage": "hardhat coverage",
"codesize": "hardhat codesize",
"deploy-all": "hardhat deploy-contracts --network",
"deploy": "hardhat deploy --network",
"fmt": "prettier --write .",
"fmt:check": "prettier --check .",
"lint": "npm run lint:sol && npm run lint:ts",
Expand Down
9 changes: 9 additions & 0 deletions modules/passkey/src/tasks/deployContracts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { task } from 'hardhat/config'

task('deploy-contracts', 'Deploys and verifies Safe contracts').setAction(async (_, hre) => {
await hre.run('deploy')
await hre.run('local-verify')
await hre.run('etherscan-verify', { forceLicense: true, license: 'LGPL-3.0' })
})

export {}
51 changes: 51 additions & 0 deletions modules/passkey/src/tasks/localVerify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { task } from 'hardhat/config'
import { loadSolc } from '../utils/solc'

task('local-verify', 'Verifies that the local deployment files correspond to the on chain code').setAction(async (_, hre) => {
const allowedSourceKey = ['keccak256', 'content']
const deployedContracts = await hre.deployments.all()
for (const contract of Object.keys(deployedContracts)) {
const deployment = await hre.deployments.get(contract)
if (!deployment.metadata) {
console.log(`Verification status for ${contract}: SKIPPED`)
continue
}
const meta = JSON.parse(deployment.metadata)
const solcjs = await loadSolc(meta.compiler.version)
delete meta.compiler
delete meta.output
delete meta.version
const sources = Object.values<Record<string, unknown>>(meta.sources)
for (const source of sources) {
for (const key of Object.keys(source)) {
if (allowedSourceKey.indexOf(key) < 0) delete source[key]
}
}
meta.settings.outputSelection = {}
const targets = Object.entries<string>(meta.settings.compilationTarget)
for (const [key, value] of targets) {
meta.settings.outputSelection[key] = {}
meta.settings.outputSelection[key][value] = ['evm.deployedBytecode.object', 'evm.deployedBytecode.immutableReferences']
}
delete meta.settings.compilationTarget
const compiled = solcjs.compile(JSON.stringify(meta))
const output = JSON.parse(compiled)
for (const [key, value] of targets) {
const compiledContract = output.contracts[key][value]
const onChainCode = hre.ethers.getBytes(await hre.ethers.provider.getCode(deployment.address))
for (const references of Object.values<{ start: number; length: number }[]>(
compiledContract.evm.deployedBytecode.immutableReferences,
)) {
for (const { start, length } of references) {
onChainCode.fill(0, start, start + length)
}
}
const onchainBytecodeHash = hre.ethers.keccak256(onChainCode)
const localBytecodeHash = hre.ethers.keccak256(`0x${compiledContract.evm.deployedBytecode.object}`)
const verifySuccess = onchainBytecodeHash === localBytecodeHash ? 'SUCCESS' : 'FAILURE'
console.log(`Verification status for ${value}: ${verifySuccess}`)
}
}
})

export {}

0 comments on commit 761333c

Please sign in to comment.