Skip to content

Commit 66cbf19

Browse files
authored
Merge pull request #18 from dev-protocol/feat-deployment-script
feat: add SBT deployment scripts.
2 parents 993fd72 + 06dee01 commit 66cbf19

File tree

8 files changed

+242
-4
lines changed

8 files changed

+242
-4
lines changed

.env.example

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
PRIVATE_KEY=''
12
MNEMONIC='Mnemonic'
3+
24
INFURA_KEY=''
3-
ETHERSCAN_KEY=''
5+
ALCHEMY_API_KEY=''
6+
47
ARBISCAN_KEY=''
8+
ETHERSCAN_KEY=''
59
POLYGONSCAN_KEY=''

contracts/SBTFactory.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ contract SBTFactory is ISBTFactory, OwnableUpgradeable {
2727
address[] calldata minters,
2828
bytes calldata identifier
2929
) external override onlyOwner returns (address) {
30+
require(sbtProxyMapping[identifier] == address(0), "Identifier already used");
31+
3032
// Create the implementation.
3133
address implementation = address(
3234
new SBT{salt: keccak256(identifier)}()

hardhat.config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import '@typechain/hardhat'
2+
import * as dotenv from 'dotenv'
23
import '@nomiclabs/hardhat-ethers'
34
import '@nomiclabs/hardhat-waffle'
45
import '@nomiclabs/hardhat-etherscan'
56
import type { HardhatUserConfig } from 'hardhat/config'
6-
import * as dotenv from 'dotenv'
77

88
dotenv.config()
99

@@ -59,7 +59,8 @@ const config: HardhatUserConfig = {
5959
},
6060
},
6161
polygonMumbai: {
62-
url: `https://polygon-mumbai.infura.io/v3/${process.env.INFURA_KEY!}`,
62+
url: `https://polygon-mumbai.g.alchemy.com/v2/${process.env
63+
.ALCHEMY_API_KEY!}`,
6364
accounts: {
6465
mnemonic: mnemnoc,
6566
},

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"build": "tsc -p tsconfig.build.json",
1616
"prebuild": "yarn generate",
1717
"clean": "del 'artifacts'",
18-
"prepare": "husky install"
18+
"prepare": "husky install",
19+
"deploy:polygonMumbai": "npx hardhat run scripts/deploy.ts --network polygonMumbai"
1920
},
2021
"author": "Dev Protocol",
2122
"license": "MPL-2.0",

scripts/deploy.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { ethers, run } from 'hardhat'
2+
import { type ContractTransaction } from 'ethers'
3+
4+
async function main() {
5+
console.log('Starting deploy script on sbt-tokens...')
6+
7+
const [signer] = await ethers.getSigners()
8+
console.log('Signer is: ', signer.address)
9+
console.log()
10+
11+
// @TODO: modify this when deploying...
12+
const minterUpdater = signer.address
13+
// @TODO: modify this when deploying...
14+
const minters = [signer.address]
15+
// @TODO: modify this address when deploying...
16+
const proxyAdmin = '0xec4562C829661c891FcEadb44F831c8a5e71bC8F'
17+
18+
// >>> Deploy SBT implementation >>>
19+
console.log('Deploying SBT implementation...')
20+
const sbtFactory = await ethers.getContractFactory('SBT')
21+
const sbtImplementation = await sbtFactory.deploy()
22+
const sbtImplementationDeployTxn = sbtImplementation.deployTransaction
23+
console.log(
24+
` - SBT implementation deploying at txn hash:${sbtImplementationDeployTxn.hash}`
25+
)
26+
await sbtImplementation.deployed()
27+
console.log(
28+
` - SBT implementation deployed at address:${sbtImplementation.address}`
29+
)
30+
await sbtImplementationDeployTxn.wait(2)
31+
console.log()
32+
33+
// >>> Deploy SBTProxy >>>
34+
console.log('Deploying SBT proxy...')
35+
const sbtProxyFactory = await ethers.getContractFactory('SBTProxy')
36+
const sbtProxyInstance = await sbtProxyFactory.deploy(
37+
sbtImplementation.address,
38+
proxyAdmin,
39+
ethers.utils.arrayify('0x')
40+
)
41+
const sbtProxyInstanceDeployTxn = sbtProxyInstance.deployTransaction
42+
console.log(
43+
` - SBT proxy deploying at txn hash:${sbtProxyInstanceDeployTxn.hash}`
44+
)
45+
await sbtProxyInstance.deployed()
46+
console.log(` - SBT proxy deployed at address:${sbtProxyInstance.address}`)
47+
await sbtProxyInstanceDeployTxn.wait(2)
48+
console.log()
49+
50+
// >>> Initialize SBT Proxy >>>
51+
console.log('Initializing SBT proxy...')
52+
const sbtProxy = sbtFactory.attach(sbtProxyInstance.address)
53+
const tx = (await sbtProxy.functions.initialize(
54+
minterUpdater,
55+
minters
56+
)) as ContractTransaction
57+
console.log(` - Initializing at transaction with hash:${tx.hash}`)
58+
await tx.wait(1)
59+
console.log(` - Initializing done.`)
60+
console.log()
61+
62+
// >>> Verify SBTImplementation code >>>
63+
console.log('Verifying SBT implementation contract...')
64+
await run(`verify:verify`, {
65+
address: sbtImplementation.address,
66+
constructorArguments: [],
67+
})
68+
console.log()
69+
70+
// >>> Verify SBTProxy code >>>
71+
console.log('Verifying SBT proxy contract...')
72+
await run(`verify:verify`, {
73+
address: sbtProxyInstance.address,
74+
contract: 'contracts/SBTProxy.sol:SBTProxy',
75+
constructorArguments: [
76+
sbtImplementation.address,
77+
proxyAdmin,
78+
ethers.utils.arrayify('0x'),
79+
],
80+
})
81+
console.log()
82+
}
83+
84+
main()
85+
.then(() => process.exit(0))
86+
.catch((error) => {
87+
console.error(error)
88+
process.exit(1)
89+
})

scripts/deploySBTFactory.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { ethers, run } from 'hardhat'
2+
3+
async function main() {
4+
console.log('Starting deploySBTFactory script on sbt-tokens...')
5+
6+
const [signer] = await ethers.getSigners()
7+
console.log('Signer is: ', signer.address)
8+
console.log()
9+
10+
// >>> Deploy SBTFactory >>>
11+
console.log('Deploying SBTFactory...')
12+
const sbtFactoryFactory = await ethers.getContractFactory('SBTFactory')
13+
const sbtFactoryInstance = await sbtFactoryFactory.deploy()
14+
const sbtFactoryInstanceDeployTxn = sbtFactoryInstance.deployTransaction
15+
console.log(
16+
` - SBTFactory deploying at txn:${sbtFactoryInstanceDeployTxn.hash}`
17+
)
18+
await sbtFactoryInstance.deployed()
19+
console.log(` - SBTFactory deployed at address:${sbtFactoryInstance.address}`)
20+
await sbtFactoryInstanceDeployTxn.wait(2)
21+
console.log()
22+
23+
// >>> Verify SBTFactory code >>>
24+
console.log('Verifying SBTFactory contract...')
25+
await run(`verify:verify`, {
26+
address: sbtFactoryInstance.address,
27+
constructorArguments: [],
28+
})
29+
console.log()
30+
}
31+
32+
main()
33+
.then(() => process.exit(0))
34+
.catch((error) => {
35+
console.error(error)
36+
process.exit(1)
37+
})

scripts/deployWithSBTFactory.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
2+
3+
import { ethers, run } from 'hardhat'
4+
import type { ContractTransaction } from 'ethers'
5+
6+
import { wait } from './utils/wait'
7+
8+
async function main() {
9+
console.log('Starting deploySBTFactory script on sbt-tokens...')
10+
11+
const [signer] = await ethers.getSigners()
12+
console.log('Signer is: ', signer.address)
13+
console.log()
14+
15+
// @TODO: modify this when deploying...
16+
const minterUpdater = signer.address
17+
// @TODO: modify this when deploying...
18+
const minters = [signer.address]
19+
// @TODO: change this whenever required.
20+
const proxyCalldata = ethers.utils.arrayify('0x')
21+
// @TODO: modify this address when deploying...
22+
const proxyAdmin = '0xec4562C829661c891FcEadb44F831c8a5e71bC8F'
23+
// @TODO: check and change this whenever required.
24+
const identifier = ethers.utils.formatBytes32String('Test Achievement SBT')
25+
// @TODO: check and change this whenever required.
26+
const sbtFactoryAddress = '0x0F0b8697169aF45FC61814C3e5b4d784a909b9A7'
27+
28+
// >>> Deploy using SBTFactory >>>
29+
console.log('Deploying new SBT using SBTFactory...')
30+
const sbtFactoryInstance = await ethers.getContractAt(
31+
'SBTFactory',
32+
sbtFactoryAddress
33+
)
34+
const txn = (await sbtFactoryInstance.functions.makeNewSBT(
35+
proxyAdmin,
36+
proxyCalldata,
37+
minterUpdater,
38+
minters,
39+
identifier
40+
)) as ContractTransaction
41+
console.log(` - SBT deployment using SBTFactory at txn:${txn.hash}`)
42+
const txReceipt = await txn.wait(10)
43+
const logs = txReceipt.logs.map((log) => {
44+
try {
45+
// Because here events/logs contains some deployment/general blockchain events which cannot be parsed by contract.interface.
46+
const l = sbtFactoryInstance.interface.parseLog(log)
47+
return l
48+
} catch (err) {
49+
// Hence, we are removing those as we do not need those events.
50+
return { name: '', args: [] }
51+
}
52+
})
53+
const proxyCreationLog = logs.find((log) => log.name === 'SBTProxyCreated')
54+
const implementationCreationLog = logs.find(
55+
(log) => log.name === 'SBTImplementationCreated'
56+
)
57+
58+
const proxyContractAddress = proxyCreationLog?.args.at(1) as string
59+
const implementationContractAddress = implementationCreationLog?.args.at(
60+
1
61+
) as string
62+
63+
await wait(30 * 1000) // For block explorer to scan newly deployed address and attach it's bytecode to it.
64+
if (implementationCreationLog) {
65+
console.log(
66+
` - SBT implementation deployed at addr:${implementationContractAddress}`
67+
)
68+
console.log(' - Verifying SBT implementation contract...')
69+
await run(`verify:verify`, {
70+
address: implementationContractAddress,
71+
contract: 'contracts/SBT.sol:SBT',
72+
constructorArguments: [],
73+
})
74+
}
75+
76+
await wait(30 * 1000) // For block explorer to scan newly deployed address and attach it's bytecode to it.
77+
78+
if (proxyCreationLog) {
79+
console.log(` - SBT proxy deployed at addr:${proxyContractAddress}`)
80+
console.log(' - Verifying SBT proxy contract...')
81+
await run(`verify:verify`, {
82+
address: proxyContractAddress,
83+
contract: 'contracts/SBTProxy.sol:SBTProxy',
84+
constructorArguments: [
85+
implementationContractAddress,
86+
proxyAdmin,
87+
proxyCalldata,
88+
],
89+
})
90+
}
91+
92+
console.log()
93+
}
94+
95+
main()
96+
.then(() => process.exit(0))
97+
.catch((error) => {
98+
console.error(error)
99+
process.exit(1)
100+
})

scripts/utils/wait.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const wait = async (ms: number) =>
2+
new Promise((resolve) => {
3+
setInterval(resolve, ms)
4+
})

0 commit comments

Comments
 (0)