trufflesuite / truffle-debugger

Core functionality for debugging Solidity files built with Truffle
67 stars 12 forks source link

TypeError: Cannot read property 'context' of null #75

Open cmcewen opened 6 years ago

cmcewen commented 6 years ago

We are trying to debug a contract and receive this error every time we try to debug a transaction involving that contract, using both truffle debug and running a script that imports the debugger. The contracts were migrated with truffle migrate --reset --compile-all

redux-saga error: uncaught at session.saga
at session.saga
at recordInstance
TypeError: Cannot read property 'context' of null
   at Object.addInstance$ (/usr/local/lib/node_modules/truffle/build/webpack:/~/truffle-debugger/dist/debugger.js:5533:1)
   at tryCatch (/usr/local/lib/node_modules/truffle/build/webpack:/~/regenerator-runtime/runtime.js:62:15)
   at Generator.invoke [as _invoke] (/usr/local/lib/node_modules/truffle/build/webpack:/~/regenerator-runtime/runtime.js:296:1)
   at Generator.prototype.(anonymous function) [as next] (/usr/local/lib/node_modules/truffle/build/webpack:/~/regenerator-runtime/runtime.js:114:1)
   at tryCatch (/usr/local/lib/node_modules/truffle/build/webpack:/~/regenerator-runtime/runtime.js:62:15)
   at maybeInvokeDelegate (/usr/local/lib/node_modules/truffle/build/webpack:/~/regenerator-runtime/runtime.js:358:1)
   at Generator.invoke [as _invoke] (/usr/local/lib/node_modules/truffle/build/webpack:/~/regenerator-runtime/runtime.js:270:1)
   at Generator.prototype.(anonymous function) [as next] (/usr/local/lib/node_modules/truffle/build/webpack:/~/regenerator-runtime/runtime.js:114:1)
   at next (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:311:1)
   at currCb (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:388:1)
   at runSelectEffect (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:699:1)
   at runEffect (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:435:1)
   at next (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:315:1)
   at proc (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:270:1)
   at resolveIterator (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:456:1)
   at runCallEffect (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:517:1)
   at runEffect (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:435:1)
   at /usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:644:1
   at Array.forEach (<anonymous>)
   at runAllEffect (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:643:1)
   at runEffect (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:435:1)
   at next (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:315:1)
   at currCb (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:388:1)
   at checkEffectEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:612:1)
   at chCbAtKey (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:627:1)
   at Object.currCb [as cb] (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:388:1)
   at /usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:358:1
   at Array.forEach (<anonymous>)
   at end (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:357:1)
   at Object.task.cont (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:99:1)
   at next (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:321:1)
   at currCb (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:388:1)
   at takeCb (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/proc.js:466:1)
   at Object.put (/usr/local/lib/node_modules/truffle/build/webpack:/~/redux-saga/es/internal/channel.js:73:1)
Truffle v4.1.11 (core: 4.1.11)
Solidity v0.4.24 (solc-js)
roschler commented 6 years ago

@cgewecke and @gnidan

Hello Christopher and Nicholas,

TL;DR

I believe this problem occurs when there is a mismatch between a contract address and the ABI the Truffle console tries to apply during a method call against a deployed contract. My feeling is that it's going to boil down to providing a better error message when this occurs, assuming you can detect such a condition like the mismatch between a deployment image vs ABI problems. When I say mismatch I mean either because the wrong contract address is supplied by the user or there is a mismatch between the ABI and the deployed contract image (user forgot to re-compile, etc.)

Long version

NOTE: My current belief, perhaps due to my own lack of skill as a novice dApp/Solidity coder, is that it is not possible to debug ZeppelinOS proxy contracts using the Truffle console debug command.

The ZeppelinOS proxy contract tools sets up an environment where a "forward facing" contract passes on calls to the current logic contract (i.e. - implementation contract) using delegatecall. It also does some tricks using Assembly() to pass on the state variables using Soliditys raw memory slots. (E.g. - mload, calldatacopy, returndatacopy, etc.). You can see those contracts here:

https://github.com/zeppelinos/zos-lib/tree/development/contracts/upgradeability

To faciliate this discussion. Please look at the zos.network.json file below. This file is the record-keeping file that the ZOS client commands use to track the proxy-to-proxied-contract relationships active in an app and the changes that take place between them over time. Note the contracts.Basil.address, proxies.Basil.address, proxies.Basil.implementation, and app addresses:

