Skip to content

Commit 79da240

Browse files
abarmatdavekay100
andauthored
Add a contract for governance proposals (#362)
Introduce a contract to inscribe proposals made effective by the Graph Council. The proposals are IPFS hash links that can contain metadata in arbitrary format with its full description. Co-authored-by: David Kajpust <[email protected]>
1 parent 3e6c097 commit 79da240

File tree

19 files changed

+686
-80
lines changed

19 files changed

+686
-80
lines changed

.eslintrc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
"no-extra-semi": "off",
1111
"@typescript-eslint/no-extra-semi": "warn",
1212
"@typescript-eslint/no-inferrable-types": "warn",
13-
"@typescript-eslint/no-empty-function": "warn"
14-
}
13+
"@typescript-eslint/no-empty-function": "warn",
14+
"no-only-tests/no-only-tests": "error"
15+
},
16+
"plugins": [
17+
"no-only-tests"
18+
]
1519
}

addresses.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,22 @@
521521
"creationCodeHash": "0x26a6f47e71ad242e264768571ce7223bf5a86fd0113ab6cb8200f65820232904",
522522
"runtimeCodeHash": "0xd5330527cfb09df657adc879d8ad704ce6b8d5917265cabbd3eb073d1399f122",
523523
"txHash": "0xca463b34d7967c4351d24b2af779817bd1da75e53a48957cfa32abd1ebf3a56c"
524+
},
525+
"GraphGovernance": {
526+
"address": "0x47241861A3918eaa9097c0345bb5A91660D7AEE1",
527+
"initArgs": [
528+
"0x1679a1d1caf1252ba43fb8fc17ebf914a0c725ae"
529+
],
530+
"creationCodeHash": "0xa02709eb59b9cca8bee1271845b42db037dc1d042dad93410ba532d378a7c79f",
531+
"runtimeCodeHash": "0xdb307489fd9a4a438b5b48909e12020b209280ad777561c0a7451655db097e75",
532+
"txHash": "0x5101e33eb13504780b225a2557a7062bef93cada0838937e02e879fb3d5c2c01",
533+
"proxy": true,
534+
"implementation": {
535+
"address": "0xa96F8468362e6A109ABFaAF6BBfDa303347B450e",
536+
"creationCodeHash": "0x5bd7ee7fbf6eb49914ffc91c747d18c0909ca18c495a8b163499ebfdd82b29d2",
537+
"runtimeCodeHash": "0xd77099bdfc3f66aec158303be46e92f8e434271d6b0c7643753cd8ac96b460b9",
538+
"txHash": "0xb12705249777b5d955dd25ea7aebf46c5d1e3062b10bc9a0a5755b40f55e11e9"
539+
}
524540
}
525541
}
526-
}
542+
}

cli/address-book.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ const { AddressZero } = constants
55

