truffle-debugger icon indicating copy to clipboard operation
truffle-debugger copied to clipboard

TypeError: Cannot read property 'context' of null

Open cmcewen opened this issue 6 years ago • 15 comments

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)

cmcewen avatar Jun 04 '18 20:06 cmcewen

@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

roschler avatar Jun 06 '18 20:06 roschler

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 avatar Jun 10 '18 18:06 gitcoinbot

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.

gitcoinbot avatar Jun 10 '18 18:06 gitcoinbot

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

froller avatar Jul 21 '18 16:07 froller

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

vongohren avatar Aug 08 '18 18:08 vongohren

@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)

vongohren avatar Aug 08 '18 21:08 vongohren

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

gnidan avatar Aug 13 '18 17:08 gnidan

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

vongohren avatar Aug 14 '18 13:08 vongohren

Original error seems to exist with truffle 4.1.14

svechinsky avatar Aug 24 '18 15:08 svechinsky

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

chris-gilbert avatar Sep 19 '18 20:09 chris-gilbert

@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.

gnidan avatar Sep 19 '18 22:09 gnidan

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

chris-gilbert avatar Sep 20 '18 12:09 chris-gilbert

@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

vongohren avatar Oct 03 '18 15:10 vongohren

Hey @gnidan any thoughts on the above?

spm32 avatar Nov 21 '18 08:11 spm32

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

kuhnchris avatar Jan 21 '19 22:01 kuhnchris