Skip to content

Commit

Permalink
refactor call to use connector for deposit to contract
Browse files Browse the repository at this point in the history
  • Loading branch information
kingpinXD committed Apr 11, 2024
1 parent 63687c0 commit ef33edc
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 85 deletions.
30 changes: 30 additions & 0 deletions testutil/keeper/mocks/crosschain/fungible.go

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

19 changes: 6 additions & 13 deletions x/crosschain/keeper/evm_deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package keeper
import (
"encoding/hex"
"fmt"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"
ethcommon "github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -39,22 +38,16 @@ func (k Keeper) HandleEVMDeposit(ctx sdk.Context, cctx *types.CrossChainTx) (boo
}

if inboundCoinType == coin.CoinType_Zeta {
// if coin type is Zeta, this is a deposit ZETA to zEVM cctx.
err := k.fungibleKeeper.DepositCoinZeta(ctx, to, inboundAmount)
if err != nil {
// Return !isContractReverted, err. This will set the cctx status to Aborted.
return false, err
}
indexBytes, err := cctx.GetCCTXIndexBytes()
if err != nil {
// Return !isContractReverted, err. This will set the cctx status to Aborted.
return false, err
}
_, isContract, err := k.fungibleKeeper.ZevmOnReceive(ctx, sender.Bytes(), to, big.NewInt(inboundSenderChainID), inboundAmount, data, indexBytes)
// Use error message only for a contract call , if to address is not a contract we do not need handle the error
if isContract && err != nil {
// Return !isContractReverted, err. This will set the cctx status to Aborted.
return false, err
// if coin type is Zeta, this is a deposit ZETA to zEVM cctx.
evmTxResponse, err := k.fungibleKeeper.ZEVMDepositAndCallContract(ctx, sender, to, inboundSenderChainID, inboundAmount, data, indexBytes)
if fungibletypes.IsContractReverted(evmTxResponse, err) || errShouldRevertCctx(err) {
return true, err // contract reverted; should refund
} else if err != nil {
return false, err // internal error; should abort
}
} else {
// cointype is Gas or ERC20; then it could be a ZRC20 deposit/depositAndCall cctx.
Expand Down
19 changes: 12 additions & 7 deletions x/crosschain/keeper/evm_deposit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"cosmossdk.io/math"
ethcommon "github.com/ethereum/go-ethereum/common"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
Expand All @@ -26,16 +27,19 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) {
fungibleMock := keepertest.GetCrosschainFungibleMock(t, k)
receiver := sample.EthAddress()
amount := big.NewInt(42)
sender := sample.EthAddress()
senderChainId := int64(0)

// expect DepositCoinZeta to be called
fungibleMock.On("DepositCoinZeta", ctx, receiver, amount).Return(nil)
fungibleMock.On("ZEVMDepositAndCallContract", ctx, ethcommon.HexToAddress(sender.String()), receiver, senderChainId, amount, mock.Anything, mock.Anything).Return(nil, nil)

// call HandleEVMDeposit
cctx := sample.CrossChainTx(t, "foo")
cctx.GetCurrentOutTxParam().Receiver = receiver.String()
cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount)
cctx.GetInboundTxParams().CoinType = coin.CoinType_Zeta
cctx.GetInboundTxParams().SenderChainId = 0
cctx.GetInboundTxParams().SenderChainId = senderChainId
cctx.InboundTxParams.Sender = sender.String()
reverted, err := k.HandleEVMDeposit(
ctx,
cctx,
Expand All @@ -52,19 +56,20 @@ func TestMsgServer_HandleEVMDeposit(t *testing.T) {

fungibleMock := keepertest.GetCrosschainFungibleMock(t, k)
receiver := sample.EthAddress()
sender := sample.EthAddress()
senderChainId := int64(0)
amount := big.NewInt(42)

cctx := sample.CrossChainTx(t, "foo")
// expect DepositCoinZeta to be called
errDeposit := errors.New("deposit failed")
fungibleMock.On("DepositCoinZeta", ctx, receiver, amount).Return(errDeposit)

fungibleMock.On("ZEVMDepositAndCallContract", ctx, ethcommon.HexToAddress(sender.String()), receiver, senderChainId, amount, mock.Anything, mock.Anything).Return(nil, errDeposit)
// call HandleEVMDeposit

cctx := sample.CrossChainTx(t, "foo")
cctx.InboundTxParams.Sender = sender.String()
cctx.GetCurrentOutTxParam().Receiver = receiver.String()
cctx.GetInboundTxParams().Amount = math.NewUintFromBigInt(amount)
cctx.GetInboundTxParams().CoinType = coin.CoinType_Zeta
cctx.GetInboundTxParams().SenderChainId = 0
cctx.GetInboundTxParams().SenderChainId = senderChainId
reverted, err := k.HandleEVMDeposit(
ctx,
cctx,
Expand Down
22 changes: 7 additions & 15 deletions x/crosschain/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
eth "github.com/ethereum/go-ethereum/common"
ethcommon "github.com/ethereum/go-ethereum/common"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/zeta-chain/zetacore/pkg/chains"
"github.com/zeta-chain/zetacore/pkg/coin"
Expand Down Expand Up @@ -162,22 +163,13 @@ type FungibleKeeper interface {
) (eth.Address, error)
FundGasStabilityPool(ctx sdk.Context, chainID int64, amount *big.Int) error
WithdrawFromGasStabilityPool(ctx sdk.Context, chainID int64, amount *big.Int) error
ZevmOnReceive(ctx sdk.Context,
zetaTxSender []byte,
zetaTxReceiver eth.Address,
senderChainID *big.Int,
amount *big.Int,
data []byte,
cctxIndexBytes [32]byte) (*evmtypes.MsgEthereumTxResponse, bool, error)

ZevmOnRevert(ctx sdk.Context,
zetaTxSender eth.Address,
zetaTxReceiver []byte,
senderChainID *big.Int,
destinationChainID *big.Int,
amount *big.Int,
ZEVMDepositAndCallContract(ctx sdk.Context,
sender ethcommon.Address,
to ethcommon.Address,
inboundSenderChainID int64,
inboundAmount *big.Int,
data []byte,
cctxIndexBytes [32]byte) (*evmtypes.MsgEthereumTxResponse, bool, error)
indexBytes [32]byte) (*evmtypes.MsgEthereumTxResponse, error)
}

type AuthorityKeeper interface {
Expand Down
14 changes: 14 additions & 0 deletions x/fungible/keeper/deposits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"

"cosmossdk.io/math"
ethcommon "github.com/ethereum/go-ethereum/common"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -369,3 +370,16 @@ func TestKeeper_DepositCoinZeta(t *testing.T) {
b = sdkk.BankKeeper.GetBalance(ctx, zetaToAddress, config.BaseDenom)
require.Equal(t, amount.Int64(), b.Amount.Int64())
}

func Test_AddressConvertion(t *testing.T) {
addressCosmosString := sample.AccAddress()
addressCosmsosAccAddress := sdk.MustAccAddressFromBech32(addressCosmosString)
// Logic used in depositCoins function
addressEth := ethcommon.HexToAddress(addressCosmosString)
//https://github.com/zeta-chain/zeta-node/blob/zevm-message-passing/x/fungible/keeper/deposits.go#L17-L17
depositAddress := sdk.AccAddress(addressEth.Bytes())
depositAddressString := depositAddress.String()

require.Equal(t, addressCosmsosAccAddress, depositAddress)
require.Equal(t, addressCosmosString, depositAddressString)
}
111 changes: 77 additions & 34 deletions x/fungible/keeper/zevm_message_passing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ import (
"math/big"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/evmos/ethermint/x/evm/statedb"
"github.com/stretchr/testify/require"
"github.com/zeta-chain/zetacore/cmd/zetacored/config"
"github.com/zeta-chain/zetacore/testutil/contracts"
keepertest "github.com/zeta-chain/zetacore/testutil/keeper"
"github.com/zeta-chain/zetacore/testutil/sample"
"github.com/zeta-chain/zetacore/x/fungible/types"
)

func TestKeeper_ZevmOnReceive(t *testing.T) {
t.Run("successfully call ZevmOnReceive on connector contract ", func(t *testing.T) {
func TestKeeper_ZEVMDepositAndCallContract(t *testing.T) {
t.Run("successfully call ZEVMDepositAndCallContract on connector contract ", func(t *testing.T) {
k, ctx, sdkk, _ := keepertest.FungibleKeeper(t)
_ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName)

Expand All @@ -23,16 +25,15 @@ func TestKeeper_ZevmOnReceive(t *testing.T) {
require.NoError(t, err)
assertContractDeployment(t, sdkk.EvmKeeper, ctx, dAppContract)

zetaTxSender := sample.EthAddress().Bytes()
senderChainID := big.NewInt(1)
zetaTxSender := sample.EthAddress()
zetaTxReceiver := dAppContract
amount := big.NewInt(45)
inboundSenderChainID := int64(1)
inboundAmount := big.NewInt(45)
data := []byte("message")
cctxIndexBytes := [32]byte{}

_, isContract, err := k.ZevmOnReceive(ctx, zetaTxSender, zetaTxReceiver, senderChainID, amount, data, cctxIndexBytes)
_, err = k.ZEVMDepositAndCallContract(ctx, zetaTxSender, zetaTxReceiver, inboundSenderChainID, inboundAmount, data, cctxIndexBytes)
require.NoError(t, err)
require.True(t, isContract)

dappAbi, err := contracts.DappMetaData.GetAbi()
require.NoError(t, err)
Expand All @@ -53,47 +54,90 @@ func TestKeeper_ZevmOnReceive(t *testing.T) {
require.NotZero(t, len(unpacked))
valSenderAddress, ok := unpacked[0].([]byte)
require.True(t, ok)
require.Equal(t, zetaTxSender, valSenderAddress)
require.Equal(t, zetaTxSender.Bytes(), valSenderAddress)
})

t.Run("fail to call ZevmOnReceive if account not found for receiver address", func(t *testing.T) {
t.Run("successfully deposit coin if account is not a contract", func(t *testing.T) {
k, ctx, sdkk, _ := keepertest.FungibleKeeper(t)
_ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName)

deploySystemContracts(t, ctx, k, sdkk.EvmKeeper)
zetaTxSender := sample.EthAddress()
zetaTxReceiver := sample.EthAddress()
inboundSenderChainID := int64(1)
inboundAmount := big.NewInt(45)
data := []byte("message")
cctxIndexBytes := [32]byte{}

_, isContract, err := k.ZevmOnReceive(ctx, sample.EthAddress().Bytes(),
sample.EthAddress(),
big.NewInt(1),
big.NewInt(45),
[]byte("message"),
[32]byte{})
require.ErrorIs(t, err, types.ErrAccountNotFound)
require.False(t, isContract)
err := sdkk.EvmKeeper.SetAccount(ctx, zetaTxReceiver, statedb.Account{
Nonce: 0,
Balance: big.NewInt(0),
CodeHash: crypto.Keccak256(nil),
})
require.NoError(t, err)

_, err = k.ZEVMDepositAndCallContract(ctx, zetaTxSender, zetaTxReceiver, inboundSenderChainID, inboundAmount, data, cctxIndexBytes)
require.NoError(t, err)
b := sdkk.BankKeeper.GetBalance(ctx, sdk.AccAddress(zetaTxReceiver.Bytes()), config.BaseDenom)
require.Equal(t, inboundAmount.Int64(), b.Amount.Int64())
})

t.Run("fail to call ZevmOnReceive if account is not a contract", func(t *testing.T) {
t.Run("fail ZEVMDepositAndCallContract if account not found", func(t *testing.T) {
k, ctx, _, _ := keepertest.FungibleKeeper(t)
_ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName)

zetaTxSender := sample.EthAddress()
zetaTxReceiver := sample.EthAddress()
inboundSenderChainID := int64(1)
inboundAmount := big.NewInt(45)
data := []byte("message")
cctxIndexBytes := [32]byte{}

_, err := k.ZEVMDepositAndCallContract(ctx, zetaTxSender, zetaTxReceiver, inboundSenderChainID, inboundAmount, data, cctxIndexBytes)
require.ErrorIs(t, err, types.ErrAccountNotFound)
require.ErrorContains(t, err, "account not found")
})
}
func TestKeeper_ZevmOnReceive(t *testing.T) {
t.Run("successfully call ZevmOnReceive on connector contract ", func(t *testing.T) {
k, ctx, sdkk, _ := keepertest.FungibleKeeper(t)
_ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName)

deploySystemContracts(t, ctx, k, sdkk.EvmKeeper)
dAppContract, err := k.DeployContract(ctx, contracts.DappMetaData)
require.NoError(t, err)
assertContractDeployment(t, sdkk.EvmKeeper, ctx, dAppContract)

zetaTxReceiver := sample.EthAddress()
err := sdkk.EvmKeeper.SetAccount(ctx, zetaTxReceiver, statedb.Account{
Nonce: 0,
Balance: big.NewInt(100),
CodeHash: crypto.Keccak256(nil),
})
zetaTxSender := sample.EthAddress().Bytes()
senderChainID := big.NewInt(1)
zetaTxReceiver := dAppContract
amount := big.NewInt(45)
data := []byte("message")
cctxIndexBytes := [32]byte{}

_, err = k.ZevmOnReceive(ctx, zetaTxSender, zetaTxReceiver, senderChainID, amount, data, cctxIndexBytes)
require.NoError(t, err)

_, isContract, err := k.ZevmOnReceive(ctx, sample.EthAddress().Bytes(),
zetaTxReceiver,
big.NewInt(1),
big.NewInt(45),
[]byte("message"),
[32]byte{})
require.ErrorIs(t, err, types.ErrCallNonContract)
require.False(t, isContract)
dappAbi, err := contracts.DappMetaData.GetAbi()
require.NoError(t, err)
res, err := k.CallEVM(
ctx,
*dappAbi,
types.ModuleAddressEVM,
dAppContract,
big.NewInt(0),
nil,
false,
false,
"zetaTxSenderAddress",
)
require.NoError(t, err)
unpacked, err := dappAbi.Unpack("zetaTxSenderAddress", res.Ret)
require.NoError(t, err)
require.NotZero(t, len(unpacked))
valSenderAddress, ok := unpacked[0].([]byte)
require.True(t, ok)
require.Equal(t, zetaTxSender, valSenderAddress)
})

t.Run("fail to call ZevmOnReceive if CallOnReceiveZevmConnector fails", func(t *testing.T) {
Expand All @@ -111,10 +155,9 @@ func TestKeeper_ZevmOnReceive(t *testing.T) {
data := []byte("message")
cctxIndexBytes := [32]byte{}

_, isContract, err := k.ZevmOnReceive(ctx, zetaTxSender, zetaTxReceiver, senderChainID, amount, data, cctxIndexBytes)
_, err = k.ZevmOnReceive(ctx, zetaTxSender, zetaTxReceiver, senderChainID, amount, data, cctxIndexBytes)
require.ErrorIs(t, err, types.ErrContractNotFound)
require.ErrorContains(t, err, "GetSystemContract address not found")
require.True(t, isContract)
})
}

Expand Down
Loading

0 comments on commit ef33edc

Please sign in to comment.