From d5d063f97e8e8a263d13342b28b54b69420c5ebb Mon Sep 17 00:00:00 2001 From: Gonzalo Date: Mon, 27 Nov 2023 17:19:41 +0100 Subject: [PATCH] Feat/rpc module (#236) * feat: rpc module * test: add test for the `rpc` module * style: format * docs: update docs * docs: update other modules * chore: add call method with url * docs: update docs and examples * docs: update examples * chore: code review * docs: update docs and examples * chore: remove call with json params --- docs/src/OTHER_MODULES.md | 1 + docs/src/SUMMARY.md | 1 + docs/src/examples/config/example.md | 4 +- docs/src/examples/events/example.md | 1 + docs/src/examples/rpc/example.md | 34 +++ docs/src/modules/rpc.md | 7 + docs/src/references/Config.md | 6 +- docs/src/references/Expect.md | 240 +++++++++++++++++++++ docs/src/references/SUMMARY.md | 1 + docs/src/references/rpc.md | 14 ++ src/_imports.sol | 3 +- src/_internal/Config.sol | 4 +- src/_internal/Rpc.sol | 41 ++++ src/script/Config.sol | 2 +- src/script/Rpc.sol | 4 + src/test/Config.sol | 2 +- src/test/Rpc.sol | 4 + test/examples/config/ConfigExample03.t.sol | 4 +- test/examples/events/EventsExample01.t.sol | 2 +- test/examples/rpc/RpcExample01.t.sol | 27 +++ test/modules/Config.t.sol | 4 +- test/modules/Fmt.t.sol | 1 - test/modules/Rpc.t.sol | 24 +++ 23 files changed, 415 insertions(+), 16 deletions(-) create mode 100644 docs/src/examples/rpc/example.md create mode 100644 docs/src/modules/rpc.md create mode 100644 docs/src/references/rpc.md create mode 100644 src/_internal/Rpc.sol create mode 100644 src/script/Rpc.sol create mode 100644 src/test/Rpc.sol create mode 100644 test/examples/rpc/RpcExample01.t.sol create mode 100644 test/modules/Rpc.t.sol diff --git a/docs/src/OTHER_MODULES.md b/docs/src/OTHER_MODULES.md index 012f0ddb..bbb2f2e3 100644 --- a/docs/src/OTHER_MODULES.md +++ b/docs/src/OTHER_MODULES.md @@ -5,4 +5,5 @@ - [Env](./modules/env.md) - [Events](./modules/events.md) - [Forks](./modules/forks.md) +- [RPC](./modules/rpc.md) - [Strings](./modules/strings.md) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index d939a4d4..248a9f0d 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -27,6 +27,7 @@ - [Env](./modules/env.md) - [Events](./modules/events.md) - [Forks](./modules/forks.md) + - [RPC](./modules/rpc.md) - [Strings](./modules/strings.md) # References diff --git a/docs/src/examples/config/example.md b/docs/src/examples/config/example.md index c792e42f..496051c9 100644 --- a/docs/src/examples/config/example.md +++ b/docs/src/examples/config/example.md @@ -51,11 +51,11 @@ Read all the RPC URL from the foundry configuration as structs // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import {Test, expect, config, Rpc} from "vulcan/test.sol"; +import {Test, expect, config, RpcConfig} from "vulcan/test.sol"; contract ConfigExample is Test { function test() external { - Rpc[] memory rpcs = config.rpcUrlStructs(); + RpcConfig[] memory rpcs = config.rpcUrlStructs(); expect(rpcs.length).toEqual(2); expect(rpcs[0].name).toEqual("arbitrum"); diff --git a/docs/src/examples/events/example.md b/docs/src/examples/events/example.md index 13f4d9b4..e66ac588 100644 --- a/docs/src/examples/events/example.md +++ b/docs/src/examples/events/example.md @@ -4,6 +4,7 @@ Logging events and reading events topics and data ```solidity +// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {Test, expect, events, Log} from "vulcan/test.sol"; diff --git a/docs/src/examples/rpc/example.md b/docs/src/examples/rpc/example.md new file mode 100644 index 00000000..7c29f54e --- /dev/null +++ b/docs/src/examples/rpc/example.md @@ -0,0 +1,34 @@ +## Examples +### Calling an RPC + +Calling an rpc using the `eth_chainId` method + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Test, expect} from "vulcan/test.sol"; +import {rpc} from "vulcan/test/Rpc.sol"; +import {Fork, forks} from "vulcan/test/Forks.sol"; + +contract RpcTest is Test { + function testNetVersion() external { + forks.create("https://rpc.mevblocker.io/fast").select(); + + string memory method = "eth_chainId"; + string memory params = "[]"; + + bytes memory data = rpc.call(method, params); + + uint8 chainId; + + assembly { + chainId := mload(add(data, 0x01)) + } + + expect(chainId).toEqual(block.chainid); + } +} + +``` + diff --git a/docs/src/modules/rpc.md b/docs/src/modules/rpc.md new file mode 100644 index 00000000..662f758b --- /dev/null +++ b/docs/src/modules/rpc.md @@ -0,0 +1,7 @@ +# RPC + +The `rpc` module provides methods to interact with JSON-RPC APIs. The list of official Ethereum RPC methods can +be found [here](https://ethereum.org/en/developers/docs/apis/json-rpc). + +{{#include ../examples/rpc/example.md}} + diff --git a/docs/src/references/Config.md b/docs/src/references/Config.md index d2c02c58..66276bf2 100644 --- a/docs/src/references/Config.md +++ b/docs/src/references/Config.md @@ -2,10 +2,10 @@ ## Structs -### Rpc +### RpcConfig ```solidity -struct Rpc { +struct RpcConfig { string name string url } @@ -25,7 +25,7 @@ Obtains a specific RPC from the configuration by name. Obtains all the RPCs from the configuration. -### **rpcUrlStructs() → (Rpc[] rpcs)** +### **rpcUrlStructs() → (RpcConfig[] rpcs)** Obtains all the RPCs from the configuration. diff --git a/docs/src/references/Expect.md b/docs/src/references/Expect.md index 8f1548da..72101886 100644 --- a/docs/src/references/Expect.md +++ b/docs/src/references/Expect.md @@ -216,238 +216,478 @@ struct _CallExpectationNot { +### **toEqual(_BoolExpectation self, bool expected, string message)** + + + ### **toEqual(_BoolExpectationNot self, bool expected)** +### **toEqual(_BoolExpectationNot self, bool expected, string message)** + + + ### **toBeTrue(_BoolExpectation self)** +### **toBeTrue(_BoolExpectation self, string message)** + + + ### **toBeFalse(_BoolExpectation self)** +### **toBeFalse(_BoolExpectation self, string message)** + + + ### **toEqual(_AddressExpectation self, address expected)** +### **toEqual(_AddressExpectation self, address expected, string message)** + + + ### **toEqual(_AddressExpectationNot self, address expected)** +### **toEqual(_AddressExpectationNot self, address expected, string message)** + + + ### **toBeAContract(_AddressExpectation self)** +### **toBeAContract(_AddressExpectation self, string message)** + + + ### **toBeAContract(_AddressExpectationNot self)** +### **toBeAContract(_AddressExpectationNot self, string message)** + + + ### **toEqual(_Bytes32Expectation self, bytes32 expected)** +### **toEqual(_Bytes32Expectation self, bytes32 expected, string message)** + + + ### **toEqual(_Bytes32ExpectationNot self, bytes32 expected)** +### **toEqual(_Bytes32ExpectationNot self, bytes32 expected, string message)** + + + ### **toBeTheHashOf(_Bytes32Expectation self, bytes data)** +### **toBeTheHashOf(_Bytes32Expectation self, bytes data, string message)** + + + ### **toBeTheHashOf(_Bytes32ExpectationNot self, bytes data)** +### **toBeTheHashOf(_Bytes32ExpectationNot self, bytes data, string message)** + + + ### **toEqual(_BytesExpectation self, bytes expected)** +### **toEqual(_BytesExpectation self, bytes expected, string message)** + + + ### **toEqual(_BytesExpectationNot self, bytes expected)** +### **toEqual(_BytesExpectationNot self, bytes expected, string message)** + + + ### **toEqual(_StringExpectation self, string expected)** +### **toEqual(_StringExpectation self, string expected, string message)** + + + ### **toEqual(_StringExpectationNot self, string expected)** +### **toEqual(_StringExpectationNot self, string expected, string message)** + + + ### **toContain(_StringExpectation self, string contained)** +### **toContain(_StringExpectation self, string contained, string message)** + + + ### **toContain(_StringExpectationNot self, string contained)** +### **toContain(_StringExpectationNot self, string contained, string message)** + + + ### **toHaveLength(_StringExpectation self, uint256 expected)** +### **toHaveLength(_StringExpectation self, uint256 expected, string message)** + + + ### **toHaveLength(_StringExpectationNot self, uint256 expected)** +### **toHaveLength(_StringExpectationNot self, uint256 expected, string message)** + + + ### **toEqual(_UintExpectation self, uint256 expected)** +### **toEqual(_UintExpectation self, uint256 expected, string message)** + + + ### **toEqual(_UintExpectationNot self, uint256 expected)** +### **toEqual(_UintExpectationNot self, uint256 expected, string message)** + + + ### **toBeCloseTo(_UintExpectation self, uint256 expected, uint256 d)** +### **toBeCloseTo(_UintExpectation self, uint256 expected, uint256 d, string message)** + + + ### **toBeLessThan(_UintExpectation self, uint256 expected)** +### **toBeLessThan(_UintExpectation self, uint256 expected, string message)** + + + ### **toBeLessThanOrEqual(_UintExpectation self, uint256 expected)** +### **toBeLessThanOrEqual(_UintExpectation self, uint256 expected, string message)** + + + ### **toBeGreaterThan(_UintExpectation self, uint256 expected)** +### **toBeGreaterThan(_UintExpectation self, uint256 expected, string message)** + + + ### **toBeGreaterThanOrEqual(_UintExpectation self, uint256 expected)** +### **toBeGreaterThanOrEqual(_UintExpectation self, uint256 expected, string message)** + + + ### **toEqual(_IntExpectation self, int256 expected)** +### **toEqual(_IntExpectation self, int256 expected, string message)** + + + ### **toEqual(_IntExpectationNot self, int256 expected)** +### **toEqual(_IntExpectationNot self, int256 expected, string message)** + + + ### **toBeCloseTo(_IntExpectation self, int256 expected, uint256 d)** +### **toBeCloseTo(_IntExpectation self, int256 expected, uint256 d, string message)** + + + ### **toBeLessThan(_IntExpectation self, int256 expected)** +### **toBeLessThan(_IntExpectation self, int256 expected, string message)** + + + ### **toBeLessThanOrEqual(_IntExpectation self, int256 expected)** +### **toBeLessThanOrEqual(_IntExpectation self, int256 expected, string message)** + + + ### **toBeGreaterThan(_IntExpectation self, int256 expected)** +### **toBeGreaterThan(_IntExpectation self, int256 expected, string message)** + + + ### **toBeGreaterThanOrEqual(_IntExpectation self, int256 expected)** +### **toBeGreaterThanOrEqual(_IntExpectation self, int256 expected, string message)** + + + ### **toHaveReverted(_CallExpectation self)** +### **toHaveReverted(_CallExpectation self, string message)** + + + ### **toHaveRevertedWith(_CallExpectation self, bytes4 expectedSelector)** +### **toHaveRevertedWith(_CallExpectation self, bytes4 expectedSelector, string message)** + + + ### **toHaveRevertedWith(_CallExpectationNot self, bytes4 expectedSelector)** +### **toHaveRevertedWith(_CallExpectationNot self, bytes4 expectedSelector, string message)** + + + ### **toHaveRevertedWith(_CallExpectation self, string error)** +### **toHaveRevertedWith(_CallExpectation self, string error, string message)** + + + ### **toHaveRevertedWith(_CallExpectationNot self, string error)** +### **toHaveRevertedWith(_CallExpectationNot self, string error, string message)** + + + ### **toHaveRevertedWith(_CallExpectation self, bytes expectedError)** +### **toHaveRevertedWith(_CallExpectation self, bytes expectedError, string message)** + + + ### **toHaveRevertedWith(_CallExpectationNot self, bytes expectedError)** +### **toHaveRevertedWith(_CallExpectationNot self, bytes expectedError, string message)** + + + ### **toHaveSucceeded(_CallExpectation self)** +### **toHaveSucceeded(_CallExpectation self, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig)** +### **toHaveEmitted(_CallExpectation self, string eventSig, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[1] topics)** +### **toHaveEmitted(_CallExpectation self, bytes32[1] topics, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[2] topics)** +### **toHaveEmitted(_CallExpectation self, bytes32[2] topics, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[3] topics)** +### **toHaveEmitted(_CallExpectation self, bytes32[3] topics, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[4] topics)** +### **toHaveEmitted(_CallExpectation self, bytes32[4] topics, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes data)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[1] topics)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[1] topics, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[2] topics)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[2] topics, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[3] topics)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[3] topics, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[1] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, bytes32[1] topics, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[2] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, bytes32[2] topics, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[3] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, bytes32[3] topics, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, bytes32[4] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, bytes32[4] topics, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[1] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[1] topics, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[2] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[2] topics, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[3] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[3] topics, bytes data, string message)** + + + ### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[] topics, bytes data)** +### **toHaveEmitted(_CallExpectation self, string eventSig, bytes32[] topics, bytes data, string message)** + + + +### **printMessage(string message)** + + + ## AnyLib diff --git a/docs/src/references/SUMMARY.md b/docs/src/references/SUMMARY.md index cbd0585f..9303c9ac 100644 --- a/docs/src/references/SUMMARY.md +++ b/docs/src/references/SUMMARY.md @@ -16,6 +16,7 @@ - [Json](./Json.md) - [Pointer](./Pointer.md) - [Result](./Result.md) +- [Rpc](./Rpc.md) - [Semver](./Semver.md) - [Strings](./Strings.md) - [Utils](./Utils.md) diff --git a/docs/src/references/rpc.md b/docs/src/references/rpc.md new file mode 100644 index 00000000..8d88dd99 --- /dev/null +++ b/docs/src/references/rpc.md @@ -0,0 +1,14 @@ +# Rpc + +## rpc + + + +### **call(string urlOrName, string method, string params) → (bytes data)** + +Calls an JSON-RPC method on a specific RPC endpoint. If there was a previous active fork it will return back to that one once the method is called. + +### **call(string method, string params) → (bytes data)** + +Calls an JSON-RPC method on the current active fork + diff --git a/src/_imports.sol b/src/_imports.sol index 115aa511..6e3ac0e6 100644 --- a/src/_imports.sol +++ b/src/_imports.sol @@ -10,7 +10,7 @@ import {events} from "./_internal/Events.sol"; import {fs, FsMetadata, FsMetadataResult, FsErrors} from "./_internal/Fs.sol"; import {json, JsonObject, JsonResult} from "./_internal/Json.sol"; import {strings} from "./_internal/Strings.sol"; -import {config, Rpc} from "./_internal/Config.sol"; +import {config, RpcConfig} from "./_internal/Config.sol"; import {fmt} from "./_internal/Fmt.sol"; import {bound, format, println, removeSelector} from "./_internal/Utils.sol"; import {huff, Huffc} from "./_internal/Huff.sol"; @@ -28,3 +28,4 @@ import { RequestClient, RequestBuilder } from "./_internal/Request.sol"; +import {rpc} from "./_internal/Rpc.sol"; diff --git a/src/_internal/Config.sol b/src/_internal/Config.sol index 049cd6cc..8c9314bb 100644 --- a/src/_internal/Config.sol +++ b/src/_internal/Config.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.13 <0.9.0; import {vulcan, Hevm} from "./Vulcan.sol"; /// @dev Struct that represents an RPC endpoint -struct Rpc { +struct RpcConfig { string name; string url; } @@ -25,7 +25,7 @@ library config { /// @dev Obtains all the RPCs from the configuration. /// @return rpcs All the RPCs as `Rpc[]`. - function rpcUrlStructs() internal view returns (Rpc[] memory rpcs) { + function rpcUrlStructs() internal view returns (RpcConfig[] memory rpcs) { Hevm.Rpc[] memory _rpcs = vulcan.hevm.rpcUrlStructs(); assembly { rpcs := _rpcs diff --git a/src/_internal/Rpc.sol b/src/_internal/Rpc.sol new file mode 100644 index 00000000..186b6d7d --- /dev/null +++ b/src/_internal/Rpc.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +import {vulcan} from "./Vulcan.sol"; +import {forksUnsafe} from "./Forks.sol"; + +library rpc { + /// @dev Calls an JSON-RPC method on a specific RPC endpoint. If there was a previous active fork it will return back to that one once the method is called. + /// @param urlOrName The url or name of the RPC endpoint to use + /// @param method The JSON-RPC method to call + /// @param params The method params as a JSON string + function call(string memory urlOrName, string memory method, string memory params) + internal + returns (bytes memory data) + { + uint256 currentFork; + bool hasActiveFork; + + try vulcan.hevm.activeFork() returns (uint256 forkId) { + currentFork = forkId; + hasActiveFork = true; + } catch (bytes memory) {} + + forksUnsafe.create(urlOrName).select(); + + bytes memory result = call(method, params); + + if (hasActiveFork) { + vulcan.hevm.selectFork(currentFork); + } + + return result; + } + + /// @dev Calls an JSON-RPC method on the current active fork + /// @param method The JSON-RPC method to call + /// @param params The method params as a JSON string + function call(string memory method, string memory params) internal returns (bytes memory data) { + return vulcan.hevm.rpc(method, params); + } +} diff --git a/src/script/Config.sol b/src/script/Config.sol index 46a1ae52..d5637b5b 100644 --- a/src/script/Config.sol +++ b/src/script/Config.sol @@ -1,4 +1,4 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; -import {config, Rpc} from "../_internal/Config.sol"; +import {config, RpcConfig} from "../_internal/Config.sol"; diff --git a/src/script/Rpc.sol b/src/script/Rpc.sol new file mode 100644 index 00000000..ae5f9c16 --- /dev/null +++ b/src/script/Rpc.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +import {rpc} from "../_internal/Rpc.sol"; diff --git a/src/test/Config.sol b/src/test/Config.sol index 46a1ae52..d5637b5b 100644 --- a/src/test/Config.sol +++ b/src/test/Config.sol @@ -1,4 +1,4 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13 <0.9.0; -import {config, Rpc} from "../_internal/Config.sol"; +import {config, RpcConfig} from "../_internal/Config.sol"; diff --git a/src/test/Rpc.sol b/src/test/Rpc.sol new file mode 100644 index 00000000..ae5f9c16 --- /dev/null +++ b/src/test/Rpc.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +import {rpc} from "../_internal/Rpc.sol"; diff --git a/test/examples/config/ConfigExample03.t.sol b/test/examples/config/ConfigExample03.t.sol index 15bff5ce..c2b6b5b7 100644 --- a/test/examples/config/ConfigExample03.t.sol +++ b/test/examples/config/ConfigExample03.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import {Test, expect, config, Rpc} from "vulcan/test.sol"; +import {Test, expect, config, RpcConfig} from "vulcan/test.sol"; /// @title Obtain all the RPC URLs using structs /// @dev Read all the RPC URL from the foundry configuration as structs contract ConfigExample is Test { function test() external { - Rpc[] memory rpcs = config.rpcUrlStructs(); + RpcConfig[] memory rpcs = config.rpcUrlStructs(); expect(rpcs.length).toEqual(2); expect(rpcs[0].name).toEqual("arbitrum"); diff --git a/test/examples/events/EventsExample01.t.sol b/test/examples/events/EventsExample01.t.sol index 198bec71..2e4249b9 100644 --- a/test/examples/events/EventsExample01.t.sol +++ b/test/examples/events/EventsExample01.t.sol @@ -1,4 +1,4 @@ -//// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {Test, expect, events, Log} from "vulcan/test.sol"; diff --git a/test/examples/rpc/RpcExample01.t.sol b/test/examples/rpc/RpcExample01.t.sol new file mode 100644 index 00000000..094695f2 --- /dev/null +++ b/test/examples/rpc/RpcExample01.t.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Test, expect} from "vulcan/test.sol"; +import {rpc} from "vulcan/test/Rpc.sol"; +import {Fork, forks} from "vulcan/test/Forks.sol"; + +/// @title Calling an RPC +/// @dev Calling an rpc using the `eth_chainId` method +contract RpcTest is Test { + function testNetVersion() external { + forks.create("https://rpc.mevblocker.io/fast").select(); + + string memory method = "eth_chainId"; + string memory params = "[]"; + + bytes memory data = rpc.call(method, params); + + uint8 chainId; + + assembly { + chainId := mload(add(data, 0x01)) + } + + expect(chainId).toEqual(block.chainid); + } +} diff --git a/test/modules/Config.t.sol b/test/modules/Config.t.sol index f7b8b912..81fa5e2b 100644 --- a/test/modules/Config.t.sol +++ b/test/modules/Config.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.13 <0.9.0; import {Test} from "../../src/test.sol"; import {expect} from "src/test/Expect.sol"; -import {config, Rpc} from "src/test/Config.sol"; +import {config, RpcConfig} from "src/test/Config.sol"; contract ConfigTest is Test { function testItCanObtainRpcUrls() external { @@ -23,7 +23,7 @@ contract ConfigTest is Test { } function testItCanObtainAllRpcUrlsAsStructs() external { - Rpc[] memory rpcs = config.rpcUrlStructs(); + RpcConfig[] memory rpcs = config.rpcUrlStructs(); expect(rpcs.length).toEqual(2); expect(rpcs[0].name).toEqual("arbitrum"); diff --git a/test/modules/Fmt.t.sol b/test/modules/Fmt.t.sol index 0c27af4a..8b5efb40 100644 --- a/test/modules/Fmt.t.sol +++ b/test/modules/Fmt.t.sol @@ -3,7 +3,6 @@ pragma solidity >=0.8.13 <0.9.0; import {Test} from "src/test.sol"; import {expect} from "src/test/Expect.sol"; -import {config, Rpc} from "src/test/Config.sol"; import {fmt} from "src/test/Fmt.sol"; import {Type, Placeholder} from "src/_internal/Fmt.sol"; diff --git a/test/modules/Rpc.t.sol b/test/modules/Rpc.t.sol new file mode 100644 index 00000000..6b146cbb --- /dev/null +++ b/test/modules/Rpc.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13 <0.9.0; + +import {Test, expect} from "vulcan/test.sol"; +import {rpc} from "vulcan/test/Rpc.sol"; +import {Fork, forks} from "vulcan/test/Forks.sol"; + +contract RpcTest is Test { + function testNetVersion() external { + string memory rpcUrl = "https://rpc.mevblocker.io/fast"; + string memory method = "eth_chainId"; + string memory params = "[]"; + + bytes memory data = rpc.call(rpcUrl, method, params); + + uint8 chainId; + + assembly { + chainId := mload(add(data, 0x01)) + } + + expect(chainId).toEqual(block.chainid); + } +}