diff --git a/x/evm/genesis.go b/x/evm/genesis.go index f05b67c9..3d676b8e 100644 --- a/x/evm/genesis.go +++ b/x/evm/genesis.go @@ -56,7 +56,7 @@ func InitGenesis( panic("code don't match codeHash") } - k.SetCode(ctx, codeHash.Bytes(), code) + k.SetCode(ctx, address, codeHash.Bytes(), code) for _, storage := range account.Storage { k.SetState(ctx, address, common.HexToHash(storage.Key), common.HexToHash(storage.Value).Bytes()) @@ -82,7 +82,7 @@ func ExportGenesis(ctx sdk.Context, k *keeper.Keeper, ak types.AccountKeeper) *t genAccount := types.GenesisAccount{ Address: addr.String(), - Code: common.Bytes2Hex(k.GetCode(ctx, ethAccount.GetCodeHash())), + Code: common.Bytes2Hex(k.GetCode(ctx, addr, ethAccount.GetCodeHash())), Storage: storage, } diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index e18f5bdf..c9b231d0 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -188,7 +188,7 @@ func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que var code []byte if acct != nil && acct.IsContract() { - code = k.GetCode(ctx, common.BytesToHash(acct.CodeHash)) + code = k.GetCode(ctx, address, common.BytesToHash(acct.CodeHash)) } return &types.QueryCodeResponse{ diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 0af2d40d..862b4119 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -46,9 +46,9 @@ func (k *Keeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) } // GetCode loads contract code from database, implements `statedb.Keeper` interface. -func (k *Keeper) GetCode(ctx sdk.Context, codeHash common.Hash) []byte { +func (k *Keeper) GetCode(ctx sdk.Context, addr common.Address, codeHash common.Hash) []byte { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode) - return store.Get(codeHash.Bytes()) + return store.Get(append(addr.Bytes(), codeHash.Bytes()...)) } // ForEachStorage iterate contract storage, callback return false to break early @@ -126,8 +126,7 @@ func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account stated } k.accountKeeper.SetAccount(ctx, acct) } else { - var baseAcc *authtypes.BaseAccount - baseAcc = acct.(*authtypes.BaseAccount) + baseAcc := acct.(*authtypes.BaseAccount) if !bytes.Equal(codeHash.Bytes(), types.EmptyCodeHash) { //if codeHash is not empty, and the acct is new created baseAccount, convert to ethAccount first @@ -174,19 +173,22 @@ func (k *Keeper) SetState(ctx sdk.Context, addr common.Address, key common.Hash, } // SetCode set contract code, delete if code is empty. -func (k *Keeper) SetCode(ctx sdk.Context, codeHash, code []byte) { +func (k *Keeper) SetCode(ctx sdk.Context, addr common.Address, codeHash, code []byte) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixCode) + key := append(addr.Bytes(), codeHash...) + // store or delete code action := "updated" if len(code) == 0 { - store.Delete(codeHash) + store.Delete(key) action = "deleted" } else { - store.Set(codeHash, code) + store.Set(key, code) } k.Logger(ctx).Debug( fmt.Sprintf("code %s", action), + "addr", common.BytesToHash(addr.Bytes()).Hex(), "code-hash", common.BytesToHash(codeHash).Hex(), ) } @@ -217,7 +219,7 @@ func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error { // remove code codeHashBz := ethAcct.GetCodeHash().Bytes() if !bytes.Equal(codeHashBz, types.EmptyCodeHash) { - k.SetCode(ctx, codeHashBz, nil) + k.SetCode(ctx, addr, codeHashBz, nil) } // clear storage diff --git a/x/evm/statedb/interfaces.go b/x/evm/statedb/interfaces.go index 4f41454c..54f33656 100644 --- a/x/evm/statedb/interfaces.go +++ b/x/evm/statedb/interfaces.go @@ -10,7 +10,7 @@ type Keeper interface { // Read methods GetAccount(ctx sdk.Context, addr common.Address) *Account GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash - GetCode(ctx sdk.Context, codeHash common.Hash) []byte + GetCode(ctx sdk.Context, addr common.Address, codeHash common.Hash) []byte // the callback returns false to break early ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) @@ -18,6 +18,6 @@ type Keeper interface { // Write methods, only called by `StateDB.Commit()` SetAccount(ctx sdk.Context, addr common.Address, account Account) error SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) - SetCode(ctx sdk.Context, codeHash []byte, code []byte) + SetCode(ctx sdk.Context, addr common.Address, codeHash []byte, code []byte) DeleteAccount(ctx sdk.Context, addr common.Address) error } diff --git a/x/evm/statedb/state_object.go b/x/evm/statedb/state_object.go index 3ebb800c..4ac18500 100644 --- a/x/evm/statedb/state_object.go +++ b/x/evm/statedb/state_object.go @@ -141,7 +141,7 @@ func (s *stateObject) Code() []byte { if bytes.Equal(s.CodeHash(), emptyCodeHash) { return nil } - code := s.db.keeper.GetCode(s.db.ctx, common.BytesToHash(s.CodeHash())) + code := s.db.keeper.GetCode(s.db.ctx, s.Address(), common.BytesToHash(s.CodeHash())) s.code = code return code } diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index e075308d..c9753581 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -250,8 +250,8 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) // CreateAccount is called during the EVM CREATE operation. The situation might arise that // a contract does the following: // -// 1. sends funds to sha(account ++ (nonce + 1)) -// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) +// 1. sends funds to sha(account ++ (nonce + 1)) +// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) // // Carrying over the balance ensures that Ether doesn't disappear. func (s *StateDB) CreateAccount(addr common.Address) { @@ -444,7 +444,7 @@ func (s *StateDB) Commit() error { } } else { if obj.code != nil && obj.dirtyCode { - s.keeper.SetCode(s.ctx, obj.CodeHash(), obj.code) + s.keeper.SetCode(s.ctx, obj.Address(), obj.CodeHash(), obj.code) } if err := s.keeper.SetAccount(s.ctx, obj.Address(), obj.account); err != nil { return sdkerrors.Wrap(err, "failed to set account")