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

Add Library contracts #1

Merged
merged 8 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ NETWORK_NAME=goerli
RPC_URL=https://goerli.infura.io/v3/xxx

DEPLOYER_PRIVATE_KEY=0x0000000000000000000000000000000000000000000000000000000000042069
GAS_LIMIT= # Optional
GAS_PRICE= # Optional

VERIFIER_API_URL=https://api-goerli.etherscan.io/api
VERIFIER_API_KEY=PLACEHOLDER_STRING
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,9 @@ The following is a list of contracts that are deployed by this script.
| GuardV2 | 0x761f5e29944D79d76656323F106CF2efBF5F09e9 |
| GuardV1 | 0x596aF90CecdBF9A768886E771178fd5561dD27Ab |
| Orderbook | 0x2cF83ECbad9D2c43ab49C512715887Bd812896f1 |
| DeveloperMultisig | 0x007a47e6BF40C1e0ed5c01aE42fDC75879140bc4 |
| ERC20MinterFactory | 0x55ECCa57590740DF0df92CE88DBdF9E8309AE9FC |
| ERC721MinterFactory | 0x0Aab812958e7996bf84A046D07639561bF6495bA |
| ERC721SaleFactory | 0x4482E04D68E5460926F25fB270694e9F5125cb61 |
| ERC1155MinterFactory | 0x04B94e4d62cdC04a7bCc829FE3d423fa5fE1b0bc |
| ERC1155SaleFactory | 0xfBa5ACD43246fc8f7B8661aE92fC5e0317FAab20 |
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
}
},
"dependencies": {
"0xsequence": "^1.2.3",
"@0xsequence/solidity-deployer": "^0.0.4",
"@typechain/ethers-v5": "^7.0.1",
"@typescript-eslint/eslint-plugin": "^4.18.0",
Expand Down
222 changes: 195 additions & 27 deletions scripts/deploy-contracts.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import ora from 'ora'
import ora, { Ora } from 'ora'

import { deployers, verifiers } from '@0xsequence/solidity-deployer'
import { JsonRpcProvider } from '@ethersproject/providers'
import { config as dotenvConfig } from 'dotenv'
import { ethers } from 'ethers'
import fs from 'fs'
import { deployGuard } from './factories/deployers/GuardDeployer'
import { BigNumber, ethers } from 'ethers'
import { writeFile } from 'fs/promises'
import { ORDERBOOK_VERIFICATION, Orderbook } from './factories/orderbook/Orderbook'
import { ERC1155MINTERFACTORY_VERIFICATION, ERC1155MinterFactory } from './factories/token_library/ERC1155MinterFactory'
import { ERC1155SALEFACTORY_VERIFICATION, ERC1155SaleFactory } from './factories/token_library/ERC1155SaleFactory'
import { ERC20MINTERFACTORY_VERIFICATION, ERC20MinterFactory } from './factories/token_library/ERC20MinterFactory'
import { ERC721MINTERFACTORY_VERIFICATION, ERC721MinterFactory } from './factories/token_library/ERC721MinterFactory'
import { ERC721SALEFACTORY_VERIFICATION, ERC721SaleFactory } from './factories/token_library/ERC721SaleFactory'
import {
FactoryV1,
GuestModuleV1,
Expand All @@ -13,47 +19,67 @@ import {
RequireFreshSignerV1,
SequenceUtilsV1
} from './factories/v1'
import { FactoryV2, GuestModuleV2, MainModuleUpgradableV2, MainModuleV2, SequenceUtilsV2 } from './factories/v2'
import { deployers, verifiers } from '@0xsequence/solidity-deployer'
import { FACTORY_V1_VERIFICATION } from './factories/v1/FactoryV1'
import { GUEST_MODULE_V1_VERIFICATION } from './factories/v1/GuestModuleV1'
import { MAIN_MODULE_V1_VERIFICATION } from './factories/v1/MainModuleV1'
import { MAIN_MODULE_UPGRADABLE_V1_VERIFICATION } from './factories/v1/MainModuleUpgradableV1'
import { FACTORY_V1_VERIFICATION } from './factories/v1/FactoryV1'
import { SEQUENCE_UTILS_V1_VERIFICATION } from './factories/v1/SequenceUtilsV1'
import { MAIN_MODULE_V1_VERIFICATION } from './factories/v1/MainModuleV1'
import { REQUIRE_FRESH_SIGNER_V1_VERIFICATION } from './factories/v1/RequireFreshSignerV1'
import { FACTORY_V2_VERIFICATION } from './factories/v2/FactoryV2'
import { MAIN_MODULE_V2_VERIFICATION } from './factories/v2/MainModuleV2'
import { MAIN_MODULE_UPGRADABLE_V2_VERIFICATION } from './factories/v2/MainModuleUpgradableV2'
import { SEQUENCE_UTILS_V1_VERIFICATION } from './factories/v1/SequenceUtilsV1'
import { FactoryV2, GuestModuleV2, MainModuleUpgradableV2, MainModuleV2, SequenceUtilsV2 } from './factories/v2'
import { FACTORY_V2_VERIFICATION, WALLET_CREATION_CODE } from './factories/v2/FactoryV2'
import { GUEST_MODULE_V2_VERIFICATION } from './factories/v2/GuestModuleV2'
import { MAIN_MODULE_UPGRADABLE_V2_VERIFICATION } from './factories/v2/MainModuleUpgradableV2'
import { MAIN_MODULE_V2_VERIFICATION } from './factories/v2/MainModuleV2'
import { SEQUENCE_UTILS_V2_VERIFICATION } from './factories/v2/SequenceUtilsV2'
import { ORDERBOOK_VERIFICATION, Orderbook } from './factories/orderbook/Orderbook'
import { deployDeveloperMultisig } from './wallets/DeveloperMultisig'
import { deployGuard } from './wallets/Guard'
import {
TUBPROXY_VERIFICATION,
TransparentUpgradeableBeaconProxy
} from './factories/token_library/TransparentUpgradeableBeaconProxy'
import { UPGRADEABLEBEACON_VERIFICATION, UpgradeableBeacon } from './factories/token_library/UpgradeableBeacon'

dotenvConfig()

const { RPC_URL, DEPLOYER_PRIVATE_KEY, NETWORK_NAME, VERIFIER_API_URL, VERIFIER_API_KEY } = process.env
interface Logger {
log(message: string): void
error(message: string): void
}

const { RPC_URL, DEPLOYER_PRIVATE_KEY, NETWORK_NAME, VERIFIER_API_URL, VERIFIER_API_KEY, GAS_LIMIT, GAS_PRICE } = process.env

export const deployContracts = async (rpcUrl: string, deployerPK: string, networkName?: string): Promise<void> => {
const prompt = ora()
const prompt = ora() as Ora & Logger
prompt.log = (message: string) => {
// Log a message and keep spinner running
const currentText = prompt.text
prompt.info(message)
prompt.start(currentText)
}
prompt.error = prompt.fail

const provider = new JsonRpcProvider(rpcUrl)
const signer = new ethers.Wallet(deployerPK, provider)
provider.getSigner = () => signer as unknown as ethers.providers.JsonRpcSigner

prompt.info(`Network Name: ${networkName}`)
prompt.info(`Chain Id: ${(await provider.getNetwork()).chainId}`)
prompt.info(`Gas price: ${await provider.getGasPrice()}`)
prompt.info(`Local Deployer Address: ${await signer.getAddress()}`)
prompt.info(`Local Deployer Balance: ${await signer.getBalance()}`)

// v1

prompt.start(`Deploying V1 contracts\n`)

const txParams = {
// gasLimit: BigNumber.from(7500000),
gasLimit: await provider.getBlock('latest').then(b => b.gasLimit.mul(4).div(10))
gasPrice: GAS_PRICE ? BigNumber.from(GAS_PRICE) : undefined, // Automated gas price
// gasPrice: (await provider.getGasPrice()).mul(3).div(2), // 1.5x gas price
gasLimit: GAS_LIMIT ? BigNumber.from(GAS_LIMIT) : await provider.getBlock('latest').then(b => b.gasLimit.mul(4).div(10))
// gasPrice: BigNumber.from(10).pow(8).mul(16)
}

const universalDeployer = new deployers.UniversalDeployer(signer, console)
// v1

prompt.start(`Deploying V1 contracts\n`)

const universalDeployer = new deployers.UniversalDeployer(signer, prompt)

const walletFactoryV1 = await universalDeployer.deploy('WalletFactory', FactoryV1, 0, txParams)
const mainModuleV1 = await universalDeployer.deploy('MainModule', MainModuleV1, 0, txParams, walletFactoryV1.address)
Expand All @@ -80,7 +106,8 @@ export const deployContracts = async (rpcUrl: string, deployerPK: string, networ
'Guard V1',
'0x596aF90CecdBF9A768886E771178fd5561dD27Ab',
mainModuleV1.address,
'0xc99c1ab359199e4dcbd4603e9b2956d5681241ceb286359cf6a647ca56e6e128'
'0xc99c1ab359199e4dcbd4603e9b2956d5681241ceb286359cf6a647ca56e6e128',
txParams
)

prompt.succeed(`Deployed V1 contracts\n`)
Expand All @@ -89,7 +116,7 @@ export const deployContracts = async (rpcUrl: string, deployerPK: string, networ

prompt.start(`Deploying V2 contracts\n`)

const singletonDeployer = new deployers.SingletonDeployer(signer, console) //, undefined, BigNumber.from('30000000000000000'))
const singletonDeployer = new deployers.SingletonDeployer(signer, prompt) //, undefined, BigNumber.from('30000000000000000'))

const walletFactoryV2 = await singletonDeployer.deploy('Factory', FactoryV2, 0, txParams)
const mainModuleUpgradeableV2 = await singletonDeployer.deploy('MainModuleUpgradable', MainModuleUpgradableV2, 0, txParams)
Expand All @@ -109,21 +136,78 @@ export const deployContracts = async (rpcUrl: string, deployerPK: string, networ
'Guard V2',
'0x761f5e29944D79d76656323F106CF2efBF5F09e9',
mainModuleV2.address,
'0x6e2f52838722eda7d569b52db277d0d87d36991a6aa9b9657ef9d8f09b0c33f4'
'0x6e2f52838722eda7d569b52db277d0d87d36991a6aa9b9657ef9d8f09b0c33f4',
txParams
)

prompt.succeed(`Deployed V2 contracts\n`)

// Sequence development multisig

prompt.start(`Deploying Sequence development multisig\n`)

const v2WalletContext = {
version: 2,
factory: walletFactoryV2.address,
mainModule: mainModuleV2.address,
mainModuleUpgradable: mainModuleUpgradeableV2.address,
guestModule: guestModuleV2.address,
sequenceUtils: sequenceUtilsV2.address,
walletCreationCode: WALLET_CREATION_CODE
}
const developerMultisig = await deployDeveloperMultisig(signer, v2WalletContext, txParams)
prompt.succeed(`Deployed Sequence development multisig\n`)

// Marketplace contracts

prompt.start(`Deploying Marketplace contracts\n`)
const orderbook = await singletonDeployer.deploy('Orderbook', Orderbook, 0, txParams)
prompt.succeed(`Deployed Marketplace contracts\n`)

// Contracts library

prompt.start(`Deploying Library contracts\n`)
const erc20MinterFactory = await singletonDeployer.deploy(
'ERC20MinterFactory',
ERC20MinterFactory,
0,
txParams,
developerMultisig.address
)
const erc721MinterFactory = await singletonDeployer.deploy(
'ERC721MinterFactory',
ERC721MinterFactory,
0,
txParams,
developerMultisig.address
)
const erc721SaleFactory = await singletonDeployer.deploy(
'ERC721SaleFactory',
ERC721SaleFactory,
0,
txParams,
developerMultisig.address
)
const erc1155MinterFactory = await singletonDeployer.deploy(
'ERC1155MinterFactory',
ERC1155MinterFactory,
0,
txParams,
developerMultisig.address
)
const erc1155SaleFactory = await singletonDeployer.deploy(
'ERC1155SaleFactory',
ERC1155SaleFactory,
0,
txParams,
developerMultisig.address
)
prompt.succeed(`Deployed Library contracts\n`)

// Output addresses

prompt.start(`Writing deployment information to output_${networkName}.json\n`)
fs.writeFileSync(
void writeFile(
`./output_${networkName}.json`,
JSON.stringify(
[
Expand All @@ -140,7 +224,13 @@ export const deployContracts = async (rpcUrl: string, deployerPK: string, networ
{ name: 'RequireFreshSignerLibV1', address: requireFreshSignerLibV1.address },
{ name: 'GuardV2', address: '0x761f5e29944D79d76656323F106CF2efBF5F09e9' },
{ name: 'GuardV1', address: '0x596aF90CecdBF9A768886E771178fd5561dD27Ab' },
{ name: 'DeveloperMultisig', address: developerMultisig.address },
{ name: 'Orderbook', address: orderbook.address },
{ name: 'ERC20MinterFactory', address: erc20MinterFactory.address },
{ name: 'ERC721MinterFactory', address: erc721MinterFactory.address },
{ name: 'ERC721SaleFactory', address: erc721SaleFactory.address },
{ name: 'ERC1155MinterFactory', address: erc1155MinterFactory.address },
{ name: 'ERC1155SaleFactory', address: erc1155SaleFactory.address }
],
null,
2
Expand All @@ -156,7 +246,7 @@ export const deployContracts = async (rpcUrl: string, deployerPK: string, networ
return
}

const verifier = new verifiers.EtherscanVerifier(VERIFIER_API_KEY, VERIFIER_API_URL, console)
const verifier = new verifiers.EtherscanVerifier(VERIFIER_API_KEY, VERIFIER_API_URL, prompt)
const waitForSuccess = true // One at a time

const { defaultAbiCoder } = ethers.utils
Expand Down Expand Up @@ -210,6 +300,84 @@ export const deployContracts = async (rpcUrl: string, deployerPK: string, networ
prompt.start('Verifying Marketplace contracts\n')
await verifier.verifyContract(orderbook.address, { ...ORDERBOOK_VERIFICATION, waitForSuccess })
prompt.succeed('Verified Marketplace contracts\n')

// Library contracts

prompt.start(`Verifying Library contracts\n`)
// Factories
await verifier.verifyContract(erc20MinterFactory.address, {
...ERC20MINTERFACTORY_VERIFICATION,
waitForSuccess,
constructorArgs: defaultAbiCoder.encode(['address'], [developerMultisig.address])
})
await verifier.verifyContract(erc721MinterFactory.address, {
...ERC721MINTERFACTORY_VERIFICATION,
waitForSuccess,
constructorArgs: defaultAbiCoder.encode(['address'], [developerMultisig.address])
})
await verifier.verifyContract(erc721SaleFactory.address, {
...ERC721SALEFACTORY_VERIFICATION,
waitForSuccess,
constructorArgs: defaultAbiCoder.encode(['address'], [developerMultisig.address])
})
await verifier.verifyContract(erc1155MinterFactory.address, {
...ERC1155MINTERFACTORY_VERIFICATION,
waitForSuccess,
constructorArgs: defaultAbiCoder.encode(['address'], [developerMultisig.address])
})
await verifier.verifyContract(erc1155SaleFactory.address, {
...ERC1155SALEFACTORY_VERIFICATION,
waitForSuccess,
constructorArgs: defaultAbiCoder.encode(['address'], [developerMultisig.address])
})
// Also deploy the TUBProxy for verification purposes
const tubProxy = await singletonDeployer.deploy(
'TransparentUpgradeableBeaconProxy',
TransparentUpgradeableBeaconProxy,
0,
txParams
)
// Token contracts deployed by the factories
const beacon = new UpgradeableBeacon(signer)
await verifier.verifyContract(await beacon.attach(await erc20MinterFactory.beacon()).implementation(), {
...ERC20MINTERFACTORY_VERIFICATION,
contractToVerify: 'src/tokens/ERC20/presets/minter/ERC20TokenMinter.sol:ERC20TokenMinter',
waitForSuccess
})
await verifier.verifyContract(await beacon.attach(await erc721MinterFactory.beacon()).implementation(), {
...ERC721MINTERFACTORY_VERIFICATION,
contractToVerify: 'src/tokens/ERC721/presets/minter/ERC721TokenMinter.sol:ERC721TokenMinter',
waitForSuccess
})
await verifier.verifyContract(await beacon.attach(await erc721SaleFactory.beacon()).implementation(), {
...ERC721SALEFACTORY_VERIFICATION,
contractToVerify: 'src/tokens/ERC721/presets/sale/ERC721Sale.sol:ERC721Sale',
waitForSuccess
})
await verifier.verifyContract(await beacon.attach(await erc1155MinterFactory.beacon()).implementation(), {
...ERC1155MINTERFACTORY_VERIFICATION,
contractToVerify: 'src/tokens/ERC1155/presets/minter/ERC1155TokenMinter.sol:ERC1155TokenMinter',
waitForSuccess
})
const erc1155SaleBeacon = await erc1155SaleFactory.beacon()
const erc1155SaleImplementation = await beacon.attach(erc1155SaleBeacon).implementation()
await verifier.verifyContract(erc1155SaleImplementation, {
...ERC1155SALEFACTORY_VERIFICATION,
contractToVerify: 'src/tokens/ERC1155/presets/sale/ERC1155Sale.sol:ERC1155Sale',
waitForSuccess
})
// Proxies
await verifier.verifyContract(erc1155SaleBeacon, {
...UPGRADEABLEBEACON_VERIFICATION,
waitForSuccess,
constructorArgs: defaultAbiCoder.encode(['address'], [erc1155SaleImplementation])
})
await verifier.verifyContract(tubProxy.address, {
...TUBPROXY_VERIFICATION,
waitForSuccess
})

prompt.succeed(`Verified Library contracts\n`)
}

const main = async () => {
Expand Down
Loading