def propose(general_config, blockchain_options, multisig_options): """Create a proposal of MultiSig transaction""" # TODO: Extend this command to cover this list of proposals # - Add new MultiSig owner # - Remove MultiSig owner # - Change threshold of MultiSig # - Upgrade contract (in particular, retarget to a deployed one) # - Transfer ownership of contract # - Send ETH from MultiSig # - Send tokens from MultiSig # - Change global fee range in PolicyManager # - Send raw transaction # Init emitter = general_config.emitter #_ensure_config_root(actor_options.config_root) # TODO: Review this commented out line blockchain = blockchain_options.connect_blockchain(emitter, general_config.debug) registry = get_registry(network=blockchain_options.network) if not multisig_options.checksum_address: multisig_options.checksum_address = select_client_account( emitter=emitter, provider_uri=blockchain_options.provider_uri, poa=blockchain_options.poa, network=blockchain_options.network, registry=registry, show_balances=True) # FIXME: Unexpected input trustee = multisig_options.create_transactingless_trustee(registry) # As a PoC, this command only allows to change the threshold # TODO: Think in the UX for choosing between different types of proposals new_threshold = click.prompt(PROMPT_NEW_MULTISIG_THRESHOLD, type=click.INT) proposal = trustee.propose_changing_threshold(new_threshold) paint_multisig_proposed_transaction(emitter=emitter, proposal=proposal, registry=registry) filepath = Path( f'proposal-changeThreshold-{trustee.multisig_agent.contract_address[:8]}-TX-{proposal.nonce}.json' ) proposal.write(filepath=filepath) emitter.echo( SUCCESSFUL_SAVE_MULTISIG_TX_PROPOSAL.format(filepath=filepath), color='blue', bold=True)
def upgrade(general_config, actor_options, retarget, target_address, ignore_deployed, multisig, confirmations): """Upgrade NuCypher existing proxy contract deployments.""" # # Setup # emitter = general_config.emitter ADMINISTRATOR, deployer_address, blockchain, local_registry = actor_options.create_actor(emitter, is_multisig=bool(multisig)) # FIXME: Workaround for building MultiSig TXs | NRN # # Pre-flight # contract_name = actor_options.contract_name if not contract_name: raise click.BadArgumentUsage(message="--contract-name is required when using --upgrade") try: # Check contract name exists Deployer = ADMINISTRATOR.deployers[contract_name] except KeyError: message = UNKNOWN_CONTRACT_NAME.format(contract_name=contract_name, constants=ADMINISTRATOR.deployers.keys()) emitter.echo(message, color='red', bold=True) raise click.Abort() deployer = Deployer(registry=local_registry) # Check deployer address is owner if Deployer._ownable and deployer_address != deployer.owner: # blockchain read emitter.echo(DEPLOYER_IS_NOT_OWNER.format(deployer_address=deployer_address, contract_name=contract_name, agent=deployer.make_agent())) raise click.Abort() else: emitter.echo('✓ Verified deployer address as contract owner', color='green') # # Business # if multisig: if not target_address: raise click.BadArgumentUsage(message="--multisig requires using --target-address.") if not actor_options.force: click.confirm(CONFIRM_BUILD_RETARGET_TRANSACTION.format(contract_name=contract_name, target_address=target_address), abort=True) transaction = ADMINISTRATOR.retarget_proxy(contract_name=contract_name, target_address=target_address, just_build_transaction=True, confirmations=confirmations) trustee_address = select_client_account(emitter=emitter, prompt="Select trustee address", provider_uri=actor_options.provider_uri, show_eth_balance=False, show_nu_balance=False, show_staking=False) if not actor_options.force: click.confirm(CONFIRM_SELECTED_ACCOUNT.format(address=trustee_address), abort=True) trustee = Trustee(registry=local_registry, checksum_address=trustee_address) transaction_proposal = trustee.create_transaction_proposal(transaction) message = SUCCESSFUL_RETARGET_TX_BUILT.format(contract_name=contract_name, target_address=target_address) emitter.message(message, color='green') paint_multisig_proposed_transaction(emitter, transaction_proposal) # TODO: Show decoded function too filepath = f'proposal-{trustee.multisig_agent.contract_address[:8]}-TX-{transaction_proposal.nonce}.json' transaction_proposal.write(filepath=filepath) emitter.echo(SUCCESSFUL_SAVE_MULTISIG_TX_PROPOSAL.format(filepath=filepath), color='blue', bold=True) return # Exit elif retarget: if not target_address: raise click.BadArgumentUsage(message="--target-address is required when using --retarget") if not actor_options.force: click.confirm(CONFIRM_RETARGET.format(contract_name=contract_name, target_address=target_address), abort=True) receipt = ADMINISTRATOR.retarget_proxy(contract_name=contract_name,target_address=target_address, confirmations=confirmations) message = SUCCESSFUL_RETARGET.format(contract_name=contract_name, target_address=target_address) emitter.message(message, color='green') paint_receipt_summary(emitter=emitter, receipt=receipt) return # Exit else: github_registry = establish_deployer_registry(emitter=emitter, download_registry=True, network=actor_options.network) if not actor_options.force: # Check for human verification of versioned upgrade details click.confirm(CONFIRM_BEGIN_UPGRADE.format(contract_name=contract_name), abort=True) if deployer._ownable: # Only ownable + upgradeable contracts apply verify_upgrade_details(blockchain=blockchain, registry=github_registry, deployer=deployer) # Success receipts = ADMINISTRATOR.upgrade_contract(contract_name=contract_name, ignore_deployed=ignore_deployed, confirmations=confirmations) emitter.message(SUCCESSFUL_UPGRADE.format(contract_name=contract_name), color='green') for name, receipt in receipts.items(): paint_receipt_summary(emitter=emitter, receipt=receipt) emitter.echo(REGISTRY_PUBLICATION_HINT.format(contract_name=contract_name, local_registry=local_registry, network=actor_options.network), color='blue') emitter.echo(ETHERSCAN_VERIFY_HINT.format(solc_version=SOLIDITY_COMPILER_VERSION), color='blue') return # Exit
def upgrade(general_config, actor_options, retarget, target_address, ignore_deployed, multisig): """ Upgrade NuCypher existing proxy contract deployments. """ # Init emitter = general_config.emitter ADMINISTRATOR, _, _, registry = actor_options.create_actor( emitter, is_multisig=bool( multisig)) # FIXME: Workaround for building MultiSig TXs contract_name = actor_options.contract_name if not contract_name: raise click.BadArgumentUsage( message="--contract-name is required when using --upgrade") if multisig: if not target_address: raise click.BadArgumentUsage( message="--multisig requires using --target-address.") if not actor_options.force: click.confirm(CONFIRM_BUILD_RETARGET_TRANSACTION.format( contract_name=contract_name, target_address=target_address), abort=True) transaction = ADMINISTRATOR.retarget_proxy( contract_name=contract_name, target_address=target_address, just_build_transaction=True) trustee_address = select_client_account( emitter=emitter, prompt="Select trustee address", provider_uri=actor_options.provider_uri, show_eth_balance=False, show_nu_balance=False, show_staking=False) if not actor_options.force: click.confirm( CONFIRM_SELECTED_ACCOUNT.format(address=trustee_address), abort=True) trustee = Trustee(registry=registry, checksum_address=trustee_address) transaction_proposal = trustee.create_transaction_proposal(transaction) message = SUCCESSFUL_RETARGET_TX_BUILT.format( contract_name=contract_name, target_address=target_address) emitter.message(message, color='green') paint_multisig_proposed_transaction( emitter, transaction_proposal) # TODO: Show decoded function too filepath = f'proposal-{trustee.multisig_agent.contract_address[:8]}-TX-{transaction_proposal.nonce}.json' transaction_proposal.write(filepath=filepath) emitter.echo( SUCCESSFUL_SAVE_MULTISIG_TX_PROPOSAL.format(filepath=filepath), color='blue', bold=True) elif retarget: if not target_address: raise click.BadArgumentUsage( message="--target-address is required when using --retarget") if not actor_options.force: click.confirm(CONFIRM_RETARGET.format( contract_name=contract_name, target_address=target_address), abort=True) receipt = ADMINISTRATOR.retarget_proxy(contract_name=contract_name, target_address=target_address) message = SUCCESSFUL_RETARGET.format(contract_name=contract_name, target_address=target_address) emitter.message(message, color='green') paint_receipt_summary(emitter=emitter, receipt=receipt) else: if not actor_options.force: click.confirm( CONFIRM_BEGIN_UPGRADE.format(contract_name=contract_name), abort=True) receipts = ADMINISTRATOR.upgrade_contract( contract_name=contract_name, ignore_deployed=ignore_deployed) emitter.message(SUCCESSFUL_UPGRADE.format(contract_name=contract_name), color='green') for name, receipt in receipts.items(): paint_receipt_summary(emitter=emitter, receipt=receipt)