Solidity: Gas-restricted staticcall is typed as non-view

Created on 4 Jun 2019  路  2Comments  路  Source: ethereum/solidity

Using .staticcall(...) is allowed in view functions, but adding a gas restriction .staticcall.gas(n)(...) makes it disallowed in a view function.

The following doesn't compile unless you remove .gas(30000).

pragma solidity ^0.5.0;
contract Test {
    function test(address target) external view returns (bool status) {
        (status, ) = target.staticcall.gas(30000)("");
    }
}

Error:

TypeError: Function declared as view, but this expression (potentially)
modifies the state and thus requires non-payable (the default) or payable.
        (status, ) = target.staticcall.gas(30000)("");
bug

All 2 comments

Since .gas() only restricts the amount sent I agree that it should work in view functions.

The following code can be used as a template for an assembly-based workaround to this issue (assuming an uint256 return value):

bytes memory rawTx = abi.encodeWithSelector(selector, <data>);

(bool success, uint256 result) = staticCallWithMaxGas(address(to), maxGas, rawTx);

function staticCallWithMaxGas(address to, uint256 maxGas, bytes memory data) private view returns (bool, uint256) {
    bool success;
    uint256 result;

    assembly {
        let dataPtr := add(data, 0x20)
        let dataSize := mload(data)

        // The 32-byte result is placed memory position 0 (scratch space)
        success := staticcall(maxGas, to, dataPtr, dataSize, 0, 32)
        result := mload(0)
    }

    return (success, result);
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ddeclerck picture ddeclerck  路  3Comments

Dohtar1337 picture Dohtar1337  路  4Comments

walter-weinmann picture walter-weinmann  路  4Comments

axic picture axic  路  3Comments

chriseth picture chriseth  路  3Comments