diff --git a/src/protocols/EthJsonRPC.sol b/src/protocols/EthJsonRPC.sol index 0ba1a4c..ba60b3a 100644 --- a/src/protocols/EthJsonRPC.sol +++ b/src/protocols/EthJsonRPC.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8.13; import "../suavelib/Suave.sol"; import "solady/src/utils/JSONParserLib.sol"; import "solady/src/utils/LibString.sol"; +import "forge-std/console.sol"; +import "../utils/HexStrings.sol"; /// @notice EthJsonRPC is a library with utilities to interact with an Ethereum JSON-RPC endpoint. contract EthJsonRPC { @@ -30,6 +32,24 @@ contract EthJsonRPC { return val; } + /// @notice call a contract function. + /// @param to the address of the contract. + /// @param data the data of the function. + /// @return the result of the function call. + function call(address to, bytes memory data) public returns (bytes memory) { + bytes memory body = abi.encodePacked( + '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"', + LibString.toHexStringChecksummed(to), + '","data":"', + LibString.toHexString(data), + '"},"latest"],"id":1}' + ); + + JSONParserLib.Item memory item = doRequest(string(body)); + bytes memory result = HexStrings.fromHexString(_stripQuotesAndPrefix(item.value())); + return result; + } + function doRequest(string memory body) public returns (JSONParserLib.Item memory) { Suave.HttpRequest memory request; request.method = "POST"; @@ -44,6 +64,15 @@ contract EthJsonRPC { return item.at('"result"'); } + function _stripQuotesAndPrefix(string memory s) internal pure returns (string memory) { + bytes memory strBytes = bytes(s); + bytes memory result = new bytes(strBytes.length - 4); + for (uint256 i = 3; i < strBytes.length - 1; i++) { + result[i - 3] = strBytes[i]; + } + return string(result); + } + function trimQuotes(string memory input) private pure returns (string memory) { bytes memory inputBytes = bytes(input); require( diff --git a/test/protocols/EthJsonRPC.t.sol b/test/protocols/EthJsonRPC.t.sol index 47ff4a8..3a855df 100644 --- a/test/protocols/EthJsonRPC.t.sol +++ b/test/protocols/EthJsonRPC.t.sol @@ -14,6 +14,15 @@ contract EthJsonRPCTest is Test, SuaveEnabled { assertEq(nonce, 0); } + function testEthJsonRPCCall() public { + EthJsonRPC ethjsonrpc = getEthJsonRPC(); + + bytes memory data = abi.encodeWithSignature("get_deposit_count()"); + bytes memory result = ethjsonrpc.call(address(0x00000000219ab540356cBB839Cbe05303d7705Fa), data); + + require(result.length > 0, "result is empty"); + } + function getEthJsonRPC() public returns (EthJsonRPC ethjsonrpc) { try vm.envString("JSONRPC_ENDPOINT") returns (string memory endpoint) { ethjsonrpc = new EthJsonRPC(endpoint);