Implement upgrade using address input

pull/2609/head
David Disu 2 years ago committed by Aniket
parent 94e507e4b0
commit d0cda84847
  1. 19
      apps/remix-ide/src/blockchain/blockchain.js
  2. 14
      libs/remix-core-plugin/src/lib/constants/uups.ts
  3. 29
      libs/remix-core-plugin/src/lib/openzeppelin-proxy.ts
  4. 7
      libs/remix-ui/run-tab/src/lib/actions/deploy.ts
  5. 2
      libs/remix-ui/run-tab/src/lib/actions/events.ts
  6. 274
      libs/remix-ui/run-tab/src/lib/components/contractGUI.tsx
  7. 2
      libs/remix-ui/run-tab/src/lib/reducers/runTab.ts
  8. 2
      libs/remix-ui/run-tab/src/lib/types/index.ts

@ -179,6 +179,25 @@ export class Blockchain extends Plugin {
this.runTx(args, confirmationCb, continueCb, promptCb, finalCb) this.runTx(args, confirmationCb, continueCb, promptCb, finalCb)
} }
async upgradeProxy(proxyAddress, data, newImplementationContractObject) {
const args = { useCall: false, data, to: proxyAddress }
const confirmationCb = (network, tx, gasEstimation, continueTxExecution, cancelCb) => {
// continue using original authorization given by user
continueTxExecution(null)
}
const continueCb = (error, continueTxExecution, cancelCb) => { continueTxExecution() }
const promptCb = (okCb, cancelCb) => { okCb() }
const finalCb = (error, txResult, address, returnValue) => {
if (error) {
const log = logBuilder(error)
return this.call('terminal', 'logHtml', log)
}
return this.call('udapp', 'resolveContractAndAddInstance', newImplementationContractObject, proxyAddress)
}
this.runTx(args, confirmationCb, continueCb, promptCb, finalCb)
}
async getEncodedFunctionHex (args, funABI) { async getEncodedFunctionHex (args, funABI) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
txFormat.encodeFunctionCall(args, funABI, (error, data) => { txFormat.encodeFunctionCall(args, funABI, (error, data) => {

@ -89,3 +89,17 @@ export const UUPSfunAbi = {
outputs: [], outputs: [],
stateMutability: "payable" stateMutability: "payable"
} }
export const UUPSupgradeAbi = {
"inputs": [
{
"internalType": "address",
"name": "newImplementation",
"type": "address"
}
],
"name": "upgradeTo",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}

@ -1,12 +1,12 @@
import { Plugin } from '@remixproject/engine'; import { Plugin } from '@remixproject/engine';
import { ContractABI, ContractAST, DeployOption } from '../types/contract'; import { ContractABI, ContractAST, DeployOption } from '../types/contract';
import { UUPS, UUPSABI, UUPSBytecode, UUPSfunAbi } from './constants/uups'; import { UUPS, UUPSABI, UUPSBytecode, UUPSfunAbi, UUPSupgradeAbi } from './constants/uups';
const proxyProfile = { const proxyProfile = {
name: 'openzeppelin-proxy', name: 'openzeppelin-proxy',
displayName: 'openzeppelin-proxy', displayName: 'openzeppelin-proxy',
description: 'openzeppelin-proxy', description: 'openzeppelin-proxy',
methods: ['isConcerned', 'execute', 'getDeployOptions'] methods: ['isConcerned', 'executeUUPSProxy', 'executeUUPSContractUpgrade', 'getDeployOptions', 'getUpgradeOptions']
}; };
export class OpenZeppelinProxy extends Plugin { export class OpenZeppelinProxy extends Plugin {
blockchain: any blockchain: any
@ -47,7 +47,7 @@ export class OpenZeppelinProxy extends Plugin {
return inputs return inputs
} }
async execute(implAddress: string, args: string | string [] = '', initializeABI, implementationContractObject): Promise<void> { async executeUUPSProxy(implAddress: string, args: string | string [] = '', initializeABI, implementationContractObject): Promise<void> {
// deploy the proxy, or use an existing one // deploy the proxy, or use an existing one
if (!initializeABI) throw new Error('Cannot deploy proxy: Missing initialize ABI') if (!initializeABI) throw new Error('Cannot deploy proxy: Missing initialize ABI')
args = args === '' ? [] : args args = args === '' ? [] : args
@ -56,6 +56,13 @@ export class OpenZeppelinProxy extends Plugin {
if (this.kind === 'UUPS') this.deployUUPSProxy(implAddress, _data, implementationContractObject) if (this.kind === 'UUPS') this.deployUUPSProxy(implAddress, _data, implementationContractObject)
} }
async executeUUPSContractUpgrade (proxyAddress: string, newImplAddress: string, newImplementationContractObject): Promise<void> {
if (!newImplAddress) throw new Error('Cannot upgrade: Missing implementation address')
if (!proxyAddress) throw new Error('Cannot upgrade: Missing proxy address')
if (this.kind === 'UUPS') this.upgradeUUPSProxy(proxyAddress, newImplAddress, newImplementationContractObject)
}
async deployUUPSProxy (implAddress: string, _data: string, implementationContractObject): Promise<void> { async deployUUPSProxy (implAddress: string, _data: string, implementationContractObject): Promise<void> {
const args = [implAddress, _data] const args = [implAddress, _data]
const constructorData = await this.blockchain.getEncodedParams(args, UUPSfunAbi) const constructorData = await this.blockchain.getEncodedParams(args, UUPSfunAbi)
@ -74,4 +81,20 @@ export class OpenZeppelinProxy extends Plugin {
implementationContractObject.name = proxyName implementationContractObject.name = proxyName
this.blockchain.deployProxy(data, implementationContractObject) this.blockchain.deployProxy(data, implementationContractObject)
} }
async upgradeUUPSProxy (proxyAddress: string, newImplAddress: string, newImplementationContractObject): Promise<void> {
const fnData = await this.blockchain.getEncodedFunctionHex([newImplAddress], UUPSupgradeAbi)
const proxyName = 'ERC1967Proxy'
const data = {
contractABI: UUPSABI,
contractName: proxyName,
funAbi: UUPSupgradeAbi,
funArgs: [newImplAddress],
linkReferences: {},
dataHex: fnData.replace('0x', '')
}
// re-use implementation contract's ABI for UI display in udapp and change name to proxy name.
newImplementationContractObject.name = proxyName
this.blockchain.upgradeProxy(proxyAddress, data, newImplementationContractObject)
}
} }

@ -135,6 +135,7 @@ export const createInstance = async (
args, args,
deployMode: DeployMode[]) => { deployMode: DeployMode[]) => {
const isProxyDeployment = (deployMode || []).find(mode => mode === 'Deploy with Proxy') const isProxyDeployment = (deployMode || []).find(mode => mode === 'Deploy with Proxy')
const isContractUpgrade = (deployMode || []).find(mode => mode === 'Upgrade Contract')
const statusCb = (msg: string) => { const statusCb = (msg: string) => {
const log = logBuilder(msg) const log = logBuilder(msg)
@ -160,7 +161,9 @@ export const createInstance = async (
if (isProxyDeployment) { if (isProxyDeployment) {
const initABI = contractObject.abi.find(abi => abi.name === 'initialize') const initABI = contractObject.abi.find(abi => abi.name === 'initialize')
plugin.call('openzeppelin-proxy', 'execute', addressToString(address), args, initABI, contractObject) plugin.call('openzeppelin-proxy', 'executeUUPSProxy', addressToString(address), args, initABI, contractObject)
} else if (isContractUpgrade) {
plugin.call('openzeppelin-proxy', 'executeUUPSContractUpgrade', args, addressToString(address), contractObject)
} }
} }
@ -192,7 +195,7 @@ export const createInstance = async (
return terminalLogger(plugin, log) return terminalLogger(plugin, log)
})) }))
} }
deployContract(plugin, selectedContract, !isProxyDeployment ? args : '', contractMetadata, compilerContracts, { deployContract(plugin, selectedContract, !isProxyDeployment && !isContractUpgrade ? args : '', contractMetadata, compilerContracts, {
continueCb: (error, continueTxExecution, cancelCb) => { continueCb: (error, continueTxExecution, cancelCb) => {
continueHandler(dispatch, gasEstimationPrompt, error, continueTxExecution, cancelCb) continueHandler(dispatch, gasEstimationPrompt, error, continueTxExecution, cancelCb)
}, },

@ -108,7 +108,7 @@ const broadcastCompilationResult = async (plugin: RunTab, dispatch: React.Dispat
if (isUpgradeable) { if (isUpgradeable) {
const options = await plugin.call('openzeppelin-proxy', 'getDeployOptions', data.contracts[file]) const options = await plugin.call('openzeppelin-proxy', 'getDeployOptions', data.contracts[file])
dispatch(setDeployOptions({ options: [{ title: 'Deploy with Proxy', active: false }], initializeOptions: options })) dispatch(setDeployOptions({ options: [{ title: 'Deploy with Proxy', active: false }, { title: 'Upgrade Contract', active: false }], initializeOptions: options }))
} }
else dispatch(setDeployOptions({} as any)) else dispatch(setDeployOptions({} as any))
dispatch(fetchContractListSuccess({ [file]: contracts })) dispatch(fetchContractListSuccess({ [file]: contracts }))

@ -3,8 +3,7 @@ import React, { useEffect, useRef, useState } from 'react'
import * as remixLib from '@remix-project/remix-lib' import * as remixLib from '@remix-project/remix-lib'
import { ContractGUIProps } from '../types' import { ContractGUIProps } from '../types'
import { CopyToClipboard } from '@remix-ui/clipboard' import { CopyToClipboard } from '@remix-ui/clipboard'
import { MultiDeployInput } from './multiDeployInput' import { shortenAddress } from '@remix-ui/helper'
import { DeployInput } from './deployInput'
const txFormat = remixLib.execution.txFormat const txFormat = remixLib.execution.txFormat
export function ContractGUI (props: ContractGUIProps) { export function ContractGUI (props: ContractGUIProps) {
@ -15,20 +14,15 @@ export function ContractGUI (props: ContractGUIProps) {
title: string, title: string,
content: string, content: string,
classList: string, classList: string,
dataId: string, dataId: string
widthClass: string }>({ title: '', content: '', classList: '', dataId: '' })
}>({ title: '', content: '', classList: '', dataId: '', widthClass: '' }) const [toggleDeployProxy, setToggleDeployProxy] = useState<boolean>(false)
const [selectedDeployIndex, setSelectedDeployIndex] = useState<number>(null) const [toggleUpgradeImp, setToggleUpgradeImp] = useState<boolean>(false)
const [showOptions, setShowOptions] = useState<boolean>(false) const [deployState, setDeployState] = useState<{ deploy: boolean, upgrade: boolean }>({ deploy: false, upgrade: false })
const [hasArgs, setHasArgs] = useState<boolean>(false) const [useLastProxy, setUseLastProxy] = useState<boolean>(false)
const [isMultiField, setIsMultiField] = useState<boolean>(false) const [proxyAddress, setProxyAddress] = useState<string>('')
const [deployInputs, setDeployInputs] = useState<{
internalType?: string,
name: string,
type: string
}[]>([])
const [deployPlaceholder, setDeployPlaceholder] = useState<string>('')
const multiFields = useRef<Array<HTMLInputElement | null>>([]) const multiFields = useRef<Array<HTMLInputElement | null>>([])
const initializeFields = useRef<Array<HTMLInputElement | null>>([])
const basicInputRef = useRef<HTMLInputElement>() const basicInputRef = useRef<HTMLInputElement>()
useEffect(() => { useEffect(() => {
@ -41,7 +35,7 @@ export function ContractGUI (props: ContractGUIProps) {
} }
setBasicInput('') setBasicInput('')
// we have the reset the fields before reseting the previous references. // we have the reset the fields before reseting the previous references.
if (basicInputRef.current) basicInputRef.current.value = '' basicInputRef.current.value = ''
multiFields.current.filter((el) => el !== null && el !== undefined).forEach((el) => el.value = '') multiFields.current.filter((el) => el !== null && el !== undefined).forEach((el) => el.value = '')
multiFields.current = [] multiFields.current = []
}, [props.title, props.funcABI]) }, [props.title, props.funcABI])
@ -53,8 +47,7 @@ export function ContractGUI (props: ContractGUIProps) {
title: title + ' - call', title: title + ' - call',
content: 'call', content: 'call',
classList: 'btn-info', classList: 'btn-info',
dataId: title + ' - call', dataId: title + ' - call'
widthClass: props.widthClass
}) })
} else if (props.funcABI.stateMutability === 'payable' || props.funcABI.payable) { } else if (props.funcABI.stateMutability === 'payable' || props.funcABI.payable) {
// // transact. stateMutability = payable // // transact. stateMutability = payable
@ -62,8 +55,7 @@ export function ContractGUI (props: ContractGUIProps) {
title: title + ' - transact (payable)', title: title + ' - transact (payable)',
content: 'transact', content: 'transact',
classList: 'btn-danger', classList: 'btn-danger',
dataId: title + ' - transact (payable)', dataId: title + ' - transact (payable)'
widthClass: props.widthClass
}) })
} else { } else {
// // transact. stateMutability = nonpayable // // transact. stateMutability = nonpayable
@ -71,59 +63,13 @@ export function ContractGUI (props: ContractGUIProps) {
title: title + ' - transact (not payable)', title: title + ' - transact (not payable)',
content: 'transact', content: 'transact',
classList: 'btn-warning', classList: 'btn-warning',
dataId: title + ' - transact (not payable)', dataId: title + ' - transact (not payable)'
widthClass: props.widthClass
}) })
} }
}, [props.lookupOnly, props.funcABI, title]) }, [props.lookupOnly, props.funcABI, title])
useEffect(() => { const getContentOnCTC = () => {
if (props.deployOption && props.deployOption[selectedDeployIndex]) { const multiString = getMultiValsString(multiFields.current)
if (props.deployOption[selectedDeployIndex].title === 'Deploy with Proxy') {
if (props.initializerOptions) {
setDeployInputs(props.initializerOptions.inputs.inputs)
setDeployPlaceholder(props.initializerOptions.initializeInputs)
setHasArgs(true)
if (props.initializerOptions.inputs.inputs.length > 1) setIsMultiField(true)
else setIsMultiField(false)
} else {
setDeployInputs([])
setDeployPlaceholder('')
setHasArgs(false)
setIsMultiField(false)
}
} else {
if (props.funcABI) {
setDeployInputs(props.funcABI.inputs)
setDeployPlaceholder(props.inputs)
setHasArgs(true)
if (props.funcABI.inputs.length > 1) setIsMultiField(true)
else setIsMultiField(false)
} else {
setDeployInputs([])
setDeployPlaceholder('')
setHasArgs(false)
setIsMultiField(false)
}
}
} else {
if (props.funcABI) {
setDeployInputs(props.funcABI.inputs)
setDeployPlaceholder(props.inputs)
setHasArgs(true)
if (props.funcABI.inputs.length > 1) setIsMultiField(true)
else setIsMultiField(false)
} else {
setDeployInputs([])
setDeployPlaceholder('')
setHasArgs(false)
setIsMultiField(false)
}
}
}, [selectedDeployIndex, props.funcABI, props.initializerOptions])
const getContentOnCTC = (fields: HTMLInputElement[]) => {
const multiString = getMultiValsString(fields)
// copy-to-clipboard icon is only visible for method requiring input params // copy-to-clipboard icon is only visible for method requiring input params
if (!multiString) { if (!multiString) {
return 'cannot encode empty arguments' return 'cannot encode empty arguments'
@ -191,8 +137,7 @@ export function ContractGUI (props: ContractGUIProps) {
if (inputString) { if (inputString) {
inputString = inputString.replace(/(^|,\s+|,)(\d+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted number by quoted number inputString = inputString.replace(/(^|,\s+|,)(\d+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted number by quoted number
inputString = inputString.replace(/(^|,\s+|,)(0[xX][0-9a-fA-F]+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted hex string by quoted hex string inputString = inputString.replace(/(^|,\s+|,)(0[xX][0-9a-fA-F]+)(\s+,|,|$)/g, '$1"$2"$3') // replace non quoted hex string by quoted hex string
inputString = JSON.stringify([inputString]) const inputJSON = JSON.parse('[' + inputString + ']')
const inputJSON = JSON.parse(inputString)
const multiInputs = multiFields.current const multiInputs = multiFields.current
for (let k = 0; k < multiInputs.length; k++) { for (let k = 0; k < multiInputs.length; k++) {
@ -204,9 +149,15 @@ export function ContractGUI (props: ContractGUIProps) {
} }
const handleActionClick = () => { const handleActionClick = () => {
const deployMode = selectedDeployIndex !== null ? [props.deployOption[selectedDeployIndex].title] : [] if (deployState.deploy) {
const proxyInitializeString = getMultiValsString(initializeFields.current)
props.clickCallBack(props.funcABI.inputs, basicInput, deployMode) props.clickCallBack(props.initializerOptions.inputs.inputs, proxyInitializeString, ['Deploy with Proxy'])
} else if (deployState.upgrade) {
props.clickCallBack(props.funcABI.inputs, proxyAddress, ['Upgrade Contract'])
} else {
props.clickCallBack(props.funcABI.inputs, basicInput)
}
} }
const handleBasicInput = (e) => { const handleBasicInput = (e) => {
@ -215,51 +166,55 @@ export function ContractGUI (props: ContractGUIProps) {
setBasicInput(value) setBasicInput(value)
} }
const handleMultiValsSubmit = (fields: HTMLInputElement[]) => { const handleExpandMultiClick = () => {
const valsString = getMultiValsString(fields) const valsString = getMultiValsString(multiFields.current)
const deployMode = selectedDeployIndex !== null ? [props.deployOption[selectedDeployIndex].title] : []
if (valsString) { if (valsString) {
props.clickCallBack(props.funcABI.inputs, valsString, deployMode) props.clickCallBack(props.funcABI.inputs, valsString)
} else { } else {
props.clickCallBack(props.funcABI.inputs, '', deployMode) props.clickCallBack(props.funcABI.inputs, '')
} }
} }
const setSelectedDeploy = (index: number) => { const handleToggleDeployProxy = () => {
setSelectedDeployIndex(index !== selectedDeployIndex ? index : null) setToggleDeployProxy(!toggleDeployProxy)
if (basicInputRef.current) basicInputRef.current.value = '' }
setBasicInput('')
const handleDeployProxySelect = (e) => {
const value = e.target.checked
if (value) setToggleUpgradeImp(false)
setToggleDeployProxy(value)
setDeployState({ upgrade: false, deploy: value })
} }
const toggleOptions = () => { const handleToggleUpgradeImp = () => {
setShowOptions(!showOptions) setToggleUpgradeImp(!toggleUpgradeImp)
}
const handleUpgradeImpSelect = (e) => {
const value = e.target.checked
setToggleUpgradeImp(value)
if (value) setToggleDeployProxy(false)
setDeployState({ deploy: false, upgrade: value })
}
const handleUseLastProxySelect = (e) => {
const value = e.target.checked
setUseLastProxy(value)
setProxyAddress('')
}
const handleSetProxyAddress = (e) => {
const value = e.target.value
setProxyAddress(value)
} }
return ( return (
<div className={`udapp_contractProperty ${hasArgs ? 'udapp_hasArgs' : ''}`}> <div className={`udapp_contractProperty ${(props.funcABI.inputs && props.funcABI.inputs.length > 0) || (props.funcABI.type === 'fallback') || (props.funcABI.type === 'receive') ? 'udapp_hasArgs' : ''}`}>
{
props.isDeploy ? !isMultiField ?
<DeployInput
buttonOptions={buttonOptions}
funcABI={props.initializerOptions ? props.initializerOptions.inputs : props.funcABI}
inputs={deployPlaceholder}
handleBasicInput={handleBasicInput}
basicInputRef={basicInputRef}
selectedIndex={selectedDeployIndex}
setSelectedIndex={setSelectedDeploy}
handleActionClick={handleActionClick}
deployOptions={props.deployOption}
/> : <MultiDeployInput
buttonOptions={buttonOptions}
selectedIndex={selectedDeployIndex}
setSelectedIndex={setSelectedDeploy}
handleMultiValsSubmit={handleMultiValsSubmit}
inputs={deployInputs}
getMultiValsString={getMultiValsString}
deployOptions={props.deployOption}
/> :
<>
<div className="udapp_contractActionsContainerSingle pt-2" style={{ display: toggleContainer ? 'none' : 'flex' }}> <div className="udapp_contractActionsContainerSingle pt-2" style={{ display: toggleContainer ? 'none' : 'flex' }}>
<button onClick={handleActionClick} title={buttonOptions.title} className={`udapp_instanceButton ${props.widthClass} btn btn-sm ${buttonOptions.classList}`} data-id={buttonOptions.dataId}>{title}</button> <button onClick={handleActionClick} title={buttonOptions.title} className={`udapp_instanceButton ${props.widthClass} btn btn-sm ${buttonOptions.classList}`} data-id={buttonOptions.dataId}>{title}</button>
<input <input
@ -292,12 +247,111 @@ export function ContractGUI (props: ContractGUIProps) {
})} })}
</div> </div>
<div className="udapp_group udapp_multiArg"> <div className="udapp_group udapp_multiArg">
<CopyToClipboard tip='Encode values of input fields & copy to clipboard' icon='fa-clipboard' direction={'bottom'} getContent={() => getContentOnCTC(multiFields.current)} /> <CopyToClipboard tip='Encode values of input fields & copy to clipboard' icon='fa-clipboard' direction={'bottom'} getContent={getContentOnCTC} />
<button onClick={() => handleMultiValsSubmit(multiFields.current)} title={buttonOptions.title} data-id={buttonOptions.dataId} className={`udapp_instanceButton ${buttonOptions.classList}`}>{ buttonOptions.content }</button> <button onClick={handleExpandMultiClick} title={buttonOptions.title} data-id={buttonOptions.dataId} className={`udapp_instanceButton ${buttonOptions.classList}`}>{ buttonOptions.content }</button>
</div>
</div>
</div>
{ props.deployOption && (props.deployOption || []).length > 0 ?
<>
<div className='d-flex justify-content-between'>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input
id="deployWithProxy"
data-id="contractGUIDeployWithProxy"
className="form-check-input custom-control-input"
type="checkbox"
onChange={handleDeployProxySelect}
checked={deployState.deploy}
/>
<label
htmlFor="deployWithProxy"
data-id="contractGUIDeployWithProxyLabel"
className="m-0 form-check-label custom-control-label udapp_checkboxAlign"
title="An ERC1967 proxy contract will be deployed along with the selected implementation contract."
>
Deploy With Proxy
</label>
</div>
<div>
{
props.initializerOptions && props.initializerOptions.initializeInputs ?
<span onClick={handleToggleDeployProxy}>
<i className={!toggleDeployProxy ? 'fas fa-angle-right pt-2' : 'fas fa-angle-down'} aria-hidden="true"></i>
</span> : null
}
</div>
</div> </div>
{
props.initializerOptions && props.initializerOptions.initializeInputs ?
<div className={`pl-4 flex-column ${toggleDeployProxy ? "d-flex" : "d-none"}`}>
<div className={`flex-column 'd-flex'}`}>{
props.initializerOptions.inputs.inputs.map((inp, index) => {
return (
<div className="mb-2" key={index}>
<label className='mt-2 text-left d-block' htmlFor={inp.name}> {inp.name}: </label>
<input ref={el => { initializeFields.current[index] = el }} style={{ height: 32 }} className="form-control udapp_input" placeholder={inp.type} title={inp.name} />
</div>
)})
}
</div>
</div> : null
}
<div className='d-flex justify-content-between'>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input
id="upgradeImplementation"
data-id="contractGUIUpgradeImplementation"
className="form-check-input custom-control-input"
type="checkbox"
onChange={handleUpgradeImpSelect}
checked={deployState.upgrade}
/>
<label
htmlFor="upgradeImplementation"
data-id="contractGUIUpgradeImplementationLabel"
className="m-0 form-check-label custom-control-label udapp_checkboxAlign"
title="The implemetation address will be updated to a new address in the proxy contract."
>
Upgrade Contract
</label>
</div>
<span onClick={handleToggleUpgradeImp}>
<i className={!toggleUpgradeImp ? 'fas fa-angle-right pt-2' : 'fas fa-angle-down'} aria-hidden="true"></i>
</span>
</div>
<div className={`pl-4 flex-column ${toggleUpgradeImp ? "d-flex" : "d-none"}`}>
<div className={`flex-column 'd-flex'}`}>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input
id="proxyAddress"
data-id="contractGUIProxyAddress"
className="form-check-input custom-control-input"
type="checkbox"
onChange={handleUseLastProxySelect}
checked={useLastProxy}
/>
<label
htmlFor="proxyAddress"
data-id="contractGUIProxyAddressLabel"
className="m-0 form-check-label custom-control-label udapp_checkboxAlign"
title="Select this option to use the last deployed ERC1967 contract on the current network."
style={{ fontSize: 12 }}
>
Use last deployed ERC1967 contract
</label>
</div>
{
!useLastProxy ?
<div className="mb-2">
<label className='mt-2 text-left d-block'>Proxy Address: </label>
<input style={{ height: 32 }} className="form-control udapp_input" placeholder='proxy address' title='Enter previously deployed proxy address on the selected network' onChange={handleSetProxyAddress} />
</div> :
<span className='text-capitalize'>{ shortenAddress(proxyAddress) || 'No proxy address available' }</span>
}
</div> </div>
</div> </div>
</> </> : null
} }
</div> </div>
) )

@ -1,6 +1,6 @@
import { CompilerAbstract } from '@remix-project/remix-solidity-ts' import { CompilerAbstract } from '@remix-project/remix-solidity-ts'
import { ContractData } from '@remix-project/core-plugin' import { ContractData } from '@remix-project/core-plugin'
import { DeployMode, DeployOption, DeployOptions } from '../types' import { DeployMode, DeployOptions } from '../types'
import { ADD_DEPLOY_OPTION, ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, FETCH_PROVIDER_LIST_FAILED, FETCH_PROVIDER_LIST_REQUEST, FETCH_PROVIDER_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_DEPLOY_OPTION, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_TX_FEE_CONTENT } from '../constants' import { ADD_DEPLOY_OPTION, ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, FETCH_PROVIDER_LIST_FAILED, FETCH_PROVIDER_LIST_REQUEST, FETCH_PROVIDER_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_DEPLOY_OPTION, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_TX_FEE_CONTENT } from '../constants'
import Web3 from 'web3' import Web3 from 'web3'

@ -219,7 +219,7 @@ export interface Modal {
cancelFn: () => void cancelFn: () => void
} }
export type DeployMode = 'Deploy with Proxy' | 'Upgrade Proxy' export type DeployMode = 'Deploy with Proxy' | 'Upgrade Contract'
export type DeployOption = { export type DeployOption = {
initializeInputs: string, initializeInputs: string,

Loading…
Cancel
Save