Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recognize and parse logs of a proxy contract #1256

Open
Keith-CY opened this issue Jan 4, 2023 · 11 comments
Open

Recognize and parse logs of a proxy contract #1256

Keith-CY opened this issue Jan 4, 2023 · 11 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@Keith-CY
Copy link
Member

Keith-CY commented Jan 4, 2023

Contract: https://v1.gwscan.com/account/0x6baefb2f6ecfb912eb0b5791a691c0af63ac6e85?tab=contract

ABI

[
  {
    "inputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "ProxyOwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "implementation",
        "type": "address"
      }
    ],
    "name": "Upgraded",
    "type": "event"
  },
  {
    "payable": true,
    "stateMutability": "payable",
    "type": "fallback"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "implementation",
    "outputs": [
      {
        "internalType": "address",
        "name": "impl",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "proxyOwner",
    "outputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferProxyOwnership",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "implementation",
        "type": "address"
      }
    ],
    "name": "upgradeTo",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "implementation",
        "type": "address"
      },
      {
        "internalType": "bytes",
        "name": "data",
        "type": "bytes"
      }
    ],
    "name": "upgradeToAndCall",
    "outputs": [],
    "payable": true,
    "stateMutability": "payable",
    "type": "function"
  }
]

Log

  {
    "address": "0x6baefb2f6ecfb912eb0b5791a691c0af63ac6e85",
    "blockHash": "0x0611ba7e2c7bf060f51cb069694591867e30d6ee8feed4863e8d2913ba71c568",
    "blockNumber": "0x4f2b4",
    "transactionIndex": "0x1",
    "transactionHash": "0xfaf1c5d2b26ef26e16ce3e9266fe538b846af714f760b78298eddd8cbde39da2",
    "data": "0x0000000000000000000000000000000000000000000000003782dace9d900000",
    "logIndex": "0x1",
    "topics": [
      "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
      "0x000000000000000000000000fb2508a367cb370aafdde4ffd25b3f4d80c85381",
      "0x00000000000000000000000044bed1c83ba2e622d9cadafdabb0f9462adfff8a"
    ],
    "removed": false
  }

Parse Function

new ethers.utils.Interface(abi).parseLog(log)

Error message(printed in console on https://v1.gwscan.com/tx/0xfaf1c5d2b26ef26e16ce3e9266fe538b846af714f760b78298eddd8cbde39da2?tab=logs)

no matching event (argument="topichash", value="0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", code=INVALID_ARGUMENT, version=abi/5.7.0)
@Keith-CY Keith-CY added the bug Something isn't working label Jan 4, 2023
@Keith-CY Keith-CY added this to the 2023/01/04 - 2023/01/11 milestone Jan 4, 2023
@Keith-CY
Copy link
Member Author

Keith-CY commented Jan 4, 2023

The response of calling implementation method is 0x0278Fc024923b81df3E76960c978c429C2cfB28e(https://v1.gwscan.com/account/0x0278fc024923b81df3e76960c978c429c2cfb28e?tab=contract). It's the delegated contract address and its ABI is

[
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "delegator",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "fromDelegate",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "toDelegate",
        "type": "address"
      }
    ],
    "name": "DelegateChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "delegate",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "previousBalance",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newBalance",
        "type": "uint256"
      }
    ],
    "name": "DelegateVotesChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "Freezed",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "_from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "_to",
        "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": "amount",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "UnFreezed",
    "type": "event"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "DELEGATION_TYPEHASH",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "DOMAIN_TYPEHASH",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      }
    ],
    "name": "allowance",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "rawAmount",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "brnLp",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      },
      {
        "internalType": "uint32",
        "name": "",
        "type": "uint32"
      }
    ],
    "name": "checkpoints",
    "outputs": [
      {
        "internalType": "uint32",
        "name": "fromBlock",
        "type": "uint32"
      },
      {
        "internalType": "uint96",
        "name": "votes",
        "type": "uint96"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "delegatee",
        "type": "address"
      }
    ],
    "name": "delegate",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "delegatee",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "nonce",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "expiry",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "delegateBySig",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "delegates",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [],
    "name": "freeze",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "getCurrentVotes",
    "outputs": [
      {
        "internalType": "uint96",
        "name": "",
        "type": "uint96"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "blockNumber",
        "type": "uint256"
      }
    ],
    "name": "getPriorVotes",
    "outputs": [
      {
        "internalType": "uint96",
        "name": "",
        "type": "uint96"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "initializer",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "isLpWhitelistRequired",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "lpWhitelist",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "nonces",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "numCheckpoints",
    "outputs": [
      {
        "internalType": "uint32",
        "name": "",
        "type": "uint32"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "_brnLp",
        "type": "address"
      }
    ],
    "name": "setBrnLpAddress",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "bool",
        "name": "status",
        "type": "bool"
      }
    ],
    "name": "setIsLpWhitelistRequired",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "addr",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "status",
        "type": "bool"
      }
    ],
    "name": "setLpWhitelist",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "dst",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "rawAmount",
        "type": "uint256"
      }
    ],
    "name": "transfer",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "src",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "dst",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "rawAmount",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [],
    "name": "unfreeze",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
  }
]

