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

Ownership commands for every program #106

Merged
merged 1 commit into from
Jan 19, 2022
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import Initialize from './initialize'
import AddAccess from './addAccess'
import ReadState from './read'
import { makeAcceptOwnershipCommand } from '../ownership/acceptOwnership'
import { makeTransferOwnershipCommand } from '../ownership/transferOwnership'
import { CONTRACT_LIST } from '../../../lib/contracts'

export default [Initialize, AddAccess, ReadState]
export default [
Initialize,
AddAccess,
ReadState,
makeAcceptOwnershipCommand(CONTRACT_LIST.ACCESS_CONTROLLER),
makeTransferOwnershipCommand(CONTRACT_LIST.ACCESS_CONTROLLER),
]
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import SetupFlow from './setup.dev.flow'
import SetupRDDFlow from './setup.dev.rdd.flow'
import Transmit from './transmit.dev'
import Inspection from './inspection'
import { makeAcceptOwnershipCommand } from '../ownership/acceptOwnership'
import { CONTRACT_LIST } from '../../../lib/contracts'
import { makeTransferOwnershipCommand } from '../ownership/transferOwnership'

export default [
Initialize,
Expand All @@ -36,4 +39,6 @@ export default [
Transmit,
SetupFlow,
SetupRDDFlow,
makeAcceptOwnershipCommand(CONTRACT_LIST.OCR_2),
makeTransferOwnershipCommand(CONTRACT_LIST.OCR_2),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Result } from '@chainlink/gauntlet-core'
import { logger, prompt } from '@chainlink/gauntlet-core/dist/utils'
import { SolanaCommand, TransactionResponse } from '@chainlink/gauntlet-solana'
import { PublicKey } from '@solana/web3.js'
import { CONTRACT_LIST, getContract } from '../../../lib/contracts'
import { SolanaConstructor } from '../../../lib/types'

export const makeAcceptOwnershipCommand = (contractId: CONTRACT_LIST): SolanaConstructor => {
return class AcceptOwnership extends SolanaCommand {
static id = `${contractId}:accept_ownership`
static category = contractId

static examples = [`yarn gauntlet ${contractId}:accept_ownership --network=devnet --state=[PROGRAM_STATE]`]

constructor(flags, args) {
super(flags, args)

this.require(!!this.flags.state, 'Please provide flags with "state"')
}

execute = async () => {
const contract = getContract(contractId, '')
const address = contract.programId.toString()
const program = this.loadProgram(contract.idl, address)

const owner = this.wallet.payer

const state = new PublicKey(this.flags.state)

await prompt(`Accepting ownership of ${contractId} state (${state.toString()}). Continue?`)

const tx = await program.rpc.acceptOwnership({
accounts: {
// Store contract expects an store account instead of a state acc
...(contractId === CONTRACT_LIST.STORE && { store: state }),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@archseer Seems like the store contract expects a different account name than the rest. Should we have same interface on every program?
(https://github.com/smartcontractkit/chainlink-solana/blob/develop/contracts/programs/store/src/lib.rs#L133)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we could do that, I kept the name different initially since there were some calls where both store and ocr2 state had to be passed but in that case it's probably better to use store_state/ocr2_state.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...(contractId !== CONTRACT_LIST.STORE && { state }),
authority: owner.publicKey,
},
signers: [owner],
})

logger.success(`Accepted ownership on tx ${tx}`)

return {
responses: [
{
tx: this.wrapResponse(tx, state.toString(), { state: state.toString() }),
contract: state.toString(),
},
],
} as Result<TransactionResponse>
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { makeTransferOwnershipCommand } from './transferOwnership'
import { makeAcceptOwnershipCommand } from './acceptOwnership'

export default {
makeTransferOwnershipCommand,
makeAcceptOwnershipCommand,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Result } from '@chainlink/gauntlet-core'
import { logger, prompt } from '@chainlink/gauntlet-core/dist/utils'
import { SolanaCommand, TransactionResponse } from '@chainlink/gauntlet-solana'
import { PublicKey } from '@solana/web3.js'
import { CONTRACT_LIST, getContract } from '../../../lib/contracts'
import { SolanaConstructor } from '../../../lib/types'

export const makeTransferOwnershipCommand = (contractId: CONTRACT_LIST): SolanaConstructor => {
return class TransferOwnership extends SolanaCommand {
static id = `${contractId}:transfer_ownership`
static category = contractId

static examples = [
`yarn gauntlet ${contractId}:transfer_ownership --network=devnet --state=[PROGRAM_STATE] --to=[PROPOSED_OWNER]`,
]

constructor(flags, args) {
super(flags, args)

this.require(!!this.flags.state, 'Please provide flags with "state"')
this.require(!!this.flags.to, 'Please provide flags with "to"')
}

execute = async () => {
const contract = getContract(contractId, '')
const address = contract.programId.toString()
const program = this.loadProgram(contract.idl, address)

const owner = this.wallet.payer

const state = new PublicKey(this.flags.state)
const proposedOwner = new PublicKey(this.flags.to)

await prompt(
`Transfering ownership of ${contractId} state (${state.toString()}) to: (${proposedOwner.toString()}). Continue?`,
)

const tx = await program.rpc.transferOwnership(proposedOwner, {
accounts: {
// Store contract expects an store account instead of a state acc
...(contractId === CONTRACT_LIST.STORE && { store: state }),
...(contractId !== CONTRACT_LIST.STORE && { state }),
authority: owner.publicKey,
},
signers: [owner],
})

logger.success(`Ownership transferred to ${proposedOwner.toString()} on tx ${tx}`)

return {
responses: [
{
tx: this.wrapResponse(tx, state.toString(), { state: state.toString() }),
contract: state.toString(),
},
],
} as Result<TransactionResponse>
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import Initialize from './initialize'
import CreateFeed from './createFeed'
import SetValidatorConfig from './setValidatorConfig'
import SetWriter from './setWriter'
import TransferOwnership from './transferOwnership'
import AcceptOwnership from './acceptOwnership'
import SetLoweringAccessController from './setLoweringAccessController'
import { makeAcceptOwnershipCommand } from '../ownership/acceptOwnership'
import { makeTransferOwnershipCommand } from '../ownership/transferOwnership'
import { CONTRACT_LIST } from '../../../lib/contracts'

export default [
Initialize,
CreateFeed,
SetValidatorConfig,
SetWriter,
TransferOwnership,
AcceptOwnership,
SetLoweringAccessController,
makeAcceptOwnershipCommand(CONTRACT_LIST.STORE),
makeTransferOwnershipCommand(CONTRACT_LIST.STORE),
]

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SolanaCommand } from '@chainlink/gauntlet-solana'

interface Oracle {
signer: Buffer
transmitter: Buffer
Expand All @@ -10,3 +12,5 @@ export interface OCR2Config {
offchainConfig: Buffer
offchainConfigVersion: number
}

export type SolanaConstructor = new (flags, args) => SolanaCommand