diff --git a/src/protocols/Bundle.sol b/src/protocols/Bundle.sol index fdd5203..a968201 100644 --- a/src/protocols/Bundle.sol +++ b/src/protocols/Bundle.sol @@ -33,11 +33,11 @@ library Bundle { return Suave.doHTTPRequest(request); } - function encodeBundle(BundleObj memory args) internal pure returns (Suave.HttpRequest memory) { - require(args.txns.length > 0, "Bundle: no txns"); - - bytes memory params = - abi.encodePacked('{"blockNumber": "', LibString.toHexString(args.blockNumber), '", "txs": ['); + /// @notice encode a bundle in json format. + /// @param args the bundle to encode. + /// @return params JSON-encoded bytes: `{blockNumber, txs, minTimestamp, maxTimestamp}` + function encodeBundleParams(BundleObj memory args) internal pure returns (bytes memory params) { + params = abi.encodePacked('{"blockNumber": "', LibString.toMinimalHexString(args.blockNumber), '", "txs": ['); for (uint256 i = 0; i < args.txns.length; i++) { params = abi.encodePacked(params, '"', LibString.toHexString(args.txns[i]), '"'); if (i < args.txns.length - 1) { @@ -53,7 +53,15 @@ library Bundle { params = abi.encodePacked(params, ', "maxTimestamp": ', LibString.toString(args.maxTimestamp)); } params = abi.encodePacked(params, "}"); + } + + /// @notice encode a call to `eth_sendBundle` as an HttpRequest. + /// @param args the bundle to encode. + /// @return request the HttpRequest to send the bundle. + function encodeBundle(BundleObj memory args) internal pure returns (Suave.HttpRequest memory) { + require(args.txns.length > 0, "Bundle: no txns"); + bytes memory params = encodeBundleParams(args); bytes memory body = abi.encodePacked('{"jsonrpc":"2.0","method":"eth_sendBundle","params":[', params, '],"id":1}'); diff --git a/test/protocols/Bundle.t.sol b/test/protocols/Bundle.t.sol index 8a85428..bbf3a09 100644 --- a/test/protocols/Bundle.t.sol +++ b/test/protocols/Bundle.t.sol @@ -18,7 +18,7 @@ contract EthSendBundle is Test { Suave.HttpRequest memory request = Bundle.encodeBundle(bundle); assertEq( string(request.body), - '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{"blockNumber": "0x01", "txs": ["0x1234"]}],"id":1}' + '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{"blockNumber": "0x1", "txs": ["0x1234"]}],"id":1}' ); assertTrue(request.withFlashbotsSignature); @@ -28,7 +28,7 @@ contract EthSendBundle is Test { Suave.HttpRequest memory request2 = Bundle.encodeBundle(bundle); assertEq( string(request2.body), - '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{"blockNumber": "0x01", "txs": ["0x1234"], "minTimestamp": 2}],"id":1}' + '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{"blockNumber": "0x1", "txs": ["0x1234"], "minTimestamp": 2}],"id":1}' ); // encode with 'maxTimestamp' @@ -37,7 +37,7 @@ contract EthSendBundle is Test { Suave.HttpRequest memory request3 = Bundle.encodeBundle(bundle); assertEq( string(request3.body), - '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{"blockNumber": "0x01", "txs": ["0x1234"], "minTimestamp": 2, "maxTimestamp": 3}],"id":1}' + '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{"blockNumber": "0x1", "txs": ["0x1234"], "minTimestamp": 2, "maxTimestamp": 3}],"id":1}' ); } diff --git a/tools/docs-gen/main.go b/tools/docs-gen/main.go index 6e75620..2cce7ab 100644 --- a/tools/docs-gen/main.go +++ b/tools/docs-gen/main.go @@ -259,6 +259,13 @@ func readForgeArtifacts(path string) ([]*artifact, error) { if d.IsDir() { return nil } + + // ignore if parent directory doesn't end w/ ".sol" + parentDir := filepath.Base(filepath.Dir(path)) + if !strings.HasSuffix(parentDir, ".sol") { + return nil + } + ext := filepath.Ext(d.Name()) if ext != ".json" { return nil