Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions evmrpc/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,10 @@ func getCommonFilterLogTests() []GetFilterLogTests {
}

func TestFilterGetLogs(t *testing.T) {
t.Skip()
testFilterGetLogs(t, "eth", getCommonFilterLogTests())
}

func TestFilterSeiGetLogs(t *testing.T) {
t.Skip()
// make sure we pass all the eth_ namespace tests
testFilterGetLogs(t, "sei", getCommonFilterLogTests())

Expand Down Expand Up @@ -245,7 +243,6 @@ func TestFilterSeiGetLogs(t *testing.T) {
}

func TestFilterEthEndpointReturnsNormalEvmLogEvenIfSyntheticLogIsInSameBlock(t *testing.T) {
t.Skip()
testFilterGetLogs(t, "eth", []GetFilterLogTests{
{
name: "normal evm log is returned even if synthetic log is in the same block",
Expand Down Expand Up @@ -300,7 +297,6 @@ func testFilterGetLogs(t *testing.T, namespace string, tests []GetFilterLogTests
}

func TestFilterGetFilterLogs(t *testing.T) {
t.Skip()
filterCriteria := map[string]interface{}{
"fromBlock": "0x2",
"toBlock": "0x2",
Expand All @@ -324,7 +320,6 @@ func TestFilterGetFilterLogs(t *testing.T) {
}

func TestFilterGetFilterChanges(t *testing.T) {
t.Skip()
filterCriteria := map[string]interface{}{
"fromBlock": "0x2",
}
Expand All @@ -333,8 +328,7 @@ func TestFilterGetFilterChanges(t *testing.T) {

resObj = sendRequest(t, TestPort, evmrpc.GetFilterChangesMethod, filterId)
logs := resObj["result"].([]interface{})
// After tightening block/receipt matching, fromBlock=0x2 now yields 5 logs total
require.Equal(t, 5, len(logs))
require.Equal(t, 7, len(logs))
logObj := logs[0].(map[string]interface{})
require.Equal(t, "0x2", logObj["blockNumber"].(string))

Expand Down Expand Up @@ -417,7 +411,6 @@ func TestFilterGetFilterChangesKeepsFilterAlive(t *testing.T) {
}

func TestGetLogsBlockHashIsNotZero(t *testing.T) {
t.Skip()
t.Parallel()
// Test that eth_getLogs returns logs with correct blockHash (not zero hash)
filterCriteria := map[string]interface{}{
Expand Down
6 changes: 3 additions & 3 deletions evmrpc/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func newInfoAPIWithWatermarks(ctxProvider func(int64) sdk.Context) *evmrpc.InfoA
func TestBlockNumber(t *testing.T) {
resObj := sendRequestGood(t, "blockNumber")
result := resObj["result"].(string)
require.Equal(t, fmt.Sprintf("0x%x", MockHeight8), result)
require.Equal(t, fmt.Sprintf("0x%x", MockHeight103), result)
}

func TestChainID(t *testing.T) {
Expand Down Expand Up @@ -91,13 +91,13 @@ func TestFeeHistory(t *testing.T) {

Ctx = Ctx.WithBlockHeight(1) // Simulate context with a specific block height

latestHex := fmt.Sprintf("0x%x", MockHeight8)
latestHex := fmt.Sprintf("0x%x", MockHeight103)
testCases := []feeHistoryTestCase{
{name: "Valid request by number", blockCount: 1, lastBlock: latestHex, rewardPercentiles: []interface{}{0.5}, expectedOldest: latestHex},
{name: "Valid request by latest", blockCount: 1, lastBlock: "latest", rewardPercentiles: []interface{}{0.5}, expectedOldest: latestHex},
{name: "Valid request by earliest", blockCount: 1, lastBlock: "earliest", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1"},
{name: "Request on the same block", blockCount: 1, lastBlock: "0x1", rewardPercentiles: []interface{}{0.5}, expectedOldest: "0x1"},
{name: "Request on future block", blockCount: 1, lastBlock: fmt.Sprintf("0x%x", MockHeight8+1), rewardPercentiles: []interface{}{0.5}, expectedError: fmt.Errorf("requested last block %d is not yet available; safe latest is %d", MockHeight8+1, MockHeight8)},
{name: "Request on future block", blockCount: 1, lastBlock: fmt.Sprintf("0x%x", MockHeight103+1), rewardPercentiles: []interface{}{0.5}, expectedError: fmt.Errorf("requested last block %d is not yet available; safe latest is %d", MockHeight103+1, MockHeight103)},
{name: "Block count truncates", blockCount: 1025, lastBlock: "latest", rewardPercentiles: []interface{}{25}, expectedOldest: "0x1"},
{name: "Too many percentiles", blockCount: 10, lastBlock: "latest", rewardPercentiles: make([]interface{}, 101), expectedError: errors.New("rewardPercentiles length must be less than or equal to 100")},
{name: "Invalid percentiles order", blockCount: 10, lastBlock: "latest", rewardPercentiles: []interface{}{99, 1}, expectedError: errors.New("invalid reward percentiles: must be ascending and between 0 and 100")},
Expand Down
53 changes: 40 additions & 13 deletions evmrpc/setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,16 +610,20 @@ func init() {
_ = store.SetEarliestVersion(1)
}
ctxProvider := func(height int64) sdk.Context {
// All branches set ClosestUpgradeName so any upgrade-name-sensitive
// gate (e.g. isReceiptFromAnteError) hits the production post-v5.8.0
// path; see LatestCtxUpgradeName above.
if height == MockHeight2 {
return MultiTxCtx.WithIsTracing(true)
return MultiTxCtx.WithIsTracing(true).WithClosestUpgradeName(LatestCtxUpgradeName)
}
if height == evmrpc.LatestCtxHeight {
// See LatestCtxUpgradeName above — make the latest ctx look
// post-v5.8.0 so any consumer that branches on upgrade name
// sees the production path, not the pre-v5.8.0 fallback.
return baseCtx.WithIsTracing(true).WithClosestUpgradeName(LatestCtxUpgradeName)
// Report MockHeight103 so the WatermarkManager's latest watermark
// covers every block the mocks produce — taking the minimum
// across height sources, a stale height here would cap log
// queries below the mocked blocks.
return baseCtx.WithBlockHeight(MockHeight103).WithIsTracing(true).WithClosestUpgradeName(LatestCtxUpgradeName)
}
return Ctx.WithIsTracing(true)
return Ctx.WithIsTracing(true).WithClosestUpgradeName(LatestCtxUpgradeName)
}
// Start good http server
goodConfig := evmrpcconfig.DefaultConfig
Expand Down Expand Up @@ -1062,7 +1066,13 @@ func setupLogs() {
Topics: []string{"0x0000000000000000000000000000000000000000000000000000000000000234", "0x0000000000000000000000000000000000000000000000000000000000000789"},
Synthetic: true,
}},
EffectiveGasPrice: 0,
// Non-zero EffectiveGasPrice avoids the Status==0 && EGP==0
// ante-error nonce-continuity check in filterTransactions, which
// would otherwise wrongly exclude this synthetic receipt because the
// test sender's nonce state isn't seeded for synthetic-tx ordering.
// The TxType=ShellEVMTxType marker still gates eth-namespace
// inclusion, so eth-side tests keep filtering it out.
EffectiveGasPrice: 100,
})
// Also create a normal (non-synthetic) receipt in block 100 with two logs
CtxBlock100 := Ctx.WithBlockHeight(MockHeight100)
Expand All @@ -1082,18 +1092,35 @@ func setupLogs() {
EffectiveGasPrice: 100,
})
CtxMock = Ctx.WithBlockHeight(MockHeight103)
// Synthetic log at latest (MockHeight103) so default-range eth_getLogs
// queries — which resolve to [latest, latest] — can exercise the
// sei-namespace synthetic-inclusion path.
bloomSynth103 := ethtypes.CreateBloom(&ethtypes.Receipt{Logs: []*ethtypes.Log{{
Address: common.HexToAddress("0x1111111111111111111111111111111111111116"),
Topics: []common.Hash{
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000234"),
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000789"),
},
}}})
EVMKeeper.MockReceipt(CtxMock, common.HexToHash(TestSyntheticTxHash), &types.Receipt{
TxType: types.ShellEVMTxType,
BlockNumber: MockHeight103,
TransactionIndex: 2,
TxHashHex: TestSyntheticTxHash,
LogsBloom: bloomSynth103[:],
Logs: []*types.Log{{
Address: "0x1111111111111111111111111111111111111116",
Topics: []string{"0x0000000000000000000000000000000000000000000000000000000000000234", "0x0000000000000000000000000000000000000000000000000000000000000789"},
Synthetic: true,
}},
// Non-zero EGP so this synthetic receipt isn't excluded by the
// Status==0 && EGP==0 ante-error nonce-continuity gate in
// filterTransactions; see the block-100 synth receipt above for the
// same rationale.
EffectiveGasPrice: 100,
})
CtxDebugTrace := Ctx.WithBlockHeight(MockHeight8)
EVMKeeper.MockReceipt(CtxDebugTrace, common.HexToHash(DebugTraceHashHex), &types.Receipt{
BlockNumber: MockHeight8,
TransactionIndex: 0,
TxHashHex: DebugTraceHashHex,
})
// DebugTraceHashHex == tx1.Hash(); tx1's receipt (mocked earlier with full
// Logs) is what debug_traceTransaction and log-filter queries both rely on.
CtxDebugTracePanic := Ctx.WithBlockHeight(MockHeight103)
EVMKeeper.MockReceipt(CtxDebugTracePanic, common.HexToHash(TestNonPanicTxHash), &types.Receipt{
BlockNumber: MockHeight103,
Expand Down
20 changes: 10 additions & 10 deletions evmrpc/subscribe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,14 @@ func TestSubscribeEmptyLogs(t *testing.T) {
}

func TestSubscribeNewLogs(t *testing.T) {
t.Skip()
// Query MockHeight8 directly: the mocks place a matching log there
// (tx1's receipt with address 0x1111…1111 and topic 0x1111…1111).
// Using a fixed historical range avoids the FromBlock=0+ToBlock=latest
// rewrite path so this test stays decoupled from "latest" placement;
// TestSubscribeEmptyLogs covers the empty-filter handshake path.
data := map[string]interface{}{
"fromBlock": "0x0",
"toBlock": "latest",
"fromBlock": fmt.Sprintf("0x%x", MockHeight8),
"toBlock": fmt.Sprintf("0x%x", MockHeight8),
"address": []common.Address{
common.HexToAddress("0x1111111111111111111111111111111111111111"),
},
Expand Down Expand Up @@ -233,16 +237,12 @@ func TestSubscribeNewLogs(t *testing.T) {
t.Fatal("Subscription ID does not match")
}
resultMap := paramMap["result"].(map[string]interface{})
if resultMap["address"] != "0x1111111111111111111111111111111111111111" && resultMap["address"] != "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" {
t.Fatalf("Unexpected address, got %v", resultMap["address"])
}
require.Equal(t, "0x1111111111111111111111111111111111111111", resultMap["address"])
firstTopic := resultMap["topics"].([]interface{})[0].(string)
if firstTopic != "0x1111111111111111111111111111111111111111111111111111111111111111" {
t.Fatalf("Unexpected topic, got %v", firstTopic)
}
require.Equal(t, "0x1111111111111111111111111111111111111111111111111111111111111111", firstTopic)
case <-timer.C:
if !receivedSubMsg || !receivedEvents {
t.Fatal("No message received within 5 seconds")
t.Fatal("No subscription ack or log notification within 2 seconds")
}
return
}
Expand Down
29 changes: 29 additions & 0 deletions integration_test/evm_module/scripts/contracts/emitter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT
// Contract used by the ws_test eth_subscribe(logs) integration test. The
// constructor emits one LOG1 with a fixed 32-byte topic; the deploy tx
// receipt therefore contains exactly one log, whose address equals the
// newly-created contract address. The test subscribes to the deploy
// block + emitter address and asserts the log is delivered over the WS.
//
// emitter_contract.hex is hand-crafted (no solc required). Init code:
//
// 7f<32-byte topic> PUSH32 topic (0x4242…4242, easy to spot in logs)
// 6000 PUSH1 0 ; LOG data size
// 6000 PUSH1 0 ; LOG data offset
// a1 LOG1
// 6001 PUSH1 1 ; runtime size
// 6000 PUSH1 0 ; runtime offset (memory is zero-init,
// so memory[0] = 0x00 = STOP)
// f3 RETURN
//
// Solidity reference (not compiled — only the .hex is used at deploy time):

pragma solidity ^0.8.0;

contract Emitter {
constructor() {
assembly {
log1(0, 0, 0x4242424242424242424242424242424242424242424242424242424242424242)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
7f424242424242424242424242424242424242424242424242424242424242424260006000a160016000f3
26 changes: 26 additions & 0 deletions integration_test/evm_module/scripts/evm_rpc_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ RECIPIENT="${SEI_EVM_IO_TX_RECIPIENT:-0xF87A299e6bC7bEba58dbBe5a5Aa21d49bCD16D52
PROJECT_ROOT="${SEI_EVM_IO_PROJECT_ROOT:-/sei-protocol/sei-chain}"
CONTRACT_HEX="${PROJECT_ROOT}/integration_test/evm_module/scripts/contracts/minimal_contract.hex"
REVERTER_HEX="${PROJECT_ROOT}/integration_test/evm_module/scripts/contracts/reverter_contract.hex"
EMITTER_HEX="${PROJECT_ROOT}/integration_test/evm_module/scripts/contracts/emitter_contract.hex"
EVM_RPC_URL="${SEI_EVM_RPC_URL:-http://localhost:8545}"
KEYRING_ARGS=()
if [[ -n "${SEI_EVM_IO_KEYRING_BACKEND:-}" ]]; then
Expand Down Expand Up @@ -63,6 +64,31 @@ if [[ -z "${SEI_EVM_IO_REVERTER_ADDRESS:-}" ]]; then
echo "WARNING: Reverter contract not deployed (deploy or receipt lookup failed). Tests using __REVERTER__ will be skipped." >&2
fi

# Deploy emitter contract (constructor emits one LOG1 with topic 0x4242…4242);
# export SEI_EVM_WS_EMITTER_ADDRESS + SEI_EVM_WS_EMITTER_BLOCK so the WS
# eth_subscribe(logs) integration test can subscribe to the deploy block + emitter
# address and assert end-to-end log delivery.
docker exec "$CONTAINER" /bin/bash -c "tr -d '[:space:]' < \"$EMITTER_HEX\" > /tmp/emitter_contract.hex"
EMITTER_OUT=$(run seid tx evm deploy /tmp/emitter_contract.hex --from "$FROM" "${KEYRING_ARGS[@]}" --chain-id sei --evm-rpc "$EVM_RPC_URL" -b block -y 2>&1) || true
EMITTER_TX=$(echo "$EMITTER_OUT" | grep -oE '0x[a-fA-F0-9]{64}' | head -1)
if [[ -n "$EMITTER_TX" ]]; then
sleep 2
for _ in 1 2 3 4 5 6 7 8 9 10; do
ERESP=$(docker exec "$CONTAINER" curl -s -X POST -H "Content-Type: application/json" -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_getTransactionReceipt\",\"params\":[\"$EMITTER_TX\"]}" "$EVM_RPC_URL" 2>/dev/null) || true
EMITTER_ADDR=$(echo "$ERESP" | grep -o '"contractAddress":"[^"]*"' | head -1 | cut -d'"' -f4)
EMITTER_BLOCK=$(echo "$ERESP" | grep -o '"blockNumber":"[^"]*"' | head -1 | cut -d'"' -f4)
[[ -n "$EMITTER_ADDR" && -n "$EMITTER_BLOCK" ]] && break
sleep 1
done
if [[ -n "$EMITTER_ADDR" && -n "$EMITTER_BLOCK" ]]; then
export SEI_EVM_WS_EMITTER_ADDRESS="$EMITTER_ADDR"
export SEI_EVM_WS_EMITTER_BLOCK="$EMITTER_BLOCK"
fi
fi
if [[ -z "${SEI_EVM_WS_EMITTER_ADDRESS:-}" || -z "${SEI_EVM_WS_EMITTER_BLOCK:-}" ]]; then
echo "WARNING: Emitter contract not deployed (deploy or receipt lookup failed). eth_subscribe(logs) integration test will be skipped." >&2
fi

export SEI_EVM_IO_RUN_INTEGRATION=1
go test ./integration_test/evm_module/rpc_io_test/ -v -count=1

Expand Down
Loading
Loading