{
  "contracts": {
    "Basil": {
      "address": "0x6ed79aa1c71fd7bdbc515efda3bd4e26394435cc",
      "bytecodeHash": "93e5232cedc10f89615de9b638a9a025dbd87a0e76127ee16695255bea4caf85"
    }
  },
  "proxies": {
    "Basil": [
      {
        "address": "0x4849038be95fe6e42da67c9edbe411709e9c6780",
        "version": "0.0.2",
        "implementation": "0x6ed79aa1c71fd7bdbc515efda3bd4e26394435cc"
      }
    ],
    "MintableERC721Token": [
      {
        "address": "0x5c4f7148f0bbc0328cb487f72b2ba71a30895a36",
        "version": "0.0.2",
        "implementation": "0xad888d0ade988ebee74b8d4f39bf29a8d0fe8a8d"
      }
    ]
  },
  "app": {
    "address": "0x67b5656d60a809915323bf2c40a8bef15a152e3e"
  },
  "version": "0.0.2",
  "package": {
    "address": "0x59d3631c86bbe35ef041872d502f218a39fba150"
  },
  "provider": {
    "address": "0x0e696947a06550def604e82c26fd9e493e576337"
  },
  "stdlib": {
    "address": "0x21a59654176f2689d12e828b77a783072cd26680",
    "customDeploy": true,
    "name": "openzeppelin-zos",
    "version": "1.9.1"
  }

For a while I was not getting the "context null" error and I recently figured out why. It's because I was passing the debug command the actual address of my proxied contract, not the address of the proxy entry point. This is actually a mistake of course because by doing this I was going around the proxy and going straight to the proxied contract, thus circumventing the proxy. However, this made the Truffle debug command happy since the ABI of the contract matched up with the contract executing the code the debug command was tracing through, given the Tx hash passed to the debug command.

The instant I switch to the proxy address and by that I mean either the app address or the proxies.Basil.address address I immediately get the "context null" error. This makes sense because the ABI of BasilERC721, the proxied contract, does not match those other addresses because they belong to different contract types. Therefore when I tried to debug the transaction using the following command, which uses the proxy "front end" address aka the app address the error occurs:

BasilERC721.at("0x67b5656d60a809915323bf2c40a8bef15a152e3e").emitOwnerDetails.sendTransaction({from: web3.eth.accounts[0], gas: 4200000});

I've attached the exact steps I follow to make this happen. When I say exact I mean exactly that since I've executed the steps a few hundred times now. The document attached is my revision of the ZeppelinOS Basil tutorial found here in its original form:

https://docs.zeppelinos.org/docs/basil.html

My next test will be to try and issue the debug command using the Zeppelin OS Proxy contract as the contract wrapper for the setToken command. Hopefully that contract is getting deployed during the Truffle migrate that takes place when you execute a debug command. Perhaps I'll be able to trace from by going in the front door.

@gnidan I believe trying to use my repo as opposed to the attached instructions will do more harm than good since you have to setup several environment variables as you go through the tutorial. If those values are wrong you'll end up debugging the wrong thing (aka "wild goose chase").

basil-tutorial-work-area.txt

gitcoinbot commented 6 years ago

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


This issue now has a funding of 300.0 DAI (300.0 USD @ $1.0/DAI) attached to it.

gitcoinbot commented 6 years ago

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


Work has been started.

These users each claimed they can complete the work by 3 months from now. Please review their action plans below:

1) roschler has been approved to start work.

Examine the materials involved with solving the issue and implement a proper solution.

Learn more on the Gitcoin Issue Details page.

froller commented 6 years ago

I noticed that removing someAddress.transfer(amount) makes debugger work w/o context null error

vongohren commented 6 years ago

@roschler is the bounty going anywhere? The bug is still there

vongohren commented 6 years ago

@roschler @gnidan for information, the new develope version gets past that context for null problem. But I experience another problem, working on this contract https://github.com/uport-project/ethr-did-registry/blob/develop/contracts/EthereumDIDRegistry.sol with method function changeOwnerSigned That is that I can't get past ecrecover in the debugger. But i get past bytes32 hash = keccak256(byte(0x19), byte(0), this, nonce[identityOwner(identity)], identity, "changeOwner", newOwner);

Tried with o and n og pass the method, but it crashes when evaluating ecrecover to go past it.

