scaffold-eth / scaffold-eth-2

Open source forkable Ethereum dev stack
https://scaffoldeth.io
MIT License
1.41k stars 887 forks source link

fix: debug page for different contracts on different chains #920

Closed rin-st closed 2 months ago

rin-st commented 2 months ago

Description

Fixes debug page in case where the app uses different contracts on different chains

Before: https://github.com/user-attachments/assets/b68a96d9-25cd-4c8e-b473-3964a8146377

After: https://github.com/user-attachments/assets/47e5f585-b9e4-4288-8d7b-7810fa4c513a

Additional Information

mertcanciy commented 2 months ago

I had that problem and I tried the new code @rin-st . It worked great!

technophile-04 commented 2 months ago

Tysm @rin-st! I think this is great! Initially I had really small concern in my heart that we probably will be confusing the user of SE-2 that although they are able to see and tinker with different contracts on debug page but when using custom hooks they are limited to only using contracts from 0th chain.

^ Umm but I think since debug contracts is already dynamic and easy to get it working with contracts on all chain probably we should go for also its just limitation of custom hooks but if people use wagmi plain hook they should be able to get it working.


I think I found a small bug, to reproduce change targetNetworks: [chains.hardhat, chains.sepolia] and then copy this :

`deployedContract.ts` : ```shell /** * This file is autogenerated by Scaffold-ETH. * You should not edit it manually or your changes might be overwritten. */ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; const deployedContracts = { 31337: { YourContract: { address: "0x5FbDB2315678afecb367f032d93F642f64180aa3", abi: [ { inputs: [ { internalType: "address", name: "_owner", type: "address", }, ], stateMutability: "nonpayable", type: "constructor", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "greetingSetter", type: "address", }, { indexed: false, internalType: "string", name: "newGreeting", type: "string", }, { indexed: false, internalType: "bool", name: "premium", type: "bool", }, { indexed: false, internalType: "uint256", name: "value", type: "uint256", }, ], name: "GreetingChange", type: "event", }, { inputs: [], name: "greeting", outputs: [ { internalType: "string", name: "", type: "string", }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "owner", outputs: [ { internalType: "address", name: "", type: "address", }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "premium", outputs: [ { internalType: "bool", name: "", type: "bool", }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "string", name: "_newGreeting", type: "string", }, ], name: "setGreeting", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [], name: "totalCounter", outputs: [ { internalType: "uint256", name: "", type: "uint256", }, ], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "", type: "address", }, ], name: "userGreetingCounter", outputs: [ { internalType: "uint256", name: "", type: "uint256", }, ], stateMutability: "view", type: "function", }, { inputs: [], name: "withdraw", outputs: [], stateMutability: "nonpayable", type: "function", }, { stateMutability: "payable", type: "receive", }, ], inheritedFunctions: {}, }, }, 11155111: { YourContract: { address: "0x0D25b202D1B5126ECFcaeFa85f7a37ed86EF79ea", abi: [ { inputs: [{ internalType: "address", name: "_owner", type: "address" }], stateMutability: "nonpayable", type: "constructor", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "greetingSetter", type: "address" }, { indexed: false, internalType: "string", name: "newGreeting", type: "string" }, { indexed: false, internalType: "bool", name: "premium", type: "bool" }, { indexed: false, internalType: "uint256", name: "value", type: "uint256" }, ], name: "GreetingChange", type: "event", }, { inputs: [], name: "greeting", outputs: [{ internalType: "string", name: "", type: "string" }], stateMutability: "view", type: "function", }, { inputs: [], name: "owner", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [], name: "premium", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "string", name: "_newGreeting", type: "string" }], name: "setGreeting", outputs: [], stateMutability: "payable", type: "function", }, { inputs: [], name: "totalCounter", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "", type: "address" }], name: "userGreetingCounter", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "withdraw", outputs: [], stateMutability: "nonpayable", type: "function" }, { stateMutability: "payable", type: "receive" }, ], }, }, } as const; export default deployedContracts satisfies GenericContractsDeclaration; ```
`externalContracts.ts` ```shell import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; /** * @example * const externalContracts = { * 1: { * DAI: { * address: "0x...", * abi: [...], * }, * }, * } as const; */ const externalContracts = { 11155111: { DAI: { address: "0x68194a729C2450ad26072b3D33ADaCbcef39D574", abi: [ { inputs: [ { internalType: "string", name: "name", type: "string" }, { internalType: "string", name: "symbol", type: "string" }, { internalType: "uint8", name: "decimals", type: "uint8" }, { internalType: "address", name: "owner", type: "address" }, ], stateMutability: "nonpayable", type: "constructor", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "owner", type: "address" }, { indexed: true, internalType: "address", name: "spender", type: "address" }, { indexed: false, internalType: "uint256", name: "value", type: "uint256" }, ], name: "Approval", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "previousOwner", type: "address" }, { indexed: true, internalType: "address", name: "newOwner", type: "address" }, ], name: "OwnershipTransferred", type: "event", }, { anonymous: false, inputs: [ { indexed: true, internalType: "address", name: "from", type: "address" }, { indexed: true, internalType: "address", name: "to", type: "address" }, { indexed: false, internalType: "uint256", name: "value", type: "uint256" }, ], name: "Transfer", type: "event", }, { inputs: [], name: "DOMAIN_SEPARATOR", outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], stateMutability: "view", type: "function", }, { inputs: [], name: "EIP712_REVISION", outputs: [{ internalType: "bytes", name: "", type: "bytes" }], stateMutability: "view", type: "function", }, { inputs: [], name: "PERMIT_TYPEHASH", outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "owner", type: "address" }, { internalType: "address", name: "spender", type: "address" }, ], name: "allowance", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "spender", type: "address" }, { internalType: "uint256", name: "amount", type: "uint256" }, ], name: "approve", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "address", name: "account", type: "address" }], name: "balanceOf", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "decimals", outputs: [{ internalType: "uint8", name: "", type: "uint8" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "spender", type: "address" }, { internalType: "uint256", name: "subtractedValue", type: "uint256" }, ], name: "decreaseAllowance", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "spender", type: "address" }, { internalType: "uint256", name: "addedValue", type: "uint256" }, ], name: "increaseAllowance", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "account", type: "address" }, { internalType: "uint256", name: "value", type: "uint256" }, ], name: "mint", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "uint256", name: "value", type: "uint256" }], name: "mint", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "name", outputs: [{ internalType: "string", name: "", type: "string" }], stateMutability: "view", type: "function", }, { inputs: [{ internalType: "address", name: "owner", type: "address" }], name: "nonces", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [], name: "owner", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "owner", type: "address" }, { internalType: "address", name: "spender", type: "address" }, { internalType: "uint256", name: "value", type: "uint256" }, { internalType: "uint256", name: "deadline", type: "uint256" }, { internalType: "uint8", name: "v", type: "uint8" }, { internalType: "bytes32", name: "r", type: "bytes32" }, { internalType: "bytes32", name: "s", type: "bytes32" }, ], name: "permit", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "renounceOwnership", outputs: [], stateMutability: "nonpayable", type: "function" }, { inputs: [], name: "symbol", outputs: [{ internalType: "string", name: "", type: "string" }], stateMutability: "view", type: "function", }, { inputs: [], name: "totalSupply", outputs: [{ internalType: "uint256", name: "", type: "uint256" }], stateMutability: "view", type: "function", }, { inputs: [ { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "amount", type: "uint256" }, ], name: "transfer", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "address", name: "sender", type: "address" }, { internalType: "address", name: "recipient", type: "address" }, { internalType: "uint256", name: "amount", type: "uint256" }, ], name: "transferFrom", outputs: [{ internalType: "bool", name: "", type: "bool" }], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "address", name: "newOwner", type: "address" }], name: "transferOwnership", outputs: [], stateMutability: "nonpayable", type: "function", }, ], }, TEST: { address: "0x5f5a404A5edabcDD80DB05E8e54A78c9EBF000C2", abi: [ { inputs: [{ internalType: "address", name: "_owner", type: "address" }], stateMutability: "nonpayable", type: "constructor", }, { stateMutability: "payable", type: "fallback" }, { inputs: [], name: "getImplementation", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "nonpayable", type: "function", }, { inputs: [], name: "getOwner", outputs: [{ internalType: "address", name: "", type: "address" }], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "bytes", name: "_code", type: "bytes" }], name: "setCode", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [{ internalType: "address", name: "_owner", type: "address" }], name: "setOwner", outputs: [], stateMutability: "nonpayable", type: "function", }, { inputs: [ { internalType: "bytes32", name: "_key", type: "bytes32" }, { internalType: "bytes32", name: "_value", type: "bytes32" }, ], name: "setStorage", outputs: [], stateMutability: "nonpayable", type: "function", }, { stateMutability: "payable", type: "receive" }, ], }, }, } as const; export default externalContracts satisfies GenericContractsDeclaration; ```
This branch: https://github.com/user-attachments/assets/ba255fc4-a0be-4387-92a3-5baa7fe6d0a3 Notice I get two error notification when I switch chain.
On main branch it doesn't give that errors: https://github.com/user-attachments/assets/875603f6-e5b8-4002-a0de-cb5333671487

Also probably when there are are contracts on multiple chains, we should probably show a networks dropdown somewhere which people can switch and see the contracts on other chain if not connected (since read works out of the box without needing to connect wallet) an example:

https://github.com/user-attachments/assets/44d3e2a3-1bb8-4f07-b22d-3a5f098f165e

Happy to push the code for this if it makes sense 🙌

rin-st commented 2 months ago

I think I found a small bug, to reproduce change

https://github.com/user-attachments/assets/a60397ac-4ddc-4ae8-bc5d-b4fab4675f9c

It doesn't work for me. Also notice that there's no error when you added dropdown (possibly because wallet is not connected)

Happy to push the code for this if it makes sense 🙌

Sure! Thank you!