Skip to content

Commit

Permalink
Merge branch 'main' into yzang/SEI-8856
Browse files Browse the repository at this point in the history
  • Loading branch information
yzang2019 authored Jan 27, 2025
2 parents 8d6ff5f + 2418932 commit b17b741
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 27 deletions.
3 changes: 2 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ func New(
)

// Create Transfer Keepers
app.TransferKeeper = ibctransferkeeper.NewKeeper(
app.TransferKeeper = ibctransferkeeper.NewKeeperWithAddressHandler(
appCodec,
keys[ibctransfertypes.StoreKey],
app.GetSubspace(ibctransfertypes.ModuleName),
Expand All @@ -504,6 +504,7 @@ func New(
app.AccountKeeper,
app.BankKeeper,
scopedTransferKeeper,
evmkeeper.NewEvmAddressHandler(&app.EvmKeeper),
)
transferModule := transfer.NewAppModule(app.TransferKeeper)
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)
Expand Down
15 changes: 14 additions & 1 deletion evmrpc/subscribe.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,20 @@ func (a *SubscriptionAPI) Logs(ctx context.Context, filter *filters.FilterCriter
if filter == nil {
filter = &filters.FilterCriteria{}
}
// when fromBlock is 0 and toBlock is latest, adjust the filter
// to unbounded filter
if filter.FromBlock != nil && filter.FromBlock.Int64() == 0 &&
filter.ToBlock != nil && filter.ToBlock.Int64() < 0 {
latest := big.NewInt(a.logFetcher.ctxProvider(LatestCtxHeight).BlockHeight())
unboundedFilter := &filters.FilterCriteria{
FromBlock: latest, // set to latest block height
ToBlock: nil, // set to nil to continue listening
Addresses: filter.Addresses,
Topics: filter.Topics,
}
filter = unboundedFilter
}

rpcSub := notifier.CreateSubscription()

if filter.BlockHash != nil {
Expand Down Expand Up @@ -183,7 +197,6 @@ func (a *SubscriptionAPI) Logs(ctx context.Context, filter *filters.FilterCriter
}
begin = lastToHeight
filter.FromBlock = big.NewInt(lastToHeight + 1)

time.Sleep(SleepInterval)
}
}()
Expand Down
11 changes: 5 additions & 6 deletions evmrpc/subscribe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,16 @@ func TestSubscribeEmptyLogs(t *testing.T) {
}

func TestSubscribeNewLogs(t *testing.T) {
t.Parallel()
data := map[string]interface{}{
"fromBlock": "0x0",
"toBlock": "latest",
"address": []common.Address{
common.HexToAddress("0x1111111111111111111111111111111111111112"),
common.HexToAddress("0xc0ffee254729296a45a3885639AC7E10F9d54979"),
common.HexToAddress("0x1111111111111111111111111111111111111111"),
},
"topics": [][]common.Hash{
{
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000123"),
common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111"),
common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111112"),
},
},
}
Expand Down Expand Up @@ -148,11 +147,11 @@ func TestSubscribeNewLogs(t *testing.T) {
t.Fatal("Subscription ID does not match")
}
resultMap := paramMap["result"].(map[string]interface{})
if resultMap["address"] != "0x1111111111111111111111111111111111111112" && resultMap["address"] != "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" {
if resultMap["address"] != "0x1111111111111111111111111111111111111111" && resultMap["address"] != "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" {
t.Fatalf("Unexpected address, got %v", resultMap["address"])
}
firstTopic := resultMap["topics"].([]interface{})[0].(string)
if firstTopic != "0x0000000000000000000000000000000000000000000000000000000000000123" {
if firstTopic != "0x1111111111111111111111111111111111111111111111111111111111111111" {
t.Fatalf("Unexpected topic, got %v", firstTopic)
}
case <-timer.C:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ replace (
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.51
github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.2.0
github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.4
github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.5
github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20241224143343-21ee50facc96
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.46
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1354,8 +1354,8 @@ github.com/sei-protocol/sei-db v0.0.46 h1:naXfSp1I3UgJJm/iSvXpdFzr9nofEOxp/EekcA
github.com/sei-protocol/sei-db v0.0.46/go.mod h1:m5g7p0QeAS3dNJHIl28zQpzOgxQmvYqPb7t4hwgIOCA=
github.com/sei-protocol/sei-iavl v0.2.0 h1:OisPjXiDT+oe+aeckzDEFgkZCYuUjHgs/PP8DPicN+I=
github.com/sei-protocol/sei-iavl v0.2.0/go.mod h1:qRf8QYUPfrAO7K6VDB2B2l/N7K5L76OorioGBcJBIbw=
github.com/sei-protocol/sei-ibc-go/v3 v3.3.4 h1:M1r1B2yzogs7RyXdCPgaNJlxqSC/rU2goqtfnUTXS/M=
github.com/sei-protocol/sei-ibc-go/v3 v3.3.4/go.mod h1:VwB/vWu4ysT5DN2aF78d17LYmx3omSAdq6gpKvM7XRA=
github.com/sei-protocol/sei-ibc-go/v3 v3.3.5 h1:SQRzWi9KSMuGNGd3f5RWAmsGGk7yeY1zhnEnrr/nqug=
github.com/sei-protocol/sei-ibc-go/v3 v3.3.5/go.mod h1:VwB/vWu4ysT5DN2aF78d17LYmx3omSAdq6gpKvM7XRA=
github.com/sei-protocol/sei-tendermint v0.4.6 h1:Gmw4tjLSnghAdue54HJzDySDvxs2Hd5d0rrv3ajgRSA=
github.com/sei-protocol/sei-tendermint v0.4.6/go.mod h1:4LSlJdhl3nf3OmohliwRNUFLOB1XWlrmSodrIP7fLh4=
github.com/sei-protocol/sei-tm-db v0.0.5 h1:3WONKdSXEqdZZeLuWYfK5hP37TJpfaUa13vAyAlvaQY=
Expand Down
2 changes: 1 addition & 1 deletion precompiles/ibc/abi.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"},{"internalType":"uint64","name":"timeoutTimestamp","type":"uint64"},{"internalType":"string","name":"memo","type":"string"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"memo","type":"string"}],"name":"transferWithDefaultTimeout","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"}]
[{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"revisionNumber","type":"uint64"},{"internalType":"uint64","name":"revisionHeight","type":"uint64"},{"internalType":"uint64","name":"timeoutTimestamp","type":"uint64"},{"internalType":"string","name":"memo","type":"string"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"toAddress","type":"string"},{"internalType":"string","name":"port","type":"string"},{"internalType":"string","name":"channel","type":"string"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"memo","type":"string"}],"name":"transferWithDefaultTimeout","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
17 changes: 6 additions & 11 deletions precompiles/ibc/ibc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/bech32"
"github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types"
connectiontypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types"
Expand Down Expand Up @@ -73,6 +72,10 @@ func NewPrecompile(
}

func (p PrecompileExecutor) Execute(ctx sdk.Context, method *abi.Method, caller common.Address, callingContract common.Address, args []interface{}, value *big.Int, readOnly bool, evm *vm.EVM, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
if err = pcommon.ValidateNonPayable(value); err != nil {
return nil, 0, err
}

if readOnly {
return nil, 0, errors.New("cannot call IBC precompile from staticcall")
}
Expand Down Expand Up @@ -352,16 +355,8 @@ func (p PrecompileExecutor) validateCommonArgs(ctx sdk.Context, args []interface
}

receiverAddressString, ok := args[0].(string)
if !ok {
return nil, errors.New("receiverAddress is not a string")
}
_, bz, err := bech32.DecodeAndConvert(receiverAddressString)
if err != nil {
return nil, err
}
err = sdk.VerifyAddressFormat(bz)
if err != nil {
return nil, err
if !ok || receiverAddressString == "" {
return nil, errors.New("receiverAddress is not a string or empty")
}

port, ok := args[1].(string)
Expand Down
24 changes: 20 additions & 4 deletions precompiles/ibc/ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ func TestPrecompile_Run(t *testing.T) {
wantErr: true,
wantErrMsg: "cannot delegatecall IBC",
},
{
name: "failed transfer: value is not nil",
fields: fields{transferKeeper: &MockTransferKeeper{}},
args: args{caller: senderEvmAddress, callingContract: common.Address{}, input: commonArgs.input, suppliedGas: 1000000, value: big.NewInt(100), isFromDelegateCall: true},
wantBz: nil,
wantErr: true,
wantErrMsg: "sending funds to a non-payable function",
},
{
name: "failed transfer: empty sourcePort",
fields: fields{transferKeeper: &MockTransferKeeper{}},
Expand Down Expand Up @@ -202,7 +210,7 @@ func TestPrecompile_Run(t *testing.T) {
caller: senderEvmAddress,
callingContract: senderEvmAddress,
input: &input{
receiverAddr: "invalid",
receiverAddr: "",
sourcePort: "transfer",
sourceChannel: "channel-0",
denom: "",
Expand All @@ -216,7 +224,7 @@ func TestPrecompile_Run(t *testing.T) {
},
wantBz: nil,
wantErr: true,
wantErrMsg: "decoding bech32 failed: invalid bech32 string length 7",
wantErrMsg: "receiverAddress is not a string or empty",
},
{
name: "memo is added to the transfer if passed",
Expand Down Expand Up @@ -357,6 +365,14 @@ func TestTransferWithDefaultTimeoutPrecompile_Run(t *testing.T) {
wantErr: true,
wantErrMsg: "cannot delegatecall IBC",
},
{
name: "failed transfer: value is not nil",
fields: fields{transferKeeper: &MockTransferKeeper{}},
args: args{caller: senderEvmAddress, callingContract: common.Address{}, input: commonArgs.input, suppliedGas: 1000000, value: big.NewInt(100), isFromDelegateCall: true},
wantBz: nil,
wantErr: true,
wantErrMsg: "sending funds to a non-payable function",
},
{
name: "failed transfer: empty sourcePort",
fields: fields{transferKeeper: &MockTransferKeeper{}},
Expand Down Expand Up @@ -424,7 +440,7 @@ func TestTransferWithDefaultTimeoutPrecompile_Run(t *testing.T) {
caller: senderEvmAddress,
callingContract: senderEvmAddress,
input: &input{
receiverAddr: "invalid",
receiverAddr: "",
sourcePort: "transfer",
sourceChannel: "channel-0",
denom: "",
Expand All @@ -435,7 +451,7 @@ func TestTransferWithDefaultTimeoutPrecompile_Run(t *testing.T) {
},
wantBz: nil,
wantErr: true,
wantErrMsg: "decoding bech32 failed: invalid bech32 string length 7",
wantErrMsg: "receiverAddress is not a string or empty",
},
}
for _, tt := range tests {
Expand Down
20 changes: 20 additions & 0 deletions x/evm/keeper/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,23 @@ func (k *Keeper) CanAddressReceive(ctx sdk.Context, addr sdk.AccAddress) bool {
// if the associated address is the cast address itself, allow the address to receive (e.g. EVM contract addresses)
return associatedAddr.Equals(addr) || !isAssociated // this means it's either a cast address that's not associated yet, or not a cast address at all.
}

type EvmAddressHandler struct {
evmKeeper *Keeper
}

func NewEvmAddressHandler(evmKeeper *Keeper) EvmAddressHandler {
return EvmAddressHandler{evmKeeper: evmKeeper}
}

func (h EvmAddressHandler) GetSeiAddressFromString(ctx sdk.Context, address string) (sdk.AccAddress, error) {
if common.IsHexAddress(address) {
parsedAddress := common.HexToAddress(address)
return h.evmKeeper.GetSeiAddressOrDefault(ctx, parsedAddress), nil
}
parsedAddress, err := sdk.AccAddressFromBech32(address)
if err != nil {
return nil, err
}
return parsedAddress, nil
}
79 changes: 79 additions & 0 deletions x/evm/keeper/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/sei-protocol/sei-chain/testutil/keeper"
evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -73,3 +74,81 @@ func TestSendingToCastAddress(t *testing.T) {
require.NotNil(t, a.BankKeeper.SendCoins(ctx, sourceAddr, castAddr, amt))
require.NotNil(t, a.BankKeeper.SendCoinsAndWei(ctx, sourceAddr, castAddr, sdk.OneInt(), sdk.OneInt()))
}

func TestEvmAddressHandler_GetSeiAddressFromString(t *testing.T) {
a := keeper.EVMTestApp
ctx := a.GetContextForDeliverTx([]byte{})
seiAddr, evmAddr := keeper.MockAddressPair()
a.EvmKeeper.SetAddressMapping(ctx, seiAddr, evmAddr)

_, notAssociatedEvmAddr := keeper.MockAddressPair()
castAddr := sdk.AccAddress(notAssociatedEvmAddr[:])

type args struct {
ctx sdk.Context
address string
}
tests := []struct {
name string
args args
want sdk.AccAddress
wantErr bool
wantErrMsg string
}{
{
name: "returns associated Sei address if input address is a valid 0x and associated",
args: args{
ctx: ctx,
address: evmAddr.String(),
},
want: seiAddr,
},
{
name: "returns default Sei address if input address is a valid 0x not associated",
args: args{
ctx: ctx,
address: notAssociatedEvmAddr.String(),
},
want: castAddr,
},
{
name: "returns Sei address if input address is a valid bech32 address",
args: args{
ctx: ctx,
address: seiAddr.String(),
},
want: seiAddr,
},
{
name: "returns error if address is invalid",
args: args{
ctx: ctx,
address: "invalid",
},
wantErr: true,
wantErrMsg: "decoding bech32 failed: invalid bech32 string length 7",
}, {
name: "returns error if address is empty",
args: args{
ctx: ctx,
address: "",
},
wantErr: true,
wantErrMsg: "empty address string is not allowed",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := evmkeeper.NewEvmAddressHandler(&a.EvmKeeper)
got, err := h.GetSeiAddressFromString(tt.args.ctx, tt.args.address)
if tt.wantErr {
require.NotNil(t, err)
require.Equal(t, tt.wantErrMsg, err.Error())
return
} else {
require.NoError(t, err)
require.Equal(t, tt.want, got)
}
})
}
}

0 comments on commit b17b741

Please sign in to comment.