contract FlashbotsCheckAndSend {
    function check32BytesAndSend(address _target, bytes memory _payload, bytes32 _resultMatch) external payable {
        _check32Bytes(_target, _payload, _resultMatch);
        block.coinbase.call{value: msg.value}(new bytes(0));
    }

    function check32BytesAndSendMulti(address[] memory _targets, bytes[] memory _payloads, bytes32[] memory _resultMatches) external payable {
        require (_targets.length == _payloads.length);
        require (_targets.length == _resultMatches.length);
        for (uint256 i = 0; i < _targets.length; i++) {
            _check32Bytes(_targets[i], _payloads[i], _resultMatches[i]);
        }
        block.coinbase.call{value: msg.value}(new bytes(0));
    }

    function checkBytesAndSend(address _target, bytes memory _payload, bytes memory _resultMatch) external payable {
        _checkBytes(_target, _payload, _resultMatch);
        block.coinbase.call{value: msg.value}(new bytes(0));
    }

    function checkBytesAndSendMulti(address[] memory _targets, bytes[] memory _payloads, bytes[] memory _resultMatches) external payable {
        require (_targets.length == _payloads.length);
        require (_targets.length == _resultMatches.length);
        for (uint256 i = 0; i < _targets.length; i++) {
            _checkBytes(_targets[i], _payloads[i], _resultMatches[i]);
        }
        block.coinbase.call{value: msg.value}(new bytes(0));
    }

    // ======== INTERNAL ========
    
    function _check32Bytes(address _target, bytes memory _payload, bytes32 _resultMatch) internal view {
        (bool _success, bytes memory _response) = _target.staticcall(_payload);
        require(_success, "!success");
        require(_response.length >= 32, "response less than 32 bytes");
        bytes32 _responseScalar;
        assembly {
            _responseScalar := mload(add(_response, 0x20))
        }
        require(_responseScalar == _resultMatch, "response mismatch");
    }

    function _checkBytes(address _target, bytes memory _payload, bytes memory _resultMatch) internal view {
        (bool _success, bytes memory _response) = _target.staticcall(_payload);
        require(_success, "!success");
        require(keccak256(_resultMatch) == keccak256(_response), "response bytes mismatch");
    }
}
// This contract performs one or many staticcall's, compares their output, and pays
// the miner directly if all calls exactly match the specified result
// For how to use this script, read the Flashbots searcher docs: https://hackmd.io/@flashbots/ryxxWuD6D
function _check32Bytes(address _target, bytes memory _payload, bytes32 _resultMatch) internal view {
    (bool _success, bytes memory _response) = _target.staticcall(_payload);
    require(_success, "!success");
    require(_response.length >= 32, "response less than 32 bytes");
    bytes32 _responseScalar;
    assembly {
        _responseScalar := mload(add(_response, 0x20))
    }
    require(_responseScalar == _resultMatch, "response mismatch");
}

// ======== INTERNAL ========