which could be used to parse logs of 0x6baefb2f6ecfb912eb0b5791a691c0af63ac6e85

Maybe we should add a function to recognize and parse logs of a proxy contract

@Keith-CY Keith-CY added documentation Improvements or additions to documentation and removed bug Something isn't working labels Jan 4, 2023
@Keith-CY Keith-CY self-assigned this Jan 4, 2023
@Keith-CY Keith-CY changed the title Check ABI of contract 0x6baefb2f6ecfb912eb0b5791a691c0af63ac6e85 on mainnet Recognize and parse logs of a proxy contract Jan 4, 2023
@Keith-CY Keith-CY moved this from Todo to In Progress in Nervos Wallet/Explorer Jan 9, 2023
@Keith-CY Keith-CY removed this from the 2023/01/04 - 2023/01/11 milestone Jan 9, 2023
@zmcNotafraid
Copy link
Member

Proxy contract workflow:

  1. Find contract that has implemention abi
  2. Query the proxy contract address and query the proxy contract abi merge into current contract
  3. Use the merged abi parse data

blockscout/blockscout#3153

@zmcNotafraid zmcNotafraid self-assigned this Jan 29, 2023
@zmcNotafraid zmcNotafraid moved this from In Progress to QA in Nervos Wallet/Explorer Feb 1, 2023
@zmcNotafraid zmcNotafraid linked a pull request Feb 2, 2023 that will close this issue
@zmcNotafraid
Copy link
Member

For SmartContract grapqh field, we add below four field

 implementation_name: string
 implementation_fetched_at: datetime
 implementation_address_hash: address
 implementation_abi: list json

So if the proxy smart contract have implementation_address_hash value. You can query it's implementation contract's abi by

query {
      smart_contract(
        input: { contract_address: "0xbFE9D9Da5D5AD0f79B0cC7800a685Fc87cAe2884" }
      ) {
       implementation_abi
      }
    }

@Keith-CY
Copy link
Member Author

Keith-CY commented Feb 3, 2023

Could you take over this feature design to deliver information of proxied contract on the proxy contract page @Danie0918

The goal of this feature is to ameliorate the workflow of viewing a targeted contract.

The progress of calling a proxied contract is user -> tx -> proxy contract -> internal tx -> target contract, so the tx links to the proxy contract instead of the target contract, which executes the actual business.

With this feature, updates in the target contract are expected to be found easily.

@Danie0918
Copy link

Ok,I'll take it over after finfish the PRD of CKB Explorer.

@Danie0918 Danie0918 moved this to 🆕 New in Layer2 Explorer Feb 26, 2023
@Danie0918 Danie0918 self-assigned this Feb 28, 2023
@Danie0918 Danie0918 moved this from 🆕 New to 📌Planning in Layer2 Explorer Mar 1, 2023
@zmcNotafraid
Copy link
Member

zmcNotafraid commented Mar 6, 2023

  • both event logs
  • implementation contract erc20 transfer

@Keith-CY
Copy link
Member Author

Front-end PR: Magickbase/godwoken-explorer-ui#924

@Danie0918 Danie0918 moved this from 📌Planning to 🏗 In Progress in Layer2 Explorer Mar 13, 2023
@zmcNotafraid
Copy link
Member

  • proxy contract's event logs
    use /accounts/implementation_address_hash/logs api
  • proxy contract's erc20 records
query {
  token_transfers(
        input: {
          to_address: implementation_address_hash
    }
 }

@zmcNotafraid zmcNotafraid linked a pull request Mar 15, 2023 that will close this issue
@zmcNotafraid zmcNotafraid removed a link to a pull request Mar 15, 2023
@zmcNotafraid zmcNotafraid moved this from 🏗 In Progress to 👀 Testing in Layer2 Explorer Mar 16, 2023
@Keith-CY
Copy link
Member Author

  • proxy contract's event logs
    use /accounts/implementation_address_hash/logs api
  • proxy contract's erc20 records
query {
  token_transfers(
        input: {
          to_address: implementation_address_hash
    }
 }

Will /accounts/implementation_address_hash/logs only return logs trigger by proxy contract instead of all logs emitted by implementation contract?

I ask this because /account/{address}/logs is expected to fetch all logs of an account before.

@zmcNotafraid
Copy link
Member

  • proxy contract's event logs
    use /accounts/implementation_address_hash/logs api
  • proxy contract's erc20 records
query {
  token_transfers(
        input: {
          to_address: implementation_address_hash
    }
 }

Will /accounts/implementation_address_hash/logs only return logs trigger by proxy contract instead of all logs emitted by implementation contract?

I ask this because /account/{address}/logs is expected to fetch all logs of an account before.

Can we use graphql api instead of this json api.

@Danie0918 Danie0918 moved this from 👀 Testing to 📫Hold On in Layer2 Explorer Mar 27, 2023
@Danie0918
Copy link

Due to the workload of interface adjustment exceeding expectations, the development and joint debugging work is suspended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
Status: 📫Hold On
Development

Successfully merging a pull request may close this issue.

4 participants