I'm writing a contract based on the ring mixer contract from here https://ropsten.etherscan.io/address/0x5e10d764314040b04ac7d96610b9851c8bc02815

I've tested it with ganache. Everything worked fine until I tried to deploy it on my private network. Truffle gave me the following error:

"RingMixerV2" received a generic error from Geth that can be caused by hitting revert in a contract constructor or running out of gas. * Returned error: gas required exceeds allowance or always failing transaction. * Try: + using the '--dry-run' option to reproduce this failure with clearer errors. + verifying that your gas is adequate for this deployment.`

I've cut down the codes as below but there's no luck. I was able to deploy it on Ropsten with Remix so I don't know what is wrong. I'm using truffle v5.0.2.

pragma solidity >0.4.99 <0.6.0;

contract RingMixerV2 {
    //Debug Code
    address public owner;
    constructor() public {
        //Debug Code
        owner = msg.sender;

        G1[0] = 1;
        G1[1] = 2;
        H = HashPoint(G1);

    function Kill() public {
        if ( (msg.sender != owner) && (owner != address(0)) ) revert();


    //alt_bn128 constants
    uint256[2] public G1;
    uint256[2] public H;
    uint256 constant public N = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001;
    uint256 constant public P = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;

    //Used for Point Compression/Decompression
    uint256 constant public ECSignMask = 0x8000000000000000000000000000000000000000000000000000000000000000;
    uint256 constant public a = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52; // (p+1)/4

    //Storage of Spent Key Images
    mapping (uint256 => bool) public KeyImageUsed;

    //Storage of Token Balances
    mapping (address => uint256) public token_balance;

    //Convenience tables for looking up acceptable mix-in keys
    mapping (uint256 => uint256[]) public lookup_pubkey_by_balance;
    mapping (uint256 => bool) public lookup_pubkey_by_balance_populated;
    mapping (uint256 => uint256) public lookup_pubkey_by_balance_count;

    function EvaluateCurve(uint256 x)
        public view returns (uint256 y, bool onCurve)
        uint256 y_squared = mulmod(x,x, P);
        y_squared = mulmod(y_squared, x, P);
        y_squared = addmod(y_squared, 3, P);

        uint256 p_local = P;
        uint256 a_local = a;

        assembly {
            //Get Free Memory Pointer
            let p := mload(0x40)

            //Store Data for Big Int Mod Exp Call
            mstore(p, 0x20)                 //Length of Base
            mstore(add(p, 0x20), 0x20)      //Length of Exponent
            mstore(add(p, 0x40), 0x20)      //Length of Modulus
            mstore(add(p, 0x60), y_squared) //Base
            mstore(add(p, 0x80), a_local)   //Exponent
            mstore(add(p, 0xA0), p_local)   //Modulus

            //Call Big Int Mod Exp
            let success := staticcall(sub(gas, 2000), 0x05, p, 0xC0, p, 0x20)

            // Use "invalid" to make gas estimation work
            //switch success case 0 { revert(p, 0xC0) }
            switch success case 0 { invalid()}

            //Store Return Data
            y := mload(p)

        //Check Answer
        onCurve = (y_squared == mulmod(y, y, P));

    //Return H = alt_bn128 evaluated at keccak256(p)
    function HashPoint(uint256[2] memory p)
        internal view returns (uint256[2] memory h)
        bool onCurve;
        h[0] = uint256(keccak256(abi.encodePacked(p[0], p[1]))) % N;

        while(!onCurve) {
            (h[1], onCurve) = EvaluateCurve(h[0]);


Any help would be appreciated.

  • 1
    Check the gasLimit of your latest block web3.eth.getBlock("latest").gasLimit in your private chain. Eventually you have set a too small value in your genesis? There is only one location in geth's code where this error message is thrown. So I am suspecting that your cap is too low.
    – ivicaa
    Jan 29, 2019 at 21:00
  • I believe that the gas limit is sufficient. The latest one is 24092006. In my genesis.json I set it to 0x8000000.
    – user50334
    Jan 30, 2019 at 2:59
  • So I run geth with verbosity and I saw this error invalid opcode 0xfa. 0xfa is staticcall so any chance it was because of this line let success := staticcall(sub(gas, 2000), 0x05, p, 0xC0, p, 0x20) ? Actually the original code is let success := call(sub(gas, 2000), 0x05, 0, p, 0xC0, p, 0x20) but after upgrading truffle, it gave me error TypeError: Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. so I changed it to staticcall.
    – user50334
    Jan 30, 2019 at 4:46

1 Answer 1


You do not have byzantium enabled in your private network.

Check that you have byzantiumBlock set in the config section of your genesis.json.

let success := staticcall(sub(gas, 2000), 0x05, p, 0xC0, p, 0x20) is calling the precompiled contract at address 0x05, which is "Modular exponentiation (EIP 198)". This works only with byznatium enabled.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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