From dcc121ccc2599458bd1fbc3bf072d983a719109f Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 21 Jul 2021 01:23:44 -0300 Subject: [PATCH 1/6] Add contract creation display on transaction details page --- src/Transaction.tsx | 1 + src/components/DecoratedAddressLink.tsx | 8 ++++++ src/transaction/Details.tsx | 35 +++++++++++++++++-------- src/types.ts | 1 + 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/Transaction.tsx b/src/Transaction.tsx index ce564f9..d46f501 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -88,6 +88,7 @@ const Transaction: React.FC = () => { miner: _block.miner, from: _receipt.from, to: _receipt.to, + createdContractAddress: _receipt.contractAddress, value: _response.value, tokenTransfers, tokenMetas, diff --git a/src/components/DecoratedAddressLink.tsx b/src/components/DecoratedAddressLink.tsx index 6d58bf5..e39715c 100644 --- a/src/components/DecoratedAddressLink.tsx +++ b/src/components/DecoratedAddressLink.tsx @@ -1,6 +1,7 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { + faStar, faMoneyBillAlt, faBurn, faCoins, @@ -15,6 +16,7 @@ type DecoratedAddressLinkProps = { selectedAddress?: string; text?: string; addressCtx?: AddressContext; + creation?: boolean; miner?: boolean; selfDestruct?: boolean; txFrom?: boolean; @@ -28,6 +30,7 @@ const DecoratedAddresssLink: React.FC = ({ selectedAddress, text, addressCtx, + creation, miner, selfDestruct, txFrom, @@ -45,6 +48,11 @@ const DecoratedAddresssLink: React.FC = ({ burn ? "line-through text-orange-500 hover:text-orange-700" : "" } ${selfDestruct ? "line-through opacity-70 hover:opacity-100" : ""}`} > + {creation && ( + + + + )} {mint && ( diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index 7d18098..7130f45 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -73,17 +73,30 @@ const Details: React.FC = ({ - -
- - - - -
+ + {txData.to ? ( +
+ + + + +
+ ) : ( +
+ + + + +
+ )} {internalTransfers && (
{internalTransfers.map((t, i) => ( diff --git a/src/types.ts b/src/types.ts index 29cc6bc..5b7dbc1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -44,6 +44,7 @@ export type TransactionData = { miner?: string; from: string; to: string; + createdContractAddress?: string; value: BigNumber; tokenTransfers: TokenTransfer[]; tokenMetas: TokenMetas; From b8fcc8914dae77b50b042b4f47ed4ba6d7896bae Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 21 Jul 2021 01:42:49 -0300 Subject: [PATCH 2/6] Show contract creation on search results --- src/search/TransactionItem.tsx | 20 ++++++++++++++++++-- src/search/search.ts | 1 + src/types.ts | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index 6d78f7e..bc84a6c 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -35,7 +35,10 @@ const TransactionItem: React.FC = ({ direction = Direction.SELF; } else if (tx.from === selectedAddress) { direction = Direction.OUT; - } else if (tx.to === selectedAddress) { + } else if ( + tx.to === selectedAddress || + tx.createdContractAddress === selectedAddress + ) { direction = Direction.IN; } else { direction = Direction.INTERNAL; @@ -44,6 +47,10 @@ const TransactionItem: React.FC = ({ const ensFrom = ensCache && tx.from && ensCache[tx.from]; const ensTo = ensCache && tx.to && ensCache[tx.to]; + const ensCreated = + ensCache && + tx.createdContractAddress && + ensCache[tx.createdContractAddress]; const flash = tx.gasPrice.isZero() && tx.internalMinerInteraction; return ( @@ -89,7 +96,7 @@ const TransactionItem: React.FC = ({ - {tx.to && ( + {tx.to ? ( = ({ miner={tx.miner === tx.to} /> + ) : ( + + + )} diff --git a/src/search/search.ts b/src/search/search.ts index a78eb81..e2d96c7 100644 --- a/src/search/search.ts +++ b/src/search/search.ts @@ -45,6 +45,7 @@ export class SearchController { hash: t.hash, from: t.from, to: t.to, + createdContractAddress: _receipt.contractAddress, value: t.value, fee: _receipt.gasUsed.mul(t.gasPrice!), gasPrice: t.gasPrice!, diff --git a/src/types.ts b/src/types.ts index 5b7dbc1..4c07826 100644 --- a/src/types.ts +++ b/src/types.ts @@ -16,6 +16,7 @@ export type ProcessedTransaction = { hash: string; from?: string; to?: string; + createdContractAddress?: string; internalMinerInteraction?: boolean; value: BigNumber; fee: BigNumber; From 61eef31a9309c0a17e033cebbc46f1c1565c0ba0 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 21 Jul 2021 01:46:10 -0300 Subject: [PATCH 3/6] Add contract creation display on block transactions list --- src/BlockTransactions.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index 8ded619..5eed574 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -57,6 +57,7 @@ const BlockTransactions: React.FC = () => { hash: t.hash, from: t.from, to: t.to, + createdContractAddress: _receipts[i].contractAddress, value: t.value, fee: provider.formatter .bigNumber(_receipts[i].gasUsed) From cf1c23dfa82ac5366f7caa7e014c3d43380122d1 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 21 Jul 2021 15:13:18 -0300 Subject: [PATCH 4/6] Add contract creation tracing --- src/components/InternalCreate.tsx | 46 ++++++++++++++++++++++++++++ src/components/InternalOperation.tsx | 5 +++ src/types.ts | 2 ++ 3 files changed, 53 insertions(+) create mode 100644 src/components/InternalCreate.tsx diff --git a/src/components/InternalCreate.tsx b/src/components/InternalCreate.tsx new file mode 100644 index 0000000..e6291a4 --- /dev/null +++ b/src/components/InternalCreate.tsx @@ -0,0 +1,46 @@ +import React, { useContext } from "react"; +import { ethers } from "ethers"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faAngleRight, faBomb } from "@fortawesome/free-solid-svg-icons"; +import AddressHighlighter from "./AddressHighlighter"; +import DecoratedAddressLink from "./DecoratedAddressLink"; +import { TransactionData, Transfer } from "../types"; + +type InternalCreateProps = { + txData: TransactionData; + transfer: Transfer; +}; + +const InternalCreate: React.FC = ({ + txData, + transfer, +}) => { + return ( + <> +
+ + CREATE + + Contract +
+ + + +
+ + (Creator:{" "} + + + + ) + +
+ + ); +}; + +export default React.memo(InternalCreate); diff --git a/src/components/InternalOperation.tsx b/src/components/InternalOperation.tsx index 0ae0a38..e0abee4 100644 --- a/src/components/InternalOperation.tsx +++ b/src/components/InternalOperation.tsx @@ -1,6 +1,7 @@ import React from "react"; import InternalTransfer from "./InternalTransfer"; import InternalSelfDestruct from "./InternalSelfDestruct"; +import InternalCreate from "./InternalCreate"; import { TransactionData, Transfer, TransferType } from "../types"; type InternalOperationProps = { @@ -19,6 +20,10 @@ const InternalOperation: React.FC = ({ {transfer.type === TransferType.SELF_DESTRUCT && ( )} + {(transfer.type === TransferType.CREATE || + transfer.type === TransferType.CREATE2) && ( + + )} ); diff --git a/src/types.ts b/src/types.ts index 4c07826..104a722 100644 --- a/src/types.ts +++ b/src/types.ts @@ -75,6 +75,8 @@ export type From = { export enum TransferType { TRANSFER = 0, SELF_DESTRUCT = 1, + CREATE = 2, + CREATE2 = 3, } export type Transfer = { From 9b957d8d20587202d35c10dce463421e136de608 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 21 Jul 2021 16:06:51 -0300 Subject: [PATCH 5/6] Rename jsonrpc method --- src/Transaction.tsx | 12 ++++---- src/components/InternalCreate.tsx | 23 +++++++------- src/components/InternalOperation.tsx | 30 ------------------- src/components/InternalSelfDestruct.tsx | 24 +++++++-------- .../InternalTransactionOperation.tsx | 28 +++++++++++++++++ src/components/InternalTransfer.tsx | 28 ++++++++--------- src/nodeFunctions.ts | 8 ++--- src/transaction/Details.tsx | 18 ++++++----- src/types.ts | 6 ++-- src/useErigonHooks.ts | 12 ++++---- 10 files changed, 95 insertions(+), 94 deletions(-) delete mode 100644 src/components/InternalOperation.tsx create mode 100644 src/components/InternalTransactionOperation.tsx diff --git a/src/Transaction.tsx b/src/Transaction.tsx index d46f501..55de7ac 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -10,7 +10,7 @@ import erc20 from "./erc20.json"; import { TokenMetas, TokenTransfer, TransactionData } from "./types"; import { RuntimeContext } from "./useRuntime"; import { SelectionContext, useSelection } from "./useSelection"; -import { useInternalTransfers } from "./useErigonHooks"; +import { useInternalOperations } from "./useErigonHooks"; const TRANSFER_TOPIC = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"; @@ -106,19 +106,19 @@ const Transaction: React.FC = () => { readBlock(); }, [provider, txhash]); - const intTransfers = useInternalTransfers(provider, txData); + const internalOps = useInternalOperations(provider, txData); const sendsEthToMiner = useMemo(() => { - if (!txData || !intTransfers) { + if (!txData || !internalOps) { return false; } - for (const t of intTransfers) { + for (const t of internalOps) { if (t.to === txData.miner) { return true; } } return false; - }, [txData, intTransfers]); + }, [txData, internalOps]); const selectionCtx = useSelection(); @@ -137,7 +137,7 @@ const Transaction: React.FC = () => {
diff --git a/src/components/InternalCreate.tsx b/src/components/InternalCreate.tsx index e6291a4..e048477 100644 --- a/src/components/InternalCreate.tsx +++ b/src/components/InternalCreate.tsx @@ -1,19 +1,18 @@ -import React, { useContext } from "react"; -import { ethers } from "ethers"; +import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faAngleRight, faBomb } from "@fortawesome/free-solid-svg-icons"; +import { faAngleRight } from "@fortawesome/free-solid-svg-icons"; import AddressHighlighter from "./AddressHighlighter"; import DecoratedAddressLink from "./DecoratedAddressLink"; -import { TransactionData, Transfer } from "../types"; +import { TransactionData, InternalOperation } from "../types"; type InternalCreateProps = { txData: TransactionData; - transfer: Transfer; + internalOp: InternalOperation; }; const InternalCreate: React.FC = ({ txData, - transfer, + internalOp, }) => { return ( <> @@ -23,17 +22,17 @@ const InternalCreate: React.FC = ({ Contract
- - + +
(Creator:{" "} - + ) diff --git a/src/components/InternalOperation.tsx b/src/components/InternalOperation.tsx deleted file mode 100644 index e0abee4..0000000 --- a/src/components/InternalOperation.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from "react"; -import InternalTransfer from "./InternalTransfer"; -import InternalSelfDestruct from "./InternalSelfDestruct"; -import InternalCreate from "./InternalCreate"; -import { TransactionData, Transfer, TransferType } from "../types"; - -type InternalOperationProps = { - txData: TransactionData; - transfer: Transfer; -}; - -const InternalOperation: React.FC = ({ - txData, - transfer, -}) => ( - <> - {transfer.type === TransferType.TRANSFER && ( - - )} - {transfer.type === TransferType.SELF_DESTRUCT && ( - - )} - {(transfer.type === TransferType.CREATE || - transfer.type === TransferType.CREATE2) && ( - - )} - -); - -export default React.memo(InternalOperation); diff --git a/src/components/InternalSelfDestruct.tsx b/src/components/InternalSelfDestruct.tsx index b717d38..6d83e3a 100644 --- a/src/components/InternalSelfDestruct.tsx +++ b/src/components/InternalSelfDestruct.tsx @@ -5,24 +5,24 @@ import { faAngleRight, faBomb } from "@fortawesome/free-solid-svg-icons"; import AddressHighlighter from "./AddressHighlighter"; import DecoratedAddressLink from "./DecoratedAddressLink"; import { RuntimeContext } from "../useRuntime"; -import { TransactionData, Transfer } from "../types"; +import { TransactionData, InternalOperation } from "../types"; const CHI_ADDRESS = "0x0000000000004946c0e9F43F4Dee607b0eF1fA1c"; const GST2_ADDRESS = "0x0000000000b3F879cb30FE243b4Dfee438691c04"; type InternalSelfDestructProps = { txData: TransactionData; - transfer: Transfer; + internalOp: InternalOperation; }; const InternalSelfDestruct: React.FC = ({ txData, - transfer, + internalOp, }) => { const { provider } = useContext(RuntimeContext); const network = provider?.network; - const toMiner = txData.miner !== undefined && transfer.to === txData.miner; + const toMiner = txData.miner !== undefined && internalOp.to === txData.miner; return ( <> @@ -35,32 +35,32 @@ const InternalSelfDestruct: React.FC = ({ Contract
- - + +
- {network?.chainId === 1 && transfer.to === CHI_ADDRESS && ( + {network?.chainId === 1 && internalOp.to === CHI_ADDRESS && ( (Chi Gastoken) )} - {network?.chainId === 1 && transfer.to === GST2_ADDRESS && ( + {network?.chainId === 1 && internalOp.to === GST2_ADDRESS && ( (GST2 Gastoken) )}
- {!transfer.value.isZero() && ( + {!internalOp.value.isZero() && (
TRANSFER - {ethers.utils.formatEther(transfer.value)} Ether + {ethers.utils.formatEther(internalOp.value)} Ether
To - +
- +
diff --git a/src/components/InternalTransactionOperation.tsx b/src/components/InternalTransactionOperation.tsx new file mode 100644 index 0000000..095162f --- /dev/null +++ b/src/components/InternalTransactionOperation.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import InternalTransfer from "./InternalTransfer"; +import InternalSelfDestruct from "./InternalSelfDestruct"; +import InternalCreate from "./InternalCreate"; +import { TransactionData, InternalOperation, OperationType } from "../types"; + +type InternalTransactionOperationProps = { + txData: TransactionData; + internalOp: InternalOperation; +}; + +const InternalTransactionOperation: React.FC = + ({ txData, internalOp }) => ( + <> + {internalOp.type === OperationType.TRANSFER && ( + + )} + {internalOp.type === OperationType.SELF_DESTRUCT && ( + + )} + {(internalOp.type === OperationType.CREATE || + internalOp.type === OperationType.CREATE2) && ( + + )} + + ); + +export default React.memo(InternalTransactionOperation); diff --git a/src/components/InternalTransfer.tsx b/src/components/InternalTransfer.tsx index d0ccbf2..90dd967 100644 --- a/src/components/InternalTransfer.tsx +++ b/src/components/InternalTransfer.tsx @@ -4,57 +4,57 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faAngleRight } from "@fortawesome/free-solid-svg-icons"; import AddressHighlighter from "./AddressHighlighter"; import DecoratedAddressLink from "./DecoratedAddressLink"; -import { TransactionData, Transfer } from "../types"; +import { TransactionData, InternalOperation } from "../types"; type InternalTransferProps = { txData: TransactionData; - transfer: Transfer; + internalOp: InternalOperation; }; const InternalTransfer: React.FC = ({ txData, - transfer, + internalOp, }) => { const fromMiner = - txData.miner !== undefined && transfer.from === txData.miner; - const toMiner = txData.miner !== undefined && transfer.to === txData.miner; + txData.miner !== undefined && internalOp.from === txData.miner; + const toMiner = txData.miner !== undefined && internalOp.to === txData.miner; return (
TRANSFER - {ethers.utils.formatEther(transfer.value)} Ether + {ethers.utils.formatEther(internalOp.value)} Ether
From - +
To - +
diff --git a/src/nodeFunctions.ts b/src/nodeFunctions.ts index 2cb5558..d160dac 100644 --- a/src/nodeFunctions.ts +++ b/src/nodeFunctions.ts @@ -1,15 +1,15 @@ import { ethers } from "ethers"; -import { TransactionData, Transfer } from "./types"; +import { TransactionData, InternalOperation } from "./types"; -export const getTransactionTransfers = async ( +export const getInternalOperations = async ( provider: ethers.providers.JsonRpcProvider, txData: TransactionData ) => { - const rawTransfers = await provider.send("ots_getTransactionTransfers", [ + const rawTransfers = await provider.send("ots_getInternalOperations", [ txData.transactionHash, ]); - const _transfers: Transfer[] = []; + const _transfers: InternalOperation[] = []; for (const t of rawTransfers) { _transfers.push({ type: t.type, diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index 7130f45..4204908 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -12,22 +12,22 @@ import AddressHighlighter from "../components/AddressHighlighter"; import DecoratedAddressLink from "../components/DecoratedAddressLink"; import Copy from "../components/Copy"; import Timestamp from "../components/Timestamp"; -import InternalOperation from "../components/InternalOperation"; +import InternalTransactionOperation from "../components/InternalTransactionOperation"; import MethodName from "../components/MethodName"; import GasValue from "../components/GasValue"; import FormattedBalance from "../components/FormattedBalance"; import TokenTransferItem from "../TokenTransferItem"; -import { TransactionData, Transfer } from "../types"; +import { TransactionData, InternalOperation } from "../types"; type DetailsProps = { txData: TransactionData; - internalTransfers?: Transfer[]; + internalOps?: InternalOperation[]; sendsEthToMiner: boolean; }; const Details: React.FC = ({ txData, - internalTransfers, + internalOps, sendsEthToMiner, }) => ( @@ -97,10 +97,14 @@ const Details: React.FC = ({
)} - {internalTransfers && ( + {internalOps && (
- {internalTransfers.map((t, i) => ( - + {internalOps.map((op, i) => ( + ))}
)} diff --git a/src/types.ts b/src/types.ts index 104a722..ac53edd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -72,15 +72,15 @@ export type From = { depth: number; }; -export enum TransferType { +export enum OperationType { TRANSFER = 0, SELF_DESTRUCT = 1, CREATE = 2, CREATE2 = 3, } -export type Transfer = { - type: TransferType; +export type InternalOperation = { + type: OperationType; from: string; to: string; value: BigNumber; diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index 447408c..50d4bf3 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -1,13 +1,13 @@ import { ethers } from "ethers"; import { useState, useEffect } from "react"; -import { getTransactionTransfers } from "./nodeFunctions"; -import { TransactionData, Transfer } from "./types"; +import { getInternalOperations } from "./nodeFunctions"; +import { TransactionData, InternalOperation } from "./types"; -export const useInternalTransfers = ( +export const useInternalOperations = ( provider: ethers.providers.JsonRpcProvider | undefined, txData: TransactionData | undefined -): Transfer[] | undefined => { - const [intTransfers, setIntTransfers] = useState(); +): InternalOperation[] | undefined => { + const [intTransfers, setIntTransfers] = useState(); useEffect(() => { const traceTransfers = async () => { @@ -15,7 +15,7 @@ export const useInternalTransfers = ( return; } - const _transfers = await getTransactionTransfers(provider, txData); + const _transfers = await getInternalOperations(provider, txData); for (const t of _transfers) { t.from = provider.formatter.address(t.from); t.to = provider.formatter.address(t.to); From 5b630e7757d27f49882d0e7cadb9ae5b0763e64a Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 21 Jul 2021 17:51:34 -0300 Subject: [PATCH 6/6] Change self-destruct address decoration --- src/components/DecoratedAddressLink.tsx | 6 ++++++ src/components/InternalSelfDestruct.tsx | 7 ++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/DecoratedAddressLink.tsx b/src/components/DecoratedAddressLink.tsx index e39715c..82d70f9 100644 --- a/src/components/DecoratedAddressLink.tsx +++ b/src/components/DecoratedAddressLink.tsx @@ -2,6 +2,7 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faStar, + faBomb, faMoneyBillAlt, faBurn, faCoins, @@ -53,6 +54,11 @@ const DecoratedAddresssLink: React.FC = ({ )} + {selfDestruct && ( + + + + )} {mint && ( diff --git a/src/components/InternalSelfDestruct.tsx b/src/components/InternalSelfDestruct.tsx index 6d83e3a..543b429 100644 --- a/src/components/InternalSelfDestruct.tsx +++ b/src/components/InternalSelfDestruct.tsx @@ -1,7 +1,7 @@ import React, { useContext } from "react"; import { ethers } from "ethers"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faAngleRight, faBomb } from "@fortawesome/free-solid-svg-icons"; +import { faAngleRight } from "@fortawesome/free-solid-svg-icons"; import AddressHighlighter from "./AddressHighlighter"; import DecoratedAddressLink from "./DecoratedAddressLink"; import { RuntimeContext } from "../useRuntime"; @@ -28,10 +28,7 @@ const InternalSelfDestruct: React.FC = ({ <>
- - - {" "} - SELF DESTRUCT + SELF DESTRUCT Contract