Skip to content

Commit

Permalink
Add CW->ERC pointer registry (#1499)
Browse files Browse the repository at this point in the history
* Add CW->ERC pointer registry

* fix tests
  • Loading branch information
codchen authored and udpatil committed Apr 19, 2024
1 parent 8948395 commit ee3940c
Show file tree
Hide file tree
Showing 22 changed files with 925 additions and 75 deletions.
4 changes: 2 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ func New(

app.EvmKeeper = *evmkeeper.NewKeeper(keys[evmtypes.StoreKey], memKeys[evmtypes.MemStoreKey],
app.GetSubspace(evmtypes.ModuleName), app.BankKeeper, &app.AccountKeeper, &app.StakingKeeper,
app.TransferKeeper)
app.TransferKeeper, wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper))
app.evmRPCConfig, err = evmrpc.ReadConfig(appOpts)
if err != nil {
panic(fmt.Sprintf("error reading EVM config due to %s", err))
Expand Down Expand Up @@ -806,8 +806,8 @@ func New(
oracletypes.ModuleName,
tokenfactorytypes.ModuleName,
epochmoduletypes.ModuleName,
evmtypes.ModuleName,
wasm.ModuleName,
evmtypes.ModuleName,
acltypes.ModuleName,
// this line is used by starport scaffolding # stargate/app/initGenesis
)
Expand Down
26 changes: 13 additions & 13 deletions integration_test/seidb/state_store_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,39 +39,39 @@
verifiers:
# Verify number of wasm codes at each height
- type: eval
expr: BEGINNING_LIST_CODE_LENGTH == 0
expr: BEGINNING_LIST_CODE_LENGTH == 2
- type: eval
expr: FIRST_SET_LIST_CODE_LENGTH == 10
expr: FIRST_SET_LIST_CODE_LENGTH == 12
- type: eval
expr: FIRST_SET_LIST_CODE_LENGTH_REVERSE == 10
expr: FIRST_SET_LIST_CODE_LENGTH_REVERSE == 12
- type: eval
expr: SECOND_SET_LIST_CODE_LENGTH == 20
expr: SECOND_SET_LIST_CODE_LENGTH == 22
- type: eval
expr: SECOND_SET_LIST_CODE_LENGTH_REVERSE == 20
expr: SECOND_SET_LIST_CODE_LENGTH_REVERSE == 22
- type: eval
expr: THIRD_SET_LIST_CODE_LENGTH == 30
expr: THIRD_SET_LIST_CODE_LENGTH == 32
- type: eval
expr: THIRD_SET_LIST_CODE_LENGTH_REVERSE == 30
expr: THIRD_SET_LIST_CODE_LENGTH_REVERSE == 32

- name: Test state store historical data checking specific wasm codes
inputs:
# Get height from first set
- cmd: tail -1 integration_test/contracts/wasm_first_set_block_height.txt
env: FIRST_SET_BLOCK_HEIGHT
# Get code id from first contract returned at first set height in forward order (0)
- cmd: seid q wasm list-code --count-total --limit 400 --height $FIRST_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[0].code_id"
- cmd: seid q wasm list-code --count-total --limit 400 --height $FIRST_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[3].code_id"
env: FIRST_ID_FIRST_SET
# Get creator from first contract returned at first set height in forward order
- cmd: seid q wasm list-code --count-total --limit 400 --height $FIRST_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[0].creator"
- cmd: seid q wasm list-code --count-total --limit 400 --height $FIRST_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[3].creator"
env: FIRST_CREATOR_FIRST_SET
# Get height from second set
- cmd: tail -1 integration_test/contracts/wasm_second_set_block_height.txt
env: SECOND_SET_BLOCK_HEIGHT
# Get code id from first contract returned at second set height in reverse order (200)
- cmd: seid q wasm list-code --reverse --count-total --limit 400 --height $SECOND_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[0].code_id"
- cmd: seid q wasm list-code --reverse --count-total --limit 400 --height $SECOND_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[3].code_id"
env: SECOND_ID_FIRST_SET
# Get creator from second contract returned at second set height in reverse order
- cmd: seid q wasm list-code --reverse --count-total --limit 400 --height $SECOND_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[0].creator"
- cmd: seid q wasm list-code --reverse --count-total --limit 400 --height $SECOND_SET_BLOCK_HEIGHT --output json | jq -r ".code_infos[3].creator"
env: FIRST_CREATOR_SECOND_SET
# Get creator id
- cmd: tail -1 integration_test/contracts/wasm_creator_id.txt
Expand All @@ -85,9 +85,9 @@
# Verify correct code ids
# NOTE: Since chain is continually running / stateful, may have remove
- type: eval
expr: FIRST_ID_FIRST_SET == 1
expr: FIRST_ID_FIRST_SET == 4
- type: eval
expr: SECOND_ID_FIRST_SET == 20
expr: SECOND_ID_FIRST_SET == 19

- name: Test state store iteration through tokenfactory denoms
inputs:
Expand Down
2 changes: 1 addition & 1 deletion precompiles/wasmd/wasmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func TestInstantiate(t *testing.T) {
outputs, err := instantiateMethod.Outputs.Unpack(res)
require.Nil(t, err)
require.Equal(t, 2, len(outputs))
require.Equal(t, "sei14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sh9m79m", outputs[0].(string))
require.Equal(t, "sei1hrpna9v7vs3stzyd4z3xf00676kf78zpe2u5ksvljswn2vnjp3yslucc3n", outputs[0].(string))
require.Empty(t, outputs[1].([]byte))
require.Equal(t, uint64(902898), g)

Expand Down
16 changes: 16 additions & 0 deletions proto/evm/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ option go_package = "github.com/sei-protocol/sei-chain/x/evm/types";
service Msg {
rpc EVMTransaction(MsgEVMTransaction) returns (MsgEVMTransactionResponse);
rpc Send(MsgSend) returns (MsgSendResponse);
rpc RegisterPointer(MsgRegisterPointer) returns (MsgRegisterPointerResponse);
}

message MsgEVMTransaction {
Expand Down Expand Up @@ -53,3 +54,18 @@ message MsgSend {
}

message MsgSendResponse {}

enum PointerType {
ERC20 = 0;
ERC721 = 1;
}

message MsgRegisterPointer {
string sender = 1;
PointerType pointer_type = 2;
string erc_address = 3;
}

message MsgRegisterPointerResponse {
string pointer_address = 1;
}
3 changes: 2 additions & 1 deletion testutil/keeper/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"encoding/hex"
"sync"
"time"

"github.com/cosmos/cosmos-sdk/crypto/hd"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
Expand Down Expand Up @@ -51,7 +52,7 @@ func MockEVMKeeperWithPrecompiles() (*evmkeeper.Keeper, sdk.Context) {

func MockEVMKeeper() (*evmkeeper.Keeper, sdk.Context) {
testApp := app.Setup(false, false)
ctx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(8)
ctx := testApp.GetContextForDeliverTx([]byte{}).WithBlockHeight(8).WithBlockTime(time.Now())
k := testApp.EvmKeeper
k.InitGenesis(ctx, *evmtypes.DefaultGenesis())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
)

const (
TestContractA = "sei14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sh9m79m"
TestContractA = "sei1hrpna9v7vs3stzyd4z3xf00676kf78zpe2u5ksvljswn2vnjp3yslucc3n"
TestContractB = "sei1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrqms7u8a"
TestContractC = "sei1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3shh3qfl"
TestContractD = "sei1up07dctjqud4fns75cnpejr4frmjtddzsmwgcktlyxd4zekhwecqghxqcp"
Expand Down
22 changes: 22 additions & 0 deletions x/evm/artifacts/erc20/artifacts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package erc20

import "embed"

const CurrentVersion uint16 = 1

//go:embed cwerc20.wasm
var f embed.FS

var cachedBin []byte

func GetBin() []byte {
if cachedBin != nil {
return cachedBin
}
bz, err := f.ReadFile("cwerc20.wasm")
if err != nil {
panic("failed to read ERC20 wrapper contract wasm")
}
cachedBin = bz
return bz
}
Binary file added x/evm/artifacts/erc20/cwerc20.wasm
Binary file not shown.
22 changes: 22 additions & 0 deletions x/evm/artifacts/erc721/artifacts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package erc721

import "embed"

const CurrentVersion uint16 = 1

//go:embed cwerc721.wasm
var f embed.FS

var cachedBin []byte

func GetBin() []byte {
if cachedBin != nil {
return cachedBin
}
bz, err := f.ReadFile("cwerc721.wasm")
if err != nil {
panic("failed to read ERC721 wrapper contract wasm")
}
cachedBin = bz
return bz
}
Binary file added x/evm/artifacts/erc721/cwerc721.wasm
Binary file not shown.
15 changes: 15 additions & 0 deletions x/evm/artifacts/utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package utils

import "encoding/binary"

func GetVersionBz(version uint16) []byte {
res := make([]byte, 2)
binary.BigEndian.PutUint16(res, version)
return res
}

func GetCodeIDBz(codeID uint64) []byte {
res := make([]byte, 8)
binary.BigEndian.PutUint64(res, codeID)
return res
}
22 changes: 22 additions & 0 deletions x/evm/keeper/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
"fmt"

"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/common"
Expand All @@ -13,6 +14,9 @@ import (
"github.com/ethereum/go-ethereum/trie/triedb/hashdb"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"

"github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20"
"github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721"
artifactsutils "github.com/sei-protocol/sei-chain/x/evm/artifacts/utils"
"github.com/sei-protocol/sei-chain/x/evm/types"
)

Expand All @@ -31,6 +35,24 @@ func (k *Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) {
k.SetAddressMapping(ctx, sdk.MustAccAddressFromBech32(addr.SeiAddress), common.HexToAddress(addr.EthAddress))
}

erc20CodeID, err := k.wasmKeeper.Create(ctx, k.accountKeeper.GetModuleAddress(types.ModuleName), erc20.GetBin(), nil)
if err != nil {
panic(err)
}
prefix.NewStore(k.PrefixStore(ctx, types.PointerCWCodePrefix), types.PointerCW20ERC20Prefix).Set(
artifactsutils.GetVersionBz(erc20.CurrentVersion),
artifactsutils.GetCodeIDBz(erc20CodeID),
)

erc721CodeID, err := k.wasmKeeper.Create(ctx, k.accountKeeper.GetModuleAddress(types.ModuleName), erc721.GetBin(), nil)
if err != nil {
panic(err)
}
prefix.NewStore(k.PrefixStore(ctx, types.PointerCWCodePrefix), types.PointerCW721ERC721Prefix).Set(
artifactsutils.GetVersionBz(erc721.CurrentVersion),
artifactsutils.GetCodeIDBz(erc721CodeID),
)

if k.EthReplayConfig.Enabled && !ethReplayInitialied {
header := k.OpenEthDatabase()
params := k.GetParams(ctx)
Expand Down
9 changes: 8 additions & 1 deletion x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"sort"
"sync"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
Expand Down Expand Up @@ -49,6 +50,7 @@ type Keeper struct {
accountKeeper *authkeeper.AccountKeeper
stakingKeeper *stakingkeeper.Keeper
transferKeeper ibctransferkeeper.Keeper
wasmKeeper *wasmkeeper.PermissionedKeeper

cachedFeeCollectorAddressMtx *sync.RWMutex
cachedFeeCollectorAddress *common.Address
Expand Down Expand Up @@ -109,7 +111,7 @@ func (ctx *ReplayChainContext) GetHeader(hash common.Hash, number uint64) *ethty
func NewKeeper(
storeKey sdk.StoreKey, memStoreKey sdk.StoreKey, paramstore paramtypes.Subspace,
bankKeeper bankkeeper.Keeper, accountKeeper *authkeeper.AccountKeeper, stakingKeeper *stakingkeeper.Keeper,
transferKeeper ibctransferkeeper.Keeper) *Keeper {
transferKeeper ibctransferkeeper.Keeper, wasmKeeper *wasmkeeper.PermissionedKeeper) *Keeper {
if !paramstore.HasKeyTable() {
paramstore = paramstore.WithKeyTable(types.ParamKeyTable())
}
Expand All @@ -121,6 +123,7 @@ func NewKeeper(
accountKeeper: accountKeeper,
stakingKeeper: stakingKeeper,
transferKeeper: transferKeeper,
wasmKeeper: wasmKeeper,
pendingTxs: make(map[string][]*PendingTx),
nonceMx: &sync.RWMutex{},
cachedFeeCollectorAddressMtx: &sync.RWMutex{},
Expand All @@ -138,6 +141,10 @@ func (k *Keeper) BankKeeper() bankkeeper.Keeper {
return k.bankKeeper
}

func (k *Keeper) WasmKeeper() *wasmkeeper.PermissionedKeeper {
return k.wasmKeeper
}

func (k *Keeper) GetStoreKey() sdk.StoreKey {
return k.storeKey
}
Expand Down
58 changes: 58 additions & 0 deletions x/evm/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package keeper

import (
"context"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"math/big"
"runtime/debug"

"github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/store/prefix"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
Expand All @@ -19,6 +22,9 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/sei-protocol/sei-chain/utils"
"github.com/sei-protocol/sei-chain/x/evm/artifacts/erc20"
"github.com/sei-protocol/sei-chain/x/evm/artifacts/erc721"
artifactsutils "github.com/sei-protocol/sei-chain/x/evm/artifacts/utils"
"github.com/sei-protocol/sei-chain/x/evm/state"
"github.com/sei-protocol/sei-chain/x/evm/types"
)
Expand Down Expand Up @@ -249,3 +255,55 @@ func (server msgServer) Send(goCtx context.Context, msg *types.MsgSend) (*types.
}
return &types.MsgSendResponse{}, nil
}

func (server msgServer) RegisterPointer(goCtx context.Context, msg *types.MsgRegisterPointer) (*types.MsgRegisterPointerResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
var existingPointer sdk.AccAddress
var existingVersion uint16
var currentVersion uint16
var exists bool
switch msg.PointerType {
case types.PointerType_ERC20:
currentVersion = erc20.CurrentVersion
existingPointer, existingVersion, exists = server.GetCW20ERC20Pointer(ctx, common.HexToAddress(msg.ErcAddress))
case types.PointerType_ERC721:
currentVersion = erc721.CurrentVersion
existingPointer, existingVersion, exists = server.GetCW721ERC721Pointer(ctx, common.HexToAddress(msg.ErcAddress))
default:
panic("unknown pointer type")
}
if exists && existingVersion >= currentVersion {
return nil, fmt.Errorf("pointer %s already registered at version %d", existingPointer.String(), existingVersion)
}
store := server.PrefixStore(ctx, types.PointerCWCodePrefix)
payload := map[string]interface{}{}
switch msg.PointerType {
case types.PointerType_ERC20:
store = prefix.NewStore(store, types.PointerCW20ERC20Prefix)
payload["erc20_address"] = msg.ErcAddress
case types.PointerType_ERC721:
store = prefix.NewStore(store, types.PointerCW721ERC721Prefix)
payload["erc721_address"] = msg.ErcAddress
default:
panic("unknown pointer type")
}
codeID := binary.BigEndian.Uint64(store.Get(artifactsutils.GetVersionBz(currentVersion)))
bz, err := json.Marshal(payload)
if err != nil {
return nil, err
}
moduleAcct := server.accountKeeper.GetModuleAddress(types.ModuleName)
pointerAddr, _, err := server.wasmKeeper.Instantiate(ctx, codeID, moduleAcct, moduleAcct, bz, fmt.Sprintf("Pointer of %s", msg.ErcAddress), sdk.NewCoins())
if err != nil {
return nil, err
}
switch msg.PointerType {
case types.PointerType_ERC20:
err = server.SetCW20ERC20Pointer(ctx, common.HexToAddress(msg.ErcAddress), pointerAddr.String())
case types.PointerType_ERC721:
err = server.SetCW721ERC721Pointer(ctx, common.HexToAddress(msg.ErcAddress), pointerAddr.String())
default:
panic("unknown pointer type")
}
return &types.MsgRegisterPointerResponse{PointerAddress: pointerAddr.String()}, err
}
Loading

0 comments on commit ee3940c

Please sign in to comment.