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

Instrumentation appears to be breaking constants #153

Closed
davesag opened this issue Nov 16, 2017 · 12 comments · Fixed by #154
Closed

Instrumentation appears to be breaking constants #153

davesag opened this issue Nov 16, 2017 · 12 comments · Fixed by #154

Comments

@davesag
Copy link

davesag commented Nov 16, 2017

I have a library as follows

pragma solidity ^0.4.18;

import 'zeppelin-solidity/contracts/token/ERC20.sol';


library KeyUtils {
    address constant private KEY_ADDRESS = 0x0;

    function getKEY() internal pure returns (ERC20) {
        return ERC20(KEY_ADDRESS);
    }
}

and normal tests of this run fine.

But when I run with solidity-coverage I get this error

/Users/davesag/src/myawesomeproject/coverageEnv/contracts/utils/KeyUtils.sol:13:5: TypeError: Library cannot have non-constant state variables
    address private KEY_ADDRESS = 0x0;
    ^-------------------------------^
Compilation failed. See above.

Somehow the instrumentation process appears to have removed the constant keyword.

@area
Copy link
Contributor

area commented Nov 16, 2017

Ah, interesting. Yes, that is deliberate, as functions declared as constant / pure / view can't have events in them, which we use for instrumentation. So we strip those out so that the contract will compile with our instrumentation, but we hadn't appreciated that there was this use case for constant.

@cgewecke
Copy link
Member

Should we stop supporting constant as a function modifier in 4.0? Looks deprecated in the docs, I.e doesn't appear as an option.

@area
Copy link
Contributor

area commented Nov 16, 2017

It is described as an alias to view. It would also mean that we forced a requirement of Solidity ^0.4.17 on the users.

@davesag
Copy link
Author

davesag commented Nov 16, 2017

Couldn't you simply not instrument constant functions? Not ideal granted but better than actually breaking code. Otherwise could you just strip constant from functions and not from actual constants. I've not looked into how you do it but a regex of $(\s+[a-z]+\s)(constant) would be enough to distinguish between

address constant MY_THING = 0x0`

and

function something() constant returns (address)

@area
Copy link
Contributor

area commented Nov 16, 2017

Couldn't you simply not instrument constant functions? Not ideal granted but better than actually breaking code.

This wasn't a deliberate design decision, just something that we overlooked! I desperately want to keep instrumenting constant functions though, as they are an important part of any contract and can be used by non-constant functions, and so are able to influence the blockchain.

We do currently use a very simple regex, but extending it is non-trivial ("now we have two problems"). For example, the following is valid (if oddly formatted!) solidity:

pragma solidity ^0.4.0;


contract Test {
    address constant public x = 1;
    
    function hash (string _target) 
    public constant returns (bytes32)  {
        return sha3(_target);
    }
    
}

@davesag
Copy link
Author

davesag commented Nov 16, 2017

That certainly is an edge-case kind of function

@area
Copy link
Contributor

area commented Nov 16, 2017

@cgewecke Is there a reason we didn't do this with something like the following in the preprocessor?

      } else if (node.type === 'FunctionDeclaration' && node.modifiers) {
          // We want to remove constant / pure / view from functions
          for (let i = 0; i < node.modifiers.length; i++) {
            if (['pure', 'constant', 'view'].indexOf(node.modifiers[i].name) > -1) {
              contract = contract.slice(0, node.modifiers[i].start) + contract.slice(node.modifiers[i].end);
              keepRunning = true;
              this.stopTraversal();
            }
          }
        }

@cgewecke
Copy link
Member

@area That's looks great - does it work for the edge case elena raised here?

@area
Copy link
Contributor

area commented Nov 16, 2017

If we run the preprocessor over everything instead of running the regex over everything, I see no reason why it wouldn't.

@cgewecke
Copy link
Member

@davesag Thanks so much for reporting this and @area thank you for fixing. Please re-open there continue to be issues:

Published in 0.4.1

@davesag
Copy link
Author

davesag commented Nov 20, 2017

Cool, I'll merge these changes into #151

@davesag
Copy link
Author

davesag commented Nov 20, 2017

done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants