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

Governance ContractKit + CLI changes #2139

Merged
merged 95 commits into from
Dec 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
2811be4
Add toBuffer transformer to BaseWrapper
yorhodes Nov 3, 2019
0494f9d
Add Proposal and Transaction interaction to GovernanceWrapper
yorhodes Nov 3, 2019
7943754
Add propose function
yorhodes Nov 3, 2019
1a18c77
Add hotfix functions to Governance wrapper
yorhodes Nov 3, 2019
2e823a9
Add upvote function to Governance wrapper
yorhodes Nov 3, 2019
bb4629b
Add approve, vote, and execute functions to Governance wrapper
yorhodes Nov 3, 2019
808de6b
Add TODOs for using proxyCall and proxySend
yorhodes Nov 3, 2019
a589e82
Transition to using proxyCall
yorhodes Nov 4, 2019
03602a0
Add tests for propose
yorhodes Nov 4, 2019
08c0022
Add test stubs
yorhodes Nov 4, 2019
ef4c57a
Add transaction construction to test stubs
yorhodes Nov 4, 2019
74ee751
Fix hotfix tests
yorhodes Nov 5, 2019
8ab8896
Add revokeUpvote
yorhodes Nov 5, 2019
9051b02
Make test hotfix and proposal transaction results different
yorhodes Nov 5, 2019
f0a6413
Fix lesser and greater calcualtion
yorhodes Nov 5, 2019
a709598
Fix formatting
yorhodes Nov 5, 2019
57ef8c8
Remove proposal index input
yorhodes Nov 5, 2019
e866228
Remove proposal index from params
yorhodes Nov 5, 2019
90e6ee2
Add json transaction builder and tests
yorhodes Nov 6, 2019
f64bf8c
Fix proposal tests with locked gold
yorhodes Nov 7, 2019
7f0fdf1
Fix tests
yorhodes Nov 7, 2019
2d86caa
Add TransactionBuilder
yorhodes Nov 7, 2019
833ed19
Add map utilities to tx builder
yorhodes Nov 7, 2019
fc7ce7b
Add doc strings
yorhodes Nov 7, 2019
8c84218
Update tests to work with tx builder
yorhodes Nov 7, 2019
b45a333
Add validator registration for hotfix tests
yorhodes Nov 8, 2019
7417a81
Merge branch 'master' of github.com:celo-org/celo-monorepo into yorho…
yorhodes Nov 8, 2019
6ba8417
Add primitive commands for interacting with proposals
yorhodes Nov 8, 2019
6247723
Add primitive commands for interacting with hotfixes
yorhodes Nov 8, 2019
858a6bf
Add encoded prop to tx builder
yorhodes Nov 8, 2019
a38070d
Make concurrencyMap calls safer
yorhodes Nov 8, 2019
7a0290b
Fix tests
yorhodes Nov 8, 2019
9b59cd5
Address some PR comments
yorhodes Nov 9, 2019
5870fd5
Significant improvements to tx builder
yorhodes Nov 9, 2019
11ae01d
Updates to wrapper interfaces
yorhodes Nov 9, 2019
370b17d
Improve typings
yorhodes Nov 9, 2019
9c3afb2
Remove imports from wrapper to builder
yorhodes Nov 10, 2019
fbf7cbc
Implement json on PTXOProposal
yorhodes Nov 11, 2019
da2c8e7
Simplify proposal utilities
yorhodes Nov 11, 2019
bb8c4be
Fix lint
yorhodes Nov 11, 2019
f970ccd
Increase jest timeout
yorhodes Nov 11, 2019
c9ee368
Fix lint
yorhodes Nov 11, 2019
f2faa20
Merge hotfix and proposal utility
yorhodes Nov 12, 2019
14fe0bc
Dedupe address functions
yorhodes Nov 12, 2019
6b90778
Use expressive names for wrappers
yorhodes Nov 12, 2019
fc84210
Use lambdas in basewrapper functions
yorhodes Nov 12, 2019
0ebd845
Add numberLikeToFrac helper to base wrapper
yorhodes Nov 12, 2019
5e77364
Fix tslint disable
yorhodes Nov 12, 2019
ceb4e2a
Fix lint
yorhodes Nov 12, 2019
48a963e
improvements for toSolidityBytes
yorhodes Nov 12, 2019
5175a15
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 12, 2019
e2454c4
Use block explorer parser in proposal utility
yorhodes Nov 12, 2019
98ad376
Make timeout test specific
yorhodes Nov 12, 2019
30a603e
Merge branch 'master' of github.com:celo-org/celo-monorepo into yorho…
yorhodes Nov 13, 2019
a59cf12
Remove static builder class
yorhodes Nov 13, 2019
63ed59d
Fix lint
yorhodes Nov 13, 2019
1327fa5
Fix contractkit explorer types
yorhodes Nov 14, 2019
1e133b2
Add doc strings and fix migration override
yorhodes Nov 14, 2019
b0c2c4f
Fix migration config merging
yorhodes Nov 14, 2019
3df97c6
Revert migration changes and disable validator dependent tests
yorhodes Nov 15, 2019
c6e58b2
Fix utils usage
yorhodes Nov 15, 2019
527718e
Fix explorer args
yorhodes Nov 15, 2019
9fed3f5
Merge branch 'master' of github.com:celo-org/celo-monorepo into yorho…
yorhodes Nov 15, 2019
fe00b39
Merge branch 'master' of github.com:celo-org/celo-monorepo into yorho…
yorhodes Nov 17, 2019
8f427cf
Fix lint
yorhodes Nov 17, 2019
96033e5
Cleanup
yorhodes Nov 17, 2019
2d768cd
Disable tests
yorhodes Nov 18, 2019
2cb1b1e
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 22, 2019
7373ad7
Further disable tests
yorhodes Nov 22, 2019
08d93e7
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 22, 2019
21d1faf
Update to use new contractkit utilities
yorhodes Nov 22, 2019
eed93e8
Address Nam's PR comments
yorhodes Nov 22, 2019
138308a
Improve utils with hexToBuffer
yorhodes Nov 22, 2019
dafede4
Merge branch 'master' of github.com:celo-org/celo-monorepo into yorho…
yorhodes Nov 22, 2019
5d26d53
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 22, 2019
f0d5274
Merge branch 'master' of github.com:celo-org/celo-monorepo into yorho…
yorhodes Nov 22, 2019
125cb5d
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 22, 2019
6f3c771
Merge branch 'master' of github.com:celo-org/celo-monorepo into yorho…
yorhodes Nov 22, 2019
88740e1
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 22, 2019
afb1428
Fix style in tests
yorhodes Nov 22, 2019
466311a
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 22, 2019
1e4716d
Updates to ProposalBuilder interface
yorhodes Nov 25, 2019
a1c3abb
Fix bugs
yorhodes Nov 26, 2019
b7a3392
Merge branch 'yorhodes/contract-upgrades' into yorhodes/contract-upgr…
yorhodes Nov 26, 2019
aeec67a
Updates to ProposalBuilder interface
yorhodes Nov 26, 2019
94b3e45
Merge branch 'master' into nambrot/contract-upgrades
nambrot Dec 9, 2019
1a0c7c4
More merge fixes
nambrot Dec 9, 2019
e6ad991
Merge branch 'nambrot/contract-upgrades' into yorhodes/contract-upgra…
nambrot Dec 9, 2019
7a6590f
Merge branch 'master' of github.com:celo-org/celo-monorepo into nambr…
yorhodes Dec 23, 2019
337de65
Comment out broken proposalID emit
yorhodes Dec 23, 2019
d2b8308
Fix more conflicts
yorhodes Dec 23, 2019
748114e
Fix celotool calldetails references
yorhodes Dec 23, 2019
b66a4a5
Fix LockedGold wrapper tests
yorhodes Dec 23, 2019
7096201
Fix governance cli docs
yorhodes Dec 23, 2019
d866c8b
Merge branch 'master' of github.com:celo-org/celo-monorepo into nambr…
yorhodes Dec 23, 2019
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: 1 addition & 1 deletion packages/celotool/src/cmds/transactions/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ async function fetchTx(
console.info(
`${parsedTransaction.callDetails.contract}#${
parsedTransaction.callDetails.function
}(${JSON.stringify(parsedTransaction.callDetails.parameters)}) ${parsedTransaction.tx.hash}`
}(${JSON.stringify(parsedTransaction.callDetails.paramMap)}) ${parsedTransaction.tx.hash}`
)

if (receipt.logs) {
Expand Down
24 changes: 24 additions & 0 deletions packages/cli/src/commands/governance/approve.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { flags } from '@oclif/command'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'

export default class Approve extends BaseCommand {
static description = 'Approve a dequeued governance proposal'

static flags = {
...BaseCommand.flags,
proposalID: flags.string({ required: true, description: 'UUID of proposal to approve' }),
from: Flags.address({ required: true, description: "Approver's address" }),
}

static examples = []

async run() {
const res = this.parse(Approve)

const governance = await this.kit.contracts.getGovernance()
const tx = await governance.approve(res.flags.proposalID)
await displaySendTx('approveTx', tx, { from: res.flags.from })
}
}
26 changes: 26 additions & 0 deletions packages/cli/src/commands/governance/approvehotfix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { flags } from '@oclif/command'
import { toBuffer } from 'ethereumjs-util'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'

export default class ApproveHotfix extends BaseCommand {
static description = 'Approve a governance hotfix'

static flags = {
...BaseCommand.flags,
from: Flags.address({ required: true, description: "Approver's address" }),
hash: flags.string({ required: true, description: 'Hash of hotfix transactions' }),
}

static examples = []

async run() {
const res = this.parse(ApproveHotfix)

const governance = await this.kit.contracts.getGovernance()
const hash = toBuffer(res.flags.hash) as Buffer
const tx = governance.approveHotfix(hash)
await displaySendTx('approveHotfixTx', tx, { from: res.flags.from })
}
}
25 changes: 25 additions & 0 deletions packages/cli/src/commands/governance/execute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { flags } from '@oclif/command'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'

export default class Execute extends BaseCommand {
static description = 'Execute a passing governance proposal'

static flags = {
...BaseCommand.flags,
proposalID: flags.string({ required: true, description: 'UUID of proposal to execute' }),
from: Flags.address({ required: true, description: "Executor's address" }),
}

static examples = []

async run() {
const res = this.parse(Execute)

const governance = await this.kit.contracts.getGovernance()

const tx = await governance.execute(res.flags.proposalID)
await displaySendTx('executeTx', tx, { from: res.flags.from })
}
}
26 changes: 26 additions & 0 deletions packages/cli/src/commands/governance/executehotfix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { flags } from '@oclif/command'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'
import { buildProposalFromJsonFile } from '../../utils/governance'

export default class ExecuteHotfix extends BaseCommand {
static description = 'Execute a governance hotfix prepared for the current epoch'

static flags = {
...BaseCommand.flags,
from: Flags.address({ required: true, description: "Executors's address" }),
jsonTransactions: flags.string({ required: true, description: 'Path to json transactions' }),
}

static examples = []

async run() {
const res = this.parse(ExecuteHotfix)

const governance = await this.kit.contracts.getGovernance()
const hotfix = await buildProposalFromJsonFile(this.kit, res.flags.jsonTransactions)
const tx = governance.executeHotfix(hotfix)
await displaySendTx('executeHotfixTx', tx, { from: res.flags.from })
}
}
26 changes: 26 additions & 0 deletions packages/cli/src/commands/governance/preparehotfix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { flags } from '@oclif/command'
import { toBuffer } from 'ethereumjs-util'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'

export default class PrepareHotfix extends BaseCommand {
static description = 'Prepare a governance hotfix for execution in the current epoch'

static flags = {
...BaseCommand.flags,
from: Flags.address({ required: true, description: "Preparer's address" }),
hash: flags.string({ required: true, description: 'Hash of hotfix transactions' }),
}

static examples = []

async run() {
const res = this.parse(PrepareHotfix)

const governance = await this.kit.contracts.getGovernance()
const hash = toBuffer(res.flags.hash) as Buffer
const tx = governance.prepareHotfix(hash)
await displaySendTx('prepareHotfixTx', tx, { from: res.flags.from })
}
}
30 changes: 30 additions & 0 deletions packages/cli/src/commands/governance/propose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { flags } from '@oclif/command'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'
import { buildProposalFromJsonFile } from '../../utils/governance'

export default class Propose extends BaseCommand {
static description = 'Submit a governance proposal'

static flags = {
...BaseCommand.flags,
jsonTransactions: flags.string({ required: true, description: 'Path to json transactions' }),
deposit: flags.string({ required: true, description: 'Amount of Gold to attach to proposal' }),
from: Flags.address({ required: true, description: "Proposer's address" }),
}

static examples = []

async run() {
const res = this.parse(Propose)

const governance = await this.kit.contracts.getGovernance()

const proposal = await buildProposalFromJsonFile(this.kit, res.flags.jsonTransactions)
const tx = governance.propose(proposal)
await displaySendTx('proposeTx', tx, { from: res.flags.from, value: res.flags.deposit })
// const proposalID = await tx.txo.call()
// this.log(`ProposalID: ${proposalID}`)
}
}
24 changes: 24 additions & 0 deletions packages/cli/src/commands/governance/upvote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { flags } from '@oclif/command'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'

export default class Upvote extends BaseCommand {
static description = 'Upvote a queued governance proposal'

static flags = {
...BaseCommand.flags,
proposalID: flags.string({ required: true, description: 'UUID of proposal to upvote' }),
from: Flags.address({ required: true, description: "Upvoter's address" }),
}

static examples = []

async run() {
const res = this.parse(Upvote)

const governance = await this.kit.contracts.getGovernance()
const tx = await governance.upvote(res.flags.proposalID, res.flags.from)
await displaySendTx('upvoteTx', tx, { from: res.flags.from })
}
}
29 changes: 29 additions & 0 deletions packages/cli/src/commands/governance/vote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { VoteValue } from '@celo/contractkit/lib/wrappers/Governance'
import { flags } from '@oclif/command'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'

export default class Vote extends BaseCommand {
static description = 'Vote on an approved governance proposal'

static voteOptions = ['Abstain', 'No', 'Yes']

static flags = {
...BaseCommand.flags,
proposalID: flags.string({ required: true, description: 'UUID of proposal to vote on' }),
vote: flags.enum({ options: Vote.voteOptions, required: true, description: 'Vote' }),
from: Flags.address({ required: true, description: "Voter's address" }),
}

static examples = []

async run() {
const res = this.parse(Vote)

const governance = await this.kit.contracts.getGovernance()

const tx = await governance.vote(res.flags.proposalID, res.flags.vote as keyof typeof VoteValue)
await displaySendTx('voteTx', tx, { from: res.flags.from })
}
}
26 changes: 26 additions & 0 deletions packages/cli/src/commands/governance/whitelisthotfix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { flags } from '@oclif/command'
import { toBuffer } from 'ethereumjs-util'
import { BaseCommand } from '../../base'
import { displaySendTx } from '../../utils/cli'
import { Flags } from '../../utils/command'

export default class WhitelistHotfix extends BaseCommand {
static description = 'Whitelist a governance hotfix'

static flags = {
...BaseCommand.flags,
from: Flags.address({ required: true, description: "Whitelister's address" }),
hash: flags.string({ required: true, description: 'Hash of hotfix transactions' }),
}

static examples = []

async run() {
const res = this.parse(WhitelistHotfix)

const governance = await this.kit.contracts.getGovernance()
const hash = toBuffer(res.flags.hash) as Buffer
const tx = governance.whitelistHotfix(hash)
await displaySendTx('whitelistHotfixTx', tx, { from: res.flags.from })
}
}
6 changes: 3 additions & 3 deletions packages/cli/src/utils/command.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ensureHexLeader, stripHexLeader } from '@celo/utils/lib/address'
import { ensureLeading0x, trimLeading0x } from '@celo/utils/lib/address'
import { BLS_POP_SIZE, BLS_PUBLIC_KEY_SIZE } from '@celo/utils/lib/bls'
import { URL_REGEX } from '@celo/utils/lib/io'
import { isE164NumberStrict } from '@celo/utils/lib/phoneNumbers'
Expand All @@ -13,14 +13,14 @@ const parseBytes = (input: string, length: number, msg: string) => {
// Check that the string is hex and and has byte length of `length`.
const expectedLength = input.startsWith('0x') ? length * 2 + 2 : length * 2
if (Web3.utils.isHex(input) && input.length === expectedLength) {
return ensureHexLeader(input)
return ensureLeading0x(input)
} else {
throw new CLIError(msg)
}
}

const parseEcdsaPublicKey: ParseFn<string> = (input) => {
const stripped = stripHexLeader(input)
const stripped = trimLeading0x(input)
// ECDSA public keys may be passed as 65 byte values. When this happens, we drop the first byte.
if (stripped.length === 65 * 2) {
return parseBytes(stripped.slice(2), 64, `${input} is not an ECDSA public key`)
Expand Down
14 changes: 14 additions & 0 deletions packages/cli/src/utils/governance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ContractKit } from '@celo/contractkit'
import {
ProposalBuilder,
ProposalTransactionJSON,
} from '@celo/contractkit/lib/governance/proposals'
import { readFileSync } from 'fs-extra'

export const buildProposalFromJsonFile = async (kit: ContractKit, jsonFile: string) => {
const builder = new ProposalBuilder(kit)
const jsonString = readFileSync(jsonFile).toString()
const jsonTransactions: ProposalTransactionJSON[] = JSON.parse(jsonString)
jsonTransactions.forEach((tx) => builder.addJsonTx(tx))
return builder.build()
}
18 changes: 10 additions & 8 deletions packages/contractkit/src/explorer/block-explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { ContractDetails, mapFromPairs, obtainKitContractDetails } from './base'
export interface CallDetails {
contract: string
function: string
parameters: Record<string, any>
paramMap: Record<string, any>
argList: any[]
}

export interface ParsedTx {
Expand Down Expand Up @@ -93,23 +94,24 @@ export class BlockExplorer {
return null
}

const parameters: Record<string, any> = abi.decodeParameters(
matchedAbi.inputs!,
encodedParameters
)
const parameters = abi.decodeParameters(matchedAbi.inputs!, encodedParameters)

// remove number & number keys
// remove numbers and number keys from parameters and build ordered list of arguments
const args = new Array(parameters.__length__)
delete parameters.__length__
Object.keys(parameters).forEach((key) => {
if (Number.parseInt(key, 10) >= 0) {
const argIndex = parseInt(key, 10)
if (argIndex >= 0) {
args[argIndex] = parameters[key]
delete parameters[key]
}
})

const callDetails: CallDetails = {
contract: contractMapping.details.name,
function: matchedAbi.name!,
parameters,
paramMap: parameters,
argList: args,
}

return {
Expand Down
17 changes: 0 additions & 17 deletions packages/contractkit/src/explorer/log-explorer.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,9 @@
import { Address } from '@celo/utils/lib/address'
import abi, { ABIDefinition } from 'web3-eth-abi'
import { Block, Transaction } from 'web3/eth/types'
import { EventLog, Log, TransactionReceipt } from 'web3/types'
import { ContractKit } from '../kit'
import { ContractDetails, mapFromPairs, obtainKitContractDetails } from './base'

export interface CallDetails {
contract: string
function: string
parameters: Record<string, any>
}

export interface ParsedTx {
callDetails: CallDetails
tx: Transaction
}

export interface ParsedBlock {
block: Block
parsedTx: ParsedTx[]
}

interface ContractMapping {
details: ContractDetails
logMapping: Map<string, ABIDefinition>
Expand Down
1 change: 1 addition & 0 deletions packages/contractkit/src/governance/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './proposals'
Loading