Add proxy inputs to VerifyView

pull/5285/head
Manuel Wedler 4 months ago committed by Aniket
parent 215a8c3b77
commit 78bea24433
  1. 28
      apps/contract-verification/src/app/components/AccordionReceipt.tsx
  2. 22
      apps/contract-verification/src/app/types/VerificationTypes.ts
  3. 18
      apps/contract-verification/src/app/views/VerifyView.tsx

@ -1,10 +1,10 @@
import React, { useMemo } from 'react'
import { SubmittedContract, SubmittedProxyContract, isContract, isProxy } from '../types'
import { SubmittedContract } from '../types'
import { shortenAddress, CustomTooltip } from '@remix-ui/helper'
import { AppContext } from '../AppContext'
interface AccordionReceiptProps {
contract: SubmittedContract | SubmittedProxyContract
contract: SubmittedContract
index: number
}
@ -13,11 +13,8 @@ export const AccordionReceipt: React.FC<AccordionReceiptProps> = ({ contract, in
const [expanded, setExpanded] = React.useState(false)
const address = isProxy(contract) ? contract.implementation.address : contract.address
const chainName = useMemo(() => {
const chainId = isProxy(contract) ? contract.implementation.chainId : contract.chainId
return chains.find((chain) => chain.chainId === parseInt(chainId))?.name ?? 'Unknown Chain'
return chains.find((chain) => chain.chainId === parseInt(contract.chainId))?.name ?? 'Unknown Chain'
}, [contract, chains])
const toggleAccordion = () => {
@ -25,21 +22,21 @@ export const AccordionReceipt: React.FC<AccordionReceiptProps> = ({ contract, in
}
return (
<div key={address + '-' + index} className="bg-secondary p-3 accordion-item" id={address + '-accordion-' + index}>
<div key={contract.address + '-' + index} className="bg-secondary p-3 accordion-item" id={contract.address + '-accordion-' + index}>
<h3 className="accordion-header" id={`heading${index}`}>
<button className="accordion-button d-flex flex-row align-items-center text-left w-100 border-0" type="button" onClick={toggleAccordion} aria-expanded={expanded} aria-controls={`collapse${index}`}>
<span className={`accordion-arrow ${expanded ? 'fa-angle-down' : 'fa-angle-right'} fa w-0`} style={{ width: '0' }}></span>
<span className="pl-4" style={{ fontSize: '1rem' }}>
<CustomTooltip tooltipText={address}>
<span>{shortenAddress(address)}</span>
<CustomTooltip tooltipText={contract.address}>
<span>{shortenAddress(contract.address)}</span>
</CustomTooltip>{' '}
on {chainName} {isProxy(contract) ? 'with proxy' : ''}
on {chainName} {contract.proxyAddress ? 'with proxy' : ''}
</span>
</button>
</h3>
<div id={`collapse${index}`} className={`accordion-collapse p-2 collapse ${expanded ? 'show' : ''}`} aria-labelledby={`heading${index}`} data-bs-parent="#receiptsAccordion">
<div className="accordion-body">
{isContract(contract) ? (
{!contract.proxyAddress ? (
<ReceiptsBody contract={contract}></ReceiptsBody>
) : (
<>
@ -47,16 +44,17 @@ export const AccordionReceipt: React.FC<AccordionReceiptProps> = ({ contract, in
<span className="font-weight-bold" style={{ fontSize: '1.2rem' }}>
Implementation
</span>
<ReceiptsBody contract={contract.implementation}></ReceiptsBody>
<ReceiptsBody contract={contract}></ReceiptsBody>
</div>
<div className="mt-3">
<span className="font-weight-bold" style={{ fontSize: '1.2rem' }}>
Proxy
</span>{' '}
<CustomTooltip tooltipText={contract.proxy.address}>
<span>{shortenAddress(contract.proxy.address)}</span>
<CustomTooltip tooltipText={contract.proxyAddress}>
<span>{shortenAddress(contract.proxyAddress)}</span>
</CustomTooltip>
<ReceiptsBody contract={contract.proxy}></ReceiptsBody>
{/* TODO add body for proxies */}
{/* <ReceiptsBody contract={contract.proxy}></ReceiptsBody> */}
</div>
</>
)}

@ -31,10 +31,10 @@ export interface VerificationReceipt {
status: VerificationStatus
message?: string
contractId: string
isProxyReceipt: boolean
}
export interface SubmittedContract {
type: 'contract'
id: string
filePath: string
contractName: string
@ -43,30 +43,16 @@ export interface SubmittedContract {
abiEncodedConstructorArgs?: string
date: string
receipts: VerificationReceipt[]
}
export interface SubmittedProxyContract {
type: 'proxy'
id: string
implementation: SubmittedContract
proxy: SubmittedContract
// Only present if the contract is behind a proxy
proxyAddress?: string
proxyReceipts?: VerificationReceipt[]
}
// This and all nested subtypes should be pure interfaces, so they can be converted to JSON easily
export interface SubmittedContracts {
// TODO implement Proxy verification
// [id: string]: SubmittedContract | SubmittedProxyContract
[id: string]: SubmittedContract
}
export function isProxy(contract: SubmittedContract | SubmittedProxyContract): contract is SubmittedProxyContract {
return contract.type === 'proxy'
}
export function isContract(contract: SubmittedContract | SubmittedProxyContract): contract is SubmittedContract {
return contract.type === 'contract'
}
type SourcifyStatus = 'fully verified' | 'partially verified'
type EtherscanStatus = 'verified'
export type VerificationStatus = SourcifyStatus | EtherscanStatus | 'failed' | 'pending' | 'not verified' | 'unknown' | 'lookup failed'

@ -20,11 +20,14 @@ export const VerifyView = () => {
const [abiEncodingError, setAbiEncodingError] = useState<string>('')
const [selectedContract, setSelectedContract] = useState<ContractDropdownSelection | undefined>()
const [enabledVerifiers, setEnabledVerifiers] = useState<Partial<Record<VerifierIdentifier, boolean>>>({})
const [hasProxy, setHasProxy] = useState(false)
const [proxyAddress, setProxyAddress] = useState('')
const [proxyAddressError, setProxyAddressError] = useState('')
const navigate = useNavigate()
const chainSettings = selectedChain ? mergeChainSettingsWithDefaults(selectedChain.chainId.toString(), settings) : undefined
const submitDisabled = !!contractAddressError || !contractAddress || !selectedChain || !selectedContract
const submitDisabled = !!contractAddressError || !contractAddress || !selectedChain || !selectedContract || (hasProxy && !!proxyAddressError) || (hasProxy && !proxyAddress)
// Enable all verifiers with valid configuration
useEffect(() => {
@ -62,11 +65,10 @@ export const VerifyView = () => {
apiUrl: chainSettings.verifiers[verifierId].apiUrl,
name: verifierId as VerifierIdentifier,
}
receipts.push({ verifierInfo, status: 'pending', contractId })
receipts.push({ verifierInfo, status: 'pending', contractId, isProxyReceipt: false })
}
const newSubmittedContract: SubmittedContract = {
type: 'contract',
id: contractId,
address: contractAddress,
chainId: selectedChain?.chainId.toString(),
@ -116,7 +118,15 @@ export const VerifyView = () => {
{selectedContract && <ConstructorArguments abiEncodedConstructorArgs={abiEncodedConstructorArgs} setAbiEncodedConstructorArgs={setAbiEncodedConstructorArgs} selectedContract={selectedContract} abiEncodingError={abiEncodingError} setAbiEncodingError={setAbiEncodingError} />}
<div>
<div className="pt-3 form-check form-switch">
<input className="form-check-input" type="checkbox" id="has-proxy" checked={!!hasProxy} onChange={(e) => setHasProxy(e.target.checked)} />
<label className="form-check-label" htmlFor="has-proxy">
The deployed contract is behind a proxy
</label>
{hasProxy && <ContractAddressInput label="Proxy Address" id="proxy-address" contractAddress={proxyAddress} setContractAddress={setProxyAddress} contractAddressError={proxyAddressError} setContractAddressError={setProxyAddressError} />}
</div>
<div className="pt-3">
Verify on:
{VERIFIERS.map((verifierId) => {
return (

Loading…
Cancel
Save