class BridgeUtils {

    public static boolean isFreeBridgeTx(Transaction uscTx, long blockNumber, BlockchainNetConfig netConfig) {
        UscAddress receiveAddress = uscTx.getReceiveAddress();
        if (receiveAddress.equals(UscAddress.nullAddress())) {
            return false;
        }

        BridgeConstants bridgeConstants = netConfig.getCommonConstants().getBridgeConstants();

        // Temporary assumption: if areBridgeTxsFree() is true then the current federation
        // must be the genesis federation.
        // Once the original federation changes, txs are always paid.
        return PrecompiledContracts.BRIDGE_ADDR.equals(receiveAddress) &&
               netConfig.getConfigForBlock(blockNumber).areBridgeTxsFree() &&
               uscTx.acceptTransactionSignature(netConfig.getCommonConstants().getChainId()) &&
               (
                       isFromFederateMember(uscTx, bridgeConstants.getGenesisFederation()) ||
                       isFromFederationChangeAuthorizedSender(uscTx, bridgeConstants) ||
                       isFromLockWhitelistChangeAuthorizedSender(uscTx, bridgeConstants) ||
                       isFromFeePerKbChangeAuthorizedSender(uscTx, bridgeConstants)
               );
    }

}