Skip to content

Commit

Permalink
[EVM] Add index to logs based on order (#1273)
Browse files Browse the repository at this point in the history
* add index to logs based on order

* add check for getLogs

* add log conversion test
  • Loading branch information
stevenlanders authored and udpatil committed Mar 4, 2024
1 parent c4c9f61 commit fa7d2a1
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 43 deletions.
7 changes: 7 additions & 0 deletions contracts/src/EVMCompatibilityTester.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ contract EVMCompatibilityTester {
event AddressSet(address indexed performer);
event Uint256Set(address indexed performer, uint256 value);
event StringSet(address indexed performer, string value);
event LogIndexEvent(address indexed performer, uint256 value);

struct MsgDetails {
address sender;
Expand Down Expand Up @@ -62,6 +63,12 @@ contract EVMCompatibilityTester {
emit BoolSet(msg.sender, value);
}

function emitMultipleLogs(uint256 count) public {
for (uint256 i = 0; i < count; i++) {
emit LogIndexEvent(msg.sender, i);
}
}

function setStringVar(string memory value) public {
stringVar = value;
emit StringSet(msg.sender, value);
Expand Down
35 changes: 31 additions & 4 deletions contracts/test/EVMCompatabilityTester.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ describe("EVM Test", function () {
});

describe("Differing maxPriorityFeePerGas and maxFeePerGas", async function() {
testCases.forEach(async ([name, maxPriorityFeePerGas, maxFeePerGas]) => {
for (const [name, maxPriorityFeePerGas, maxFeePerGas] of testCases) {
it(`EIP-1559 test: ${name}`, async function() {
console.log(`maxPriorityFeePerGas = ${maxPriorityFeePerGas}`)
console.log(`maxFeePerGas = ${maxFeePerGas}`)
Expand Down Expand Up @@ -458,12 +458,12 @@ describe("EVM Test", function () {
console.log(`tip = ${tip}`)
const effectiveGasPrice = tip + gasPrice;
console.log(`effectiveGasPrice = ${effectiveGasPrice}`)

const diff = balanceBefore - balanceAfter;
console.log(`diff = ${diff}`)
expect(diff).to.equal(21000 * effectiveGasPrice);
});
});
}
});
});
});
Expand Down Expand Up @@ -560,14 +560,41 @@ describe("EVM Test", function () {
expect(nonce).to.be.a('number');
});

it("Should set log index correctly", async function () {
const blockNumber = await ethers.provider.getBlockNumber();
const numberOfEvents = 5;

// check receipt
const txResponse = await evmTester.emitMultipleLogs(numberOfEvents);
const receipt = await txResponse.wait();
expect(receipt.logs.length).to.equal(numberOfEvents)
for(let i=0; i<receipt.logs.length; i++) {
expect(receipt.logs[i].index).to.equal(i);
}

// check logs
const filter = {
fromBlock: blockNumber,
toBlock: 'latest',
address: await evmTester.getAddress(),
topics: [ethers.id("LogIndexEvent(address,uint256)")]
};
const logs = await ethers.provider.getLogs(filter);
expect(logs.length).to.equal(numberOfEvents)
for(let i=0; i<logs.length; i++) {
expect(logs[i].index).to.equal(i);
}
})

it("Should fetch logs for a specific event", async function () {
// Emit an event by making a transaction
const blockNumber = await ethers.provider.getBlockNumber();
const txResponse = await evmTester.setBoolVar(true);
await txResponse.wait();

// Create a filter to get logs
const filter = {
fromBlock: 0,
fromBlock: blockNumber,
toBlock: 'latest',
address: await evmTester.getAddress(),
topics: [ethers.id("BoolSet(address,bool)")]
Expand Down
1 change: 1 addition & 0 deletions proto/evm/receipt.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ message Log {
string address = 1;
repeated string topics = 2;
bytes data = 3;
uint32 index = 4;
}

message Receipt {
Expand Down
3 changes: 2 additions & 1 deletion x/evm/keeper/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ func convertLog(l *types.Log, receipt *types.Receipt) *ethtypes.Log {
BlockNumber: receipt.BlockNumber,
TxHash: common.HexToHash(receipt.TxHashHex),
TxIndex: uint(receipt.TransactionIndex),
}
Index: uint(l.Index)}
}

func ConvertEthLog(l *ethtypes.Log) *types.Log {
return &types.Log{
Address: l.Address.Hex(),
Topics: utils.Map(l.Topics, func(h common.Hash) string { return h.Hex() }),
Data: l.Data,
Index: uint32(l.Index),
}
}
83 changes: 83 additions & 0 deletions x/evm/keeper/log_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package keeper

import (
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"

evmtypes "github.com/sei-protocol/sei-chain/x/evm/types"
)

func TestConvertEthLog(t *testing.T) {
// Create a sample ethtypes.Log object
ethLog := &types.Log{
Address: common.HexToAddress("0x123"),
Topics: []common.Hash{
common.HexToHash("0x456"),
common.HexToHash("0x789"),
},
Data: []byte("data"),
BlockNumber: 1,
TxHash: common.HexToHash("0xabc"),
TxIndex: 2,
Index: 3,
}

// Convert the ethtypes.Log to a types.Log
log := ConvertEthLog(ethLog)

// Check that the fields match
require.Equal(t, ethLog.Address.Hex(), log.Address)
require.Equal(t, len(ethLog.Topics), len(log.Topics))
for i, topic := range ethLog.Topics {
require.Equal(t, topic.Hex(), log.Topics[i])
}
require.Equal(t, ethLog.Data, log.Data)
require.Equal(t, uint32(ethLog.Index), log.Index)
}

func TestGetLogsForTx(t *testing.T) {
// Create a sample types.Receipt object with a list of types.Log objects
receipt := &evmtypes.Receipt{
Logs: []*evmtypes.Log{
{
Address: common.HexToAddress("0x123").Hex(),
Topics: []string{
"0x0000000000000000000000000000000000000000000000000000000000000456",
"0x0000000000000000000000000000000000000000000000000000000000000789",
},
Data: []byte("data"),
Index: 3,
},
{
Address: common.HexToAddress("0x123").Hex(),
Topics: []string{
"0x0000000000000000000000000000000000000000000000000000000000000def",
"0x0000000000000000000000000000000000000000000000000000000000000123",
},
Data: []byte("data2"),
Index: 4,
},
},
BlockNumber: 1,
TransactionIndex: 2,
TxHashHex: "0xabc",
}

// Convert the types.Receipt to a list of ethtypes.Log objects
logs := GetLogsForTx(receipt)

// Check that the fields match
require.Equal(t, len(receipt.Logs), len(logs))
for i, log := range logs {
require.Equal(t, receipt.Logs[i].Address, log.Address.Hex())
require.Equal(t, len(receipt.Logs[i].Topics), len(log.Topics))
for j, topic := range log.Topics {
require.Equal(t, receipt.Logs[i].Topics[j], topic.Hex())
}
require.Equal(t, receipt.Logs[i].Data, log.Data)
require.Equal(t, uint(receipt.Logs[i].Index), log.Index)
}
}
1 change: 1 addition & 0 deletions x/evm/state/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type Logs struct {
}

func (s *DBImpl) AddLog(l *ethtypes.Log) {
l.Index = uint(len(s.logs))
s.logs = append(s.logs, l)
}

Expand Down
112 changes: 74 additions & 38 deletions x/evm/types/receipt.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fa7d2a1

Please sign in to comment.