Truffle – Fixing Gas Required Exceeds Allowance or Always Failing Transaction

contract-deploymenttruffle-contract

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();

        selfdestruct(msg.sender);
    }

    //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]);
            h[0]++;
        }
        h[0]--;
    }

}

Any help would be appreciated.

Best Answer

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.

Related Topic