66
export type AddressBookEntry = {
77
address: string
8-
constructorArgs?: Array<{ name: string; value: string }>
9-
initArgs?: Array<{ name: string; value: string }>
8+
constructorArgs?: Array<string>
9+
initArgs?: Array<string>
1010
creationCodeHash?: string
1111
runtimeCodeHash?: string
1212
txHash?: string

cli/commands/contracts/governance.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import consola from 'consola'
2+
import yargs, { Argv } from 'yargs'
3+
4+
import { sendTransaction } from '../../network'
5+
import { loadEnv, CLIArgs, CLIEnvironment } from '../../env'
6+
7+
const logger = consola.create({})
8+
9+
export const createProposal = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise<void> => {
10+
const id = cliArgs.id
11+
const votes = cliArgs.votes
12+
const metadata = cliArgs.metadata
13+
const resolution = cliArgs.resolution
14+
const governance = cli.contracts.Governance
15+
16+
logger.log(`Creating proposal ${id}...`)
17+
await sendTransaction(cli.wallet, governance, 'createProposal', [id, votes, metadata, resolution])
18+
}
19+
20+
export const upgradeProposal = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise<void> => {
21+
const id = cliArgs.id
22+
const votes = cliArgs.votes
23+
const metadata = cliArgs.metadata
24+
const resolution = cliArgs.resolution
25+
const governance = cli.contracts.Governance
26+
27+
logger.log(`Upgrade proposal ${id}...`)
28+
await sendTransaction(cli.wallet, governance, 'upgradeProposal', [
29+
id,
30+
votes,
31+
metadata,
32+
resolution,
33+
])
34+
}
35+
36+
export const governanceCommand = {
37+
command: 'governance',
38+
describe: 'Graph governance contract calls',
39+
builder: (yargs: Argv): yargs.Argv => {
40+
return yargs
41+
.command({
42+
command: 'createProposal',
43+
describe: 'Create a proposal',
44+
builder: (yargs: Argv): yargs.Argv => {
45+
return yargs
46+
.option('id', {
47+
description: 'Proposal ID',
48+
type: 'string',
49+
requiresArg: true,
50+
demandOption: true,
51+
})
52+
.option('votes', {
53+
description: 'IPFS hash in bytes32',
54+
type: 'string',
55+
requiresArg: true,
56+
demandOption: true,
57+
})
58+
.option('metadata', {
59+
description: 'IPFS hash in bytes32',
60+
type: 'string',
61+
requiresArg: true,
62+
demandOption: true,
63+
})
64+
.option('resolution', {
65+
description: 'Resolution. 1 = Accepted, 2 = Rejected ',
66+
type: 'number',
67+
requiresArg: true,
68+
demandOption: true,
69+
})
70+
.option('b', {
71+
alias: 'build-tx',
72+
description:
73+
'Build the acceptProxy tx and print it. Then use tx data with a multisig',
74+
})
75+
},
76+
handler: async (argv: CLIArgs): Promise<void> => {
77+
return createProposal(await loadEnv(argv), argv)
78+
},
79+
})
80+
.command({
81+
command: 'upgradeProposal',
82+
describe: 'Upgrade a proposal',
83+
builder: (yargs: Argv): yargs.Argv => {
84+
return yargs
85+
.option('id', {
86+
description: 'Proposal ID',
87+
type: 'string',
88+
requiresArg: true,
89+
demandOption: true,
90+
})
91+
.option('votes', {
92+
description: 'IPFS hash in bytes32',
93+
type: 'string',
94+
requiresArg: true,
95+
demandOption: true,
96+
})
97+
.option('metadata', {
98+
description: 'IPFS hash in bytes32',
99+
type: 'string',
100+
requiresArg: true,
101+
demandOption: true,
102+
})
103+
.option('resolution', {
104+
description: 'Resolution. 1 = Accepted, 2 = Rejected ',
105+
type: 'number',
106+
requiresArg: true,
107+
demandOption: true,
108+
})
109+
.option('b', {
110+
alias: 'build-tx',
111+
description:
112+
'Build the acceptProxy tx and print it. Then use tx data with a multisig',
113+
})
114+
},
115+
handler: async (argv: CLIArgs): Promise<void> => {
116+
return upgradeProposal(await loadEnv(argv), argv)
117+
},
118+
})
119+
},
120+
handler: (): void => {
121+
yargs.showHelp()
122+
},
123+
}

cli/commands/contracts/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import yargs, { Argv } from 'yargs'
1+
import yargs, { Argv, command } from 'yargs'
22

33
import { curationCommand } from './curation'
44
import { serviceRegistryCommand } from './serviceRegistry'
@@ -9,6 +9,7 @@ import { graphTokenCommand } from './graphToken'
99
import { gdaiCommand } from './gsr-gdai'
1010
import { stakingCommand } from './staking'
1111
import { anyCommand } from './any'
12+
import { governanceCommand } from './governance'
1213

1314
import { CLIArgs } from '../../env'
1415
import { disputeManagerCommand } from './disputeManager'
@@ -28,6 +29,7 @@ export const contractsCommand = {
2829
.command(stakingCommand)
2930
.command(anyCommand)
3031
.command(disputeManagerCommand)
32+
.command(governanceCommand)
3133
},
3234
handler: (argv: CLIArgs): void => {
3335
yargs.showHelp()

cli/commands/deploy.ts

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,62 @@
11
import yargs, { Argv } from 'yargs'
22

3-
import { deployContract } from '../network'
3+
import {
4+
getContractAt,
5+
deployContract,
6+
deployContractAndSave,
7+
deployContractWithProxy,
8+
deployContractWithProxyAndSave,
9+
} from '../network'
410
import { loadEnv, CLIArgs, CLIEnvironment } from '../env'
511
import { logger } from '../logging'
612

713
export const deploy = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise<void> => {
814
const contractName = cliArgs.contract
915
const initArgs = cliArgs.init
10-
11-
logger.log(`Deploying contract ${contractName}...`)
16+
const deployType = cliArgs.type
17+
const buildAcceptProxyTx = cliArgs.buildTx
1218

1319
// Deploy contract
1420
const contractArgs = initArgs ? initArgs.split(',') : []
15-
await deployContract(contractName, contractArgs, cli.wallet)
21+
switch (deployType) {
22+
case 'deploy':
23+
logger.log(`Deploying contract ${contractName}...`)
24+
await deployContract(contractName, contractArgs, cli.wallet)
25+
break
26+
case 'deploy-save':
27+
logger.log(`Deploying contract ${contractName} and saving to address book...`)
28+
await deployContractAndSave(contractName, contractArgs, cli.wallet, cli.addressBook)
29+
break
30+
case 'deploy-with-proxy':
31+
// Get the GraphProxyAdmin to own the GraphProxy for this contract
32+
const proxyAdminEntry = cli.addressBook.getEntry('GraphProxyAdmin')
33+
if (!proxyAdminEntry) {
34+
throw new Error('GraphProxyAdmin not detected in the config, must be deployed first!')
35+
}
36+
const proxyAdmin = getContractAt('GraphProxyAdmin', proxyAdminEntry.address)
37+
38+
logger.log(`Deploying contract ${contractName} with proxy ...`)
39+
await deployContractWithProxy(
40+
proxyAdmin,
41+
contractName,
42+
contractArgs,
43+
cli.wallet,
44+
buildAcceptProxyTx,
45+
)
46+
break
47+
case 'deploy-with-proxy-save':
48+
logger.log(`Deploying contract ${contractName} with proxy and saving to address book...`)
49+
await deployContractWithProxyAndSave(
50+
contractName,
51+
contractArgs,
52+
cli.wallet,
53+
cli.addressBook,
54+
buildAcceptProxyTx,
55+
)
56+
break
57+
default:
58+
logger.error('Please provide the correct option for deploy type')
59+
}
1660
}
1761

1862
export const deployCommand = {
@@ -33,6 +77,19 @@ export const deployCommand = {
3377
requiresArg: true,
3478
demandOption: true,
3579
})
80+
.option('t', {
81+
alias: 'type',
82+
description: 'Choose deploy, deploy-save, deploy-with-proxy, deploy-with-proxy-save',
83+
type: 'string',
84+
requiresArg: true,
85+
demandOption: true,
86+
})
87+
.option('b', {
88+
alias: 'build-tx',
89+
description: 'Build the acceptProxy tx and print it. Then use tx data with a multisig',
90+
default: false,
91+
type: 'boolean',
92+
})
3693
},
3794
handler: async (argv: CLIArgs): Promise<void> => {
3895
return deploy(await loadEnv(argv), argv)

cli/commands/migrate.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,12 @@ export const migrate = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise<vo
7474
// Get config and deploy contract
7575
const contractConfig = getContractConfig(graphConfig, cli.addressBook, name)
7676
const deployFn = contractConfig.proxy ? deployContractWithProxyAndSave : deployContractAndSave
77-
const contract = await deployFn(name, contractConfig.params, cli.wallet, cli.addressBook)
77+
const contract = await deployFn(
78+
name,
79+
contractConfig.params.map((a) => a.value), // keep only the values
80+
cli.wallet,
81+
cli.addressBook,
82+
)
7883
logger.log('')
7984

8085
// Defer contract calls after deploying every contract

0 commit comments

Comments
 (0)