class Bridge extends PrecompiledContracts.PrecompiledContract {

    @Override
    public byte[] execute(byte[] data) {
        try
        {
            // Preliminary validation: the transaction on which we execute cannot be null
            if (rskTx == null) {
                throw new RuntimeException("Rsk Transaction is null");
            }

            BridgeParsedData bridgeParsedData = parseData(data);

            // Function parsing from data returned null => invalid function selected, halt!
            if (bridgeParsedData == null) {
                String errorMessage = String.format("Invalid data given: %s.", ByteUtil.toHexString(data));
                logger.info(errorMessage);
                if (activations.isActive(ConsensusRule.RSKIP88)) {
                    throw new BridgeIllegalArgumentException(errorMessage);
                }

                return null;
            }

            // If this is not a local call, then first check whether the function
            // allows for non-local calls
            if (activations.isActive(ConsensusRule.RSKIP88) && !isLocalCall() && bridgeParsedData.bridgeMethod.onlyAllowsLocalCalls()) {
                String errorMessage = String.format("Non-local-call to %s. Returning without execution.", bridgeParsedData.bridgeMethod.getFunction().name);
                logger.info(errorMessage);
                throw new BridgeIllegalArgumentException(errorMessage);
            }

            Optional<?> result;
            try {
                // bridgeParsedData.function should be one of the CallTransaction.Function declared above.
                // If the user tries to call an non-existent function, parseData() will return null.
                result = bridgeParsedData.bridgeMethod.getExecutor().execute(this, bridgeParsedData.args);
            } catch (BridgeIllegalArgumentException ex) {
                String errorMessage = String.format("Error executing: %s", bridgeParsedData.bridgeMethod);
                logger.warn(errorMessage, ex);
                if (activations.isActive(ConsensusRule.RSKIP88)) {
                    throw new BridgeIllegalArgumentException(errorMessage);
                }

                return null;
            }

            teardown();

            return result.map(bridgeParsedData.bridgeMethod.getFunction()::encodeOutputs).orElse(null);
        }
        catch(Exception ex) {
            logger.error(ex.getMessage(), ex);
            panicProcessor.panic("bridgeexecute", ex.getMessage());
            throw new RuntimeException(String.format("Exception executing bridge: %s", ex.getMessage()), ex);
        }
    }

    public  Bridge(RskAddress contractAddress, Constants constants, ActivationConfig activationConfig,
            BridgeSupportFactory bridgeSupportFactory);

}