EthereumDIDRegistry.sol:

44:
45:   function checkSignature(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 hash) internal returns(address) {
46:     address signer = ecrecover(hash, sigV, sigR, sigS);
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

debug(develop:0xf2d18920...)> o
redux-saga error: uncaught at session.saga
at session.saga
 at controller.saga
 at stepOver
 TypeError: Cannot read property 'binary' of undefined
    at evm.current.context (/Users/snorre/code/truffle/packages/truffle-debugger/dist/lib/evm/selectors/index.js:204:1)
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:76:25
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:90:33
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at Function.<anonymous> (/Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25)
    at args (/Users/snorre/code/truffle/node_modules/reselect-tree/lib/index.js:79:1)
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at Function.<anonymous> (/Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25)
    at args (/Users/snorre/code/truffle/node_modules/reselect-tree/lib/index.js:79:1)
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at Function.<anonymous> (/Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25)
    at args (/Users/snorre/code/truffle/node_modules/reselect-tree/lib/index.js:79:1)
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25
    at runSelectEffect (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/proc.js:709:28)
    at runEffect (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/proc.js:446:761)
    at next (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/proc.js:326:9)
    at currCb (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/proc.js:399:7)
    at takeCb (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/proc.js:477:108)
    at Object.put (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/channel.js:85:16)
    at /Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/channel.js:173:10
    at Array.<anonymous> (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/channel.js:194:9)
    at Object.emit (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/channel.js:38:13)
    at /Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/middleware.js:73:21
    at dispatch (/Users/snorre/code/truffle/node_modules/redux/lib/applyMiddleware.js:45:18)
    at /Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/utils.js:265:12
    at /Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/proc.js:500:52
    at exec (/Users/snorre/code/truffle/node_modules/redux-saga/lib/internal/scheduler.js:25:5)
TypeError: Cannot read property 'binary' of undefined
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at args (/Users/snorre/code/truffle/node_modules/reselect-tree/lib/index.js:79:1)
    at Function.<anonymous> (/Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25)
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at args (/Users/snorre/code/truffle/node_modules/reselect-tree/lib/index.js:79:1)
    at Function.<anonymous> (/Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25)
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at args (/Users/snorre/code/truffle/node_modules/reselect-tree/lib/index.js:79:1)
    at Function.<anonymous> (/Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25)
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:86:37
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:90:33
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:36:25
    at /Users/snorre/code/truffle/node_modules/reselect/lib/index.js:76:25
    at evm.current.context (/Users/snorre/code/truffle/packages/truffle-debugger/dist/lib/evm/selectors/index.js:204:1)
gnidan commented 6 years ago

Just released Truffle v4.1.14. Can people with this issue see if that version fixes it? Thanks!

npm uninstall -g truffle
npm install -g truffle
vongohren commented 6 years ago

I seem to be back at start with newest development branch. So now I cant event get to the ecrecover statment, as I did with last version. Other code works, but debugging transactions that iterates over ecrecover, gets this thing I initially posted.

PS: for more information around this, there was a discussion in gitter truffle-dev

svechinsky commented 6 years ago

Original error seems to exist with truffle 4.1.14

chris-gilbert commented 6 years ago

Has there been any progress on this? Any workaround for debugging through ZeppelinOS proxies?

gnidan commented 6 years ago

@chris-gilbert Truffle has just onboarded a new full-time member of the team (@hjaltman) to work on the debugger. Planning to address some of these long-standing bugs in the coming weeks.

chris-gilbert commented 6 years ago

Great news @gnidan. @hjaltman Let me know if I can help in any way, either through setting up reproducible steps or testing out builds.

vongohren commented 6 years ago

@gnidan @hjaltman Im back to debugging the same contract that I used in the reference issue https://github.com/uport-project/ethr-did-registry/issues/9

And now it is a new interesting error but, I still cant get pas ecrecover See attached picture. I was thinking that the fix that was discussed, was to kinda just skip ecrecover, but atleast continue down the road.

What are the thoughts on this?

screen shot 2018-10-03 at 17 20 41
spm32 commented 5 years ago

Hey @gnidan any thoughts on the above?

kuhnchris commented 5 years ago

Hello @gnidan @roschler ! We saw that there isn't any progress on this issue for a couple of months now - is there anything we can help you here in terms of the bounty side of things?

Thanks! Chris & the Gitcoin Team