4

I'm trying to call some of the new precompiled contract (ecmul) from a pure function but it fails with:

browser/ballot.sol:11:23: TypeError: Function declared as pure, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable.
            if iszero(call(not(0), 0x07, 0, input, 0x60, p, 0x40)) {
                      ^--^

This is the sample contract (requires solc 0.4.19):

pragma solidity ^0.4.19;

contract Ballot {
    function ecmul(uint256 x, uint256 y, uint256 scalar) public pure returns (uint256[2] p) {
        // With a public key (x, y), this computes p = scalar * (x, y).
        uint256[3] memory input;
        input[0] = x;
        input[1] = y;
        input[2] = scalar;
        assembly {
            // call ecmul precompile
            if iszero(call(not(0), 0x07, 0, input, 0x60, p, 0x40)) {
                revert(0, 0)
            }
        }
    }
}

Taken from the article precompiles & solidity.

If I declare the function as view it will work but seems as unnecessary since it is a precompiled contract it should not modify the storage of any contract.

  • You say using view seems unnecessary, are there any other specific reasons you want to use pure instead of view? – willjgriff Jan 10 '18 at 16:29
  • @willjgriff My main issue is that modifying it to view forces me to modify all functions that use ecmul to be declared as view, and this forces any function that calls one of those to also be declared as view. – Ismael Jan 10 '18 at 19:40
2

Firstly note that the view modifier, as seen in the doc here doesn't allow modifying of the state, it only allows reading of the state and behaves the same as constant (the modifier used for these code snippets in the article you've linked to). The pure modifier, in the doc here prevents both modifying and reading of the state.

To answer your question, it seems like using call() with any arguments raises this error when the pure modifier, which prevents reading of the state, is used. Which makes sense as call() needs to read the state to get the contract code at the address specified so it can execute a function on it.

| improve this answer | |
  • The thing is precompiled contracts do not read and do not modify their state. One can argue that they do not have state. As an example sha256() is a precompiled contract and you can call it from a pure function. – Ismael Jan 10 '18 at 0:55
  • If they're not in the state and the EVM doesn't have to read from the state to get them then I guess the compiler just doesn't know what the precompiled code addresses are. For all other contract addresses view is required and it doesn't consider these addresses different. – willjgriff Jan 10 '18 at 11:52
  • Perhaps functions will be added to Solidity to represent these precompiles in future like the sha256() and ecrecvoer() functions. – willjgriff Jan 10 '18 at 12:05
  • Yes, I hope eventually all precompiled contracts will be added to solidity. I was hopping for a workaround. – Ismael Jan 10 '18 at 16:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.