CCQ/EVM: Testing library for building responses (#3768)
* CCQ/EVM: Testing library for building responses * Add request building stuff * Convert to a library * Don't pass in unnecessary lengths
This commit is contained in:
parent
c0b402cd1f
commit
0a49c6ee28
|
@ -9,6 +9,7 @@ import "../../contracts/Implementation.sol";
|
|||
import "../../contracts/Setup.sol";
|
||||
import "../../contracts/Wormhole.sol";
|
||||
import "forge-std/Test.sol";
|
||||
import "./QueryTest.sol";
|
||||
|
||||
// @dev A non-abstract QueryResponse contract
|
||||
contract QueryResponseContract is QueryResponse {
|
||||
|
@ -66,7 +67,6 @@ contract TestQueryResponse is Test {
|
|||
uint8 _version,
|
||||
uint16 _senderChainId,
|
||||
bytes memory _signature,
|
||||
uint32 _queryRequestLen,
|
||||
uint8 _queryRequestVersion,
|
||||
uint32 _queryRequestNonce,
|
||||
uint8 _numPerChainQueries,
|
||||
|
@ -74,15 +74,17 @@ contract TestQueryResponse is Test {
|
|||
uint8 _numPerChainResponses,
|
||||
bytes memory _perChainResponses
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_version,
|
||||
_senderChainId,
|
||||
_signature,
|
||||
_queryRequestLen,
|
||||
bytes memory queryRequest = QueryTest.buildOffChainQueryRequestBytes(
|
||||
_queryRequestVersion,
|
||||
_queryRequestNonce,
|
||||
_numPerChainQueries,
|
||||
_perChainQueries,
|
||||
_perChainQueries
|
||||
);
|
||||
return QueryTest.buildQueryResponseBytes(
|
||||
_version,
|
||||
_senderChainId,
|
||||
_signature,
|
||||
queryRequest,
|
||||
_numPerChainResponses,
|
||||
_perChainResponses
|
||||
);
|
||||
|
@ -116,21 +118,21 @@ contract TestQueryResponse is Test {
|
|||
}
|
||||
|
||||
function test_getResponseHash() public {
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes32 hash = queryResponse.getResponseHash(resp);
|
||||
bytes32 expectedHash = 0xed18e80906ffa80ce953a132a9cbbcf84186955f8fc8ce0322cd68622a58570e;
|
||||
assertEq(hash, expectedHash);
|
||||
}
|
||||
|
||||
function test_getResponseDigest() public {
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes32 digest = queryResponse.getResponseDigest(resp);
|
||||
bytes32 expectedDigest = 0x5b84b19c68ee0b37899230175a92ee6eda4c5192e8bffca1d057d811bb3660e2;
|
||||
assertEq(digest, expectedDigest);
|
||||
}
|
||||
|
||||
function test_verifyQueryResponseSignatures() public view {
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -139,7 +141,7 @@ contract TestQueryResponse is Test {
|
|||
}
|
||||
|
||||
function test_parseAndVerifyQueryResponse() public {
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -306,7 +308,7 @@ contract TestQueryResponse is Test {
|
|||
// Start of Solana Stuff ///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function test_verifyQueryResponseSignaturesForSolana() public view {
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, solanaSignature, solanaQueryRequestLen, solanaQueryRequestVersion, solanaQueryRequestNonce, solanaNumPerChainQueries, solanaPerChainQueries, solanaNumPerChainResponses, solanaPerChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, solanaSignature, solanaQueryRequestVersion, solanaQueryRequestNonce, solanaNumPerChainQueries, solanaPerChainQueries, solanaNumPerChainResponses, solanaPerChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -413,7 +415,7 @@ contract TestQueryResponse is Test {
|
|||
function testFuzz_parseAndVerifyQueryResponse_fuzzVersion(uint8 _version) public {
|
||||
vm.assume(_version != 1);
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(_version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(_version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -424,7 +426,7 @@ contract TestQueryResponse is Test {
|
|||
function testFuzz_parseAndVerifyQueryResponse_fuzzSenderChainId(uint16 _senderChainId) public {
|
||||
vm.assume(_senderChainId != 0);
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, _senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, _senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -437,7 +439,7 @@ contract TestQueryResponse is Test {
|
|||
// This signature isn't validated in the QueryResponse library, therefore it could be an 65 byte hex string
|
||||
vm.assume(_signature.length == 65);
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, _signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, _signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -450,7 +452,7 @@ contract TestQueryResponse is Test {
|
|||
// A signature that isn't 65 bytes long will always lead to a revert. The type of revert is unknown since it could be one of many.
|
||||
vm.assume(_signature.length != 65);
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, _signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, _signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -462,7 +464,7 @@ contract TestQueryResponse is Test {
|
|||
// We add 6 to account for version + nonce + numPerChainQueries
|
||||
vm.assume(_queryRequestLen != _perChainQueries.length + 6);
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, _queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, _perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, _perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -473,7 +475,7 @@ contract TestQueryResponse is Test {
|
|||
function testFuzz_parseAndVerifyQueryResponse_fuzzQueryRequestVersion(uint8 _version, uint8 _queryRequestVersion) public {
|
||||
vm.assume(_version != _queryRequestVersion);
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(_version, senderChainId, signature, queryRequestLen, _queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(_version, senderChainId, signature, _queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -482,7 +484,7 @@ contract TestQueryResponse is Test {
|
|||
}
|
||||
|
||||
function testFuzz_parseAndVerifyQueryResponse_fuzzQueryRequestNonce(uint32 _queryRequestNonce) public {
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, _queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, _queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -494,7 +496,7 @@ contract TestQueryResponse is Test {
|
|||
function testFuzz_parseAndVerifyQueryResponse_fuzzNumPerChainQueriesAndResponses(uint8 _numPerChainQueries, uint8 _numPerChainResponses) public {
|
||||
vm.assume(_numPerChainQueries != _numPerChainResponses);
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, _numPerChainQueries, perChainQueries, _numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, _numPerChainQueries, perChainQueries, _numPerChainResponses, perChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -508,7 +510,7 @@ contract TestQueryResponse is Test {
|
|||
|
||||
bytes memory packedPerChainQueries = abi.encodePacked(_requestChainId, uint8(_requestQueryType), uint32(perChainQueriesInner.length), perChainQueriesInner);
|
||||
bytes memory packedPerChainResponses = abi.encodePacked(_responseChainId, uint8(_requestQueryType), uint32(perChainResponsesInner.length), perChainResponsesInner);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -523,7 +525,7 @@ contract TestQueryResponse is Test {
|
|||
|
||||
bytes memory packedPerChainQueries = abi.encodePacked(uint16(0x0005), uint8(_requestQueryType), uint32(perChainQueriesInner.length), perChainQueriesInner);
|
||||
bytes memory packedPerChainResponses = abi.encodePacked(uint16(0x0005), uint8(_responseQueryType), uint32(perChainResponsesInner.length), perChainResponsesInner);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -536,7 +538,7 @@ contract TestQueryResponse is Test {
|
|||
|
||||
bytes memory packedPerChainQueries = abi.encodePacked(uint16(0x0005), uint8(_requestQueryType), uint32(perChainQueriesInner.length), perChainQueriesInner);
|
||||
bytes memory packedPerChainResponses = abi.encodePacked(uint16(0x0005), uint8(_requestQueryType), uint32(perChainResponsesInner.length), perChainResponsesInner);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -549,7 +551,7 @@ contract TestQueryResponse is Test {
|
|||
|
||||
bytes memory packedPerChainQueries = abi.encodePacked(uint16(0x0005), uint8(0x01), _queryLength, perChainQueriesInner);
|
||||
bytes memory packedPerChainResponses = abi.encodePacked(uint16(0x0005), uint8(0x01), uint32(perChainResponsesInner.length), perChainResponsesInner);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, packedPerChainQueries, numPerChainResponses, packedPerChainResponses);
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = getSignature(resp);
|
||||
IWormhole.Signature[] memory signatures = new IWormhole.Signature[](1);
|
||||
signatures[0] = IWormhole.Signature({r: sigR, s: sigS, v: sigV, guardianIndex: sigGuardianIndex});
|
||||
|
@ -581,7 +583,7 @@ contract TestQueryResponse is Test {
|
|||
function testFuzz_verifyQueryResponseSignatures_validSignatureWrongPrefix(bytes calldata responsePrefix) public {
|
||||
vm.assume(keccak256(responsePrefix) != keccak256(queryResponse.responsePrefix()));
|
||||
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestLen, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes memory resp = concatenateQueryResponseBytesOffChain(version, senderChainId, signature, queryRequestVersion, queryRequestNonce, numPerChainQueries, perChainQueries, numPerChainResponses, perChainResponses);
|
||||
bytes32 responseDigest = keccak256(abi.encodePacked(responsePrefix, keccak256(resp)));
|
||||
|
||||
(uint8 sigV, bytes32 sigR, bytes32 sigS) = vm.sign(DEVNET_GUARDIAN_PRIVATE_KEY, responseDigest);
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
// SPDX-License-Identifier: Apache 2
|
||||
|
||||
// forge test --match-contract QueryTest
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
// @dev QueryTest is a library to build Cross Chain Query (CCQ) responses for testing purposes.
|
||||
library QueryTest {
|
||||
//
|
||||
// Query Request stuff
|
||||
//
|
||||
|
||||
/// @dev buildOffChainQueryRequestBytes builds an off chain query request from the specified fields.
|
||||
function buildOffChainQueryRequestBytes(
|
||||
uint8 _version,
|
||||
uint32 _nonce,
|
||||
uint8 _numPerChainQueries,
|
||||
bytes memory _perChainQueries
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_version,
|
||||
_nonce,
|
||||
_numPerChainQueries,
|
||||
_perChainQueries // Each created by buildPerChainRequestBytes()
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildPerChainRequestBytes builds a per chain request from the specified fields.
|
||||
function buildPerChainRequestBytes(
|
||||
uint16 _chainId,
|
||||
uint8 _queryType,
|
||||
bytes memory _queryBytes
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_chainId,
|
||||
_queryType,
|
||||
uint32(_queryBytes.length),
|
||||
_queryBytes
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallRequestBytes builds an eth_call query request from the specified fields.
|
||||
function buildEthCallRequestBytes(
|
||||
bytes memory _blockId,
|
||||
uint8 _numCallData,
|
||||
bytes memory _callData // Created with buildEthCallDataBytes()
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
uint32(_blockId.length),
|
||||
_blockId,
|
||||
_numCallData,
|
||||
_callData
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallByTimestampRequestBytes builds an eth_call_by_timestamp query request from the specified fields.
|
||||
function buildEthCallByTimestampRequestBytes(
|
||||
uint64 _targetTimeUs,
|
||||
bytes memory _targetBlockHint,
|
||||
bytes memory _followingBlockHint,
|
||||
uint8 _numCallData,
|
||||
bytes memory _callData // Created with buildEthCallDataBytes()
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_targetTimeUs,
|
||||
uint32(_targetBlockHint.length),
|
||||
_targetBlockHint,
|
||||
uint32(_followingBlockHint.length),
|
||||
_followingBlockHint,
|
||||
_numCallData,
|
||||
_callData
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallWithFinalityRequestBytes builds an eth_call_with_finality query request from the specified fields.
|
||||
function buildEthCallWithFinalityRequestBytes(
|
||||
bytes memory _blockId,
|
||||
bytes memory _finality,
|
||||
uint8 _numCallData,
|
||||
bytes memory _callData // Created with buildEthCallDataBytes()
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
uint32(_blockId.length),
|
||||
_blockId,
|
||||
uint32(_finality.length),
|
||||
_finality,
|
||||
_numCallData,
|
||||
_callData
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallDataBytes builds the call data associated with one of the eth_call family of queries.
|
||||
function buildEthCallDataBytes(
|
||||
address _contractAddress,
|
||||
bytes memory _callData
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_contractAddress,
|
||||
uint32(_callData.length),
|
||||
_callData
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildSolanaAccountRequestBytes builds an sol_account query request from the specified fields.
|
||||
function buildSolanaAccountRequestBytes(
|
||||
bytes memory _commitment,
|
||||
uint64 _minContextSlot,
|
||||
uint64 _dataSliceOffset,
|
||||
uint64 _dataSliceLength,
|
||||
uint8 _numAccounts,
|
||||
bytes memory _accounts // Each account is 32 bytes.
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
uint32(_commitment.length),
|
||||
_commitment,
|
||||
_minContextSlot,
|
||||
_dataSliceOffset,
|
||||
_dataSliceLength,
|
||||
_numAccounts,
|
||||
_accounts
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Query Response stuff
|
||||
//
|
||||
|
||||
/// @dev buildQueryResponseBytes builds a query response from the specified fields.
|
||||
function buildQueryResponseBytes(
|
||||
uint8 _version,
|
||||
uint16 _senderChainId,
|
||||
bytes memory _signature,
|
||||
bytes memory _queryRequest,
|
||||
uint8 _numPerChainResponses,
|
||||
bytes memory _perChainResponses
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_version,
|
||||
_senderChainId,
|
||||
_signature,
|
||||
uint32(_queryRequest.length),
|
||||
_queryRequest,
|
||||
_numPerChainResponses,
|
||||
_perChainResponses // Each created by buildPerChainResponseBytes()
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildPerChainResponseBytes builds a per chain response from the specified fields.
|
||||
function buildPerChainResponseBytes(
|
||||
uint16 _chainId,
|
||||
uint8 _queryType,
|
||||
bytes memory _responseBytes
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_chainId,
|
||||
_queryType,
|
||||
uint32(_responseBytes.length),
|
||||
_responseBytes
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallResponseBytes builds an eth_call response from the specified fields.
|
||||
function buildEthCallResponseBytes(
|
||||
uint64 _blockNumber,
|
||||
bytes32 _blockHash,
|
||||
uint64 _blockTimeUs,
|
||||
uint8 _numResults,
|
||||
bytes memory _results // Created with buildEthCallResultBytes()
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_blockNumber,
|
||||
_blockHash,
|
||||
_blockTimeUs,
|
||||
_numResults,
|
||||
_results
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallByTimestampResponseBytes builds an eth_call_by_timestamp response from the specified fields.
|
||||
function buildEthCallByTimestampResponseBytes(
|
||||
uint64 _targetBlockNumber,
|
||||
bytes32 _targetBlockHash,
|
||||
uint64 _targetBlockTimeUs,
|
||||
uint64 _followingBlockNumber,
|
||||
bytes32 _followingBlockHash,
|
||||
uint64 _followingBlockTimeUs,
|
||||
uint8 _numResults,
|
||||
bytes memory _results // Created with buildEthCallResultBytes()
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_targetBlockNumber,
|
||||
_targetBlockHash,
|
||||
_targetBlockTimeUs,
|
||||
_followingBlockNumber,
|
||||
_followingBlockHash,
|
||||
_followingBlockTimeUs,
|
||||
_numResults,
|
||||
_results
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallWithFinalityResponseBytes builds an eth_call_with_finality response from the specified fields. Note that it is currently the same as buildEthCallResponseBytes.
|
||||
function buildEthCallWithFinalityResponseBytes(
|
||||
uint64 _blockNumber,
|
||||
bytes32 _blockHash,
|
||||
uint64 _blockTimeUs,
|
||||
uint8 _numResults,
|
||||
bytes memory _results // Created with buildEthCallResultBytes()
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_blockNumber,
|
||||
_blockHash,
|
||||
_blockTimeUs,
|
||||
_numResults,
|
||||
_results
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildEthCallResultBytes builds an eth_call result from the specified fields.
|
||||
function buildEthCallResultBytes(
|
||||
bytes memory _result
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
uint32(_result.length),
|
||||
_result
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev buildSolanaAccountResponseBytes builds a sol_account response from the specified fields.
|
||||
function buildSolanaAccountResponseBytes(
|
||||
uint64 _slotNumber,
|
||||
uint64 _blockTimeUs,
|
||||
bytes32 _blockHash,
|
||||
uint8 _numResults,
|
||||
bytes memory _results // Created with buildEthCallResultBytes()
|
||||
) internal pure returns (bytes memory){
|
||||
return abi.encodePacked(
|
||||
_slotNumber,
|
||||
_blockTimeUs,
|
||||
_blockHash,
|
||||
_numResults,
|
||||
_results
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
// SPDX-License-Identifier: Apache 2
|
||||
|
||||
// forge test --match-contract QueryTest
|
||||
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
import "./QueryTest.sol";
|
||||
|
||||
contract TestQueryTest is Test {
|
||||
//
|
||||
// Query Request tests
|
||||
//
|
||||
|
||||
function test_buildOffChainQueryRequestBytes() public {
|
||||
bytes memory req = QueryTest.buildOffChainQueryRequestBytes(
|
||||
/* version */ 1,
|
||||
/* nonce */ 1,
|
||||
/* numPerChainQueries */ 1,
|
||||
/* perChainQueries */ hex"0002010000004200000005307837343402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567"
|
||||
);
|
||||
assertEq(req, hex"0100000001010002010000004200000005307837343402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567");
|
||||
}
|
||||
|
||||
function test_buildPerChainRequestBytes() public {
|
||||
bytes memory pcr = QueryTest.buildPerChainRequestBytes(
|
||||
/* chainId */ 2,
|
||||
/* queryType */ 1,
|
||||
/* queryBytes */ hex"00000005307837343402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567"
|
||||
);
|
||||
assertEq(pcr, hex"0002010000004200000005307837343402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567");
|
||||
}
|
||||
|
||||
function test_buildEthCallRequestBytes() public {
|
||||
bytes memory ecr = QueryTest.buildEthCallRequestBytes(
|
||||
/* blockId */ "0x744",
|
||||
/* numCallData */ 2,
|
||||
/* callData */ hex"ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567"
|
||||
);
|
||||
assertEq(ecr, hex"00000005307837343402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567");
|
||||
}
|
||||
|
||||
function test_buildEthCallByTimestampRequestBytes() public {
|
||||
bytes memory ecr = QueryTest.buildEthCallByTimestampRequestBytes(
|
||||
/* targetTimeUs */ 0x10642ac0,
|
||||
/* targetBlockHint */ "0x15d",
|
||||
/* followingBlockHint */ "0x15e",
|
||||
/* numCallData */ 2,
|
||||
/* callData */ hex"ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567"
|
||||
);
|
||||
assertEq(ecr, hex"0000000010642ac000000005307831356400000005307831356502ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567");
|
||||
}
|
||||
|
||||
function test_buildEthCallWithFinalityRequestBytes() public {
|
||||
bytes memory ecr = QueryTest.buildEthCallWithFinalityRequestBytes(
|
||||
/* blockId */ "0x1f8",
|
||||
/* finality */ "finalized",
|
||||
/* numCallData */ 2,
|
||||
/* callData */ hex"ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567"
|
||||
);
|
||||
assertEq(ecr, hex"0000000530783166380000000966696e616c697a656402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567");
|
||||
}
|
||||
|
||||
function test_buildEthCallDataBytes() public {
|
||||
bytes memory ecd1 = QueryTest.buildEthCallDataBytes(
|
||||
/* contractAddress */ 0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E,
|
||||
/* callData */ hex"06fdde03"
|
||||
);
|
||||
assertEq(ecd1, hex"ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03");
|
||||
bytes memory ecd2 = QueryTest.buildEthCallDataBytes(
|
||||
/* contractAddress */ 0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E,
|
||||
/* callData */ hex"313ce567"
|
||||
);
|
||||
assertEq(ecd2, hex"ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567");
|
||||
}
|
||||
|
||||
function test_buildSolanaAccountRequestBytes() public {
|
||||
bytes memory ecr = QueryTest.buildSolanaAccountRequestBytes(
|
||||
/* commitment */ "finalized",
|
||||
/* minContextSlot */ 8069,
|
||||
/* dataSliceOffset */ 10,
|
||||
/* dataSliceLength */ 20,
|
||||
/* numAccounts */ 2,
|
||||
/* accounts */ hex"165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3019c006c48c8cbf33849cb07a3f936159cc523f9591cb1999abd45890ec5fee9b7"
|
||||
);
|
||||
assertEq(ecr, hex"0000000966696e616c697a65640000000000001f85000000000000000a000000000000001402165809739240a0ac03b98440fe8985548e3aa683cd0d4d9df5b5659669faa3019c006c48c8cbf33849cb07a3f936159cc523f9591cb1999abd45890ec5fee9b7");
|
||||
}
|
||||
|
||||
//
|
||||
// Query Response tests
|
||||
//
|
||||
|
||||
function test_buildQueryResponseBytes() public {
|
||||
bytes memory resp = QueryTest.buildQueryResponseBytes(
|
||||
/* version */ 1,
|
||||
/* senderChainId */ 0,
|
||||
/* signature */ hex"11b03bdbbe15a8f12b803d2193de5ddff72d92eaabd2763553ec3c3133182d1443719a05e2b65c87b923c6bd8aeff49f34937f90f3ab7cd33449388c60fa30a301",
|
||||
/* queryRequest */ hex"0100000001010002010000004200000005307837343402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce567",
|
||||
/* numPerChainResponses */ 1,
|
||||
/* perChainResponses */ hex"000201000000b900000000000007446a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b000000006ab13b8002000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012"
|
||||
);
|
||||
assertEq(resp, hex"01000011b03bdbbe15a8f12b803d2193de5ddff72d92eaabd2763553ec3c3133182d1443719a05e2b65c87b923c6bd8aeff49f34937f90f3ab7cd33449388c60fa30a3010000004f0100000001010002010000004200000005307837343402ddb64fe46a91d46ee29420539fc25fd07c5fea3e0000000406fdde03ddb64fe46a91d46ee29420539fc25fd07c5fea3e00000004313ce56701000201000000b900000000000007446a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b000000006ab13b8002000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012");
|
||||
}
|
||||
|
||||
function test_buildPerChainResponseBytes() public {
|
||||
bytes memory pcr = QueryTest.buildPerChainResponseBytes(
|
||||
/* chainId */ 2,
|
||||
/* queryType */ 1,
|
||||
/* responseBytes */ hex"00000000000007446a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b000000006ab13b8002000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012"
|
||||
);
|
||||
assertEq(pcr, hex"000201000000b900000000000007446a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b000000006ab13b8002000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012");
|
||||
}
|
||||
|
||||
function test_buildEthCallResponseBytes() public {
|
||||
bytes memory ecr = QueryTest.buildEthCallResponseBytes(
|
||||
/* blockNumber */ 1860,
|
||||
/* blockHash */ hex"6a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b",
|
||||
/* blockTimeUs */ 0x6ab13b80,
|
||||
/* numResults */ 2,
|
||||
/* results */ hex"000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012"
|
||||
);
|
||||
assertEq(ecr, hex"00000000000007446a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b000000006ab13b8002000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012");
|
||||
}
|
||||
|
||||
function test_buildEthCallByTimestampResponseBytes() public {
|
||||
bytes memory ecr = QueryTest.buildEthCallByTimestampResponseBytes(
|
||||
/* targetBlockNumber */ 349,
|
||||
/* targetBlockHash */ hex"966cd846f812be43c4ee2d310f962bc592ba944c66de878e53584b8e75c6051f",
|
||||
/* targetBlockTimeUs */ 0x10642ac0,
|
||||
/* followingBlockNumber */ 350,
|
||||
/* followingBlockHash */ hex"04b022afaab8da2dd80bd8e6ae55e6303473a5e1de846a5de76d619e162429ce",
|
||||
/* followingBlockTimeUs */ 0x10736d00,
|
||||
/* numResults */ 2,
|
||||
/* results */ hex"000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012"
|
||||
);
|
||||
assertEq(ecr, hex"000000000000015d966cd846f812be43c4ee2d310f962bc592ba944c66de878e53584b8e75c6051f0000000010642ac0000000000000015e04b022afaab8da2dd80bd8e6ae55e6303473a5e1de846a5de76d619e162429ce0000000010736d0002000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012");
|
||||
}
|
||||
|
||||
function test_buildEthCallWithFinalityResponseBytes() public {
|
||||
bytes memory ecr = QueryTest.buildEthCallWithFinalityResponseBytes(
|
||||
/* blockNumber */ 1860,
|
||||
/* blockHash */ hex"6a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b",
|
||||
/* blockTimeUs */ 0x6ab13b80,
|
||||
/* numResults */ 2,
|
||||
/* results */ hex"000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012"
|
||||
);
|
||||
assertEq(ecr, hex"00000000000007446a0b819aee8945e659e37537a0bdbe03c06275be23e499819138d1eee8337e9b000000006ab13b8002000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012");
|
||||
}
|
||||
|
||||
function test_buildEthCallResultBytes() public {
|
||||
bytes memory ecr1 = QueryTest.buildEthCallResultBytes(
|
||||
/* result */ hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000"
|
||||
);
|
||||
assertEq(ecr1, hex"000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d5772617070656420457468657200000000000000000000000000000000000000");
|
||||
bytes memory ecr2 = QueryTest.buildEthCallResultBytes(
|
||||
/* result */ hex"0000000000000000000000000000000000000000000000000000000000000012"
|
||||
);
|
||||
assertEq(ecr2, hex"000000200000000000000000000000000000000000000000000000000000000000000012");
|
||||
}
|
||||
|
||||
function test_buildSolanaAccountResponseBytes() public {
|
||||
bytes memory ecr = QueryTest.buildSolanaAccountResponseBytes(
|
||||
/* slotNumber */ 5603,
|
||||
/* blockTimeUs */ 0x610cdf2510500,
|
||||
/* blockHash */ hex"e0eca895a92c0347e30538cd07c50777440de58e896dd13ff86ef0dae3e12552",
|
||||
/* numResults */ 2,
|
||||
/* results */ hex"0000000000164d6000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90000005201000000574108aed69daf7e625a361864b1f74d13702f2ca56de9660e566d1d8691848d0000e8890423c78a09010000000000000000000000000000000000000000000000000000000000000000000000000000000000164d6000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90000005201000000574108aed69daf7e625a361864b1f74d13702f2ca56de9660e566d1d8691848d01000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
);
|
||||
assertEq(ecr, hex"00000000000015e3000610cdf2510500e0eca895a92c0347e30538cd07c50777440de58e896dd13ff86ef0dae3e12552020000000000164d6000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90000005201000000574108aed69daf7e625a361864b1f74d13702f2ca56de9660e566d1d8691848d0000e8890423c78a09010000000000000000000000000000000000000000000000000000000000000000000000000000000000164d6000000000000000000006ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a90000005201000000574108aed69daf7e625a361864b1f74d13702f2ca56de9660e566d1d8691848d01000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue