Skip to content

Commit

Permalink
Merge pull request #236 from stratosnet/fix-EVM-set-code
Browse files Browse the repository at this point in the history
QB-1761: Fix evm contract destroy
  • Loading branch information
alexstratos authored Mar 28, 2023
2 parents bc075d4 + 6250dc6 commit a794975
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 17 deletions.
4 changes: 2 additions & 2 deletions x/evm/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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,
}

Expand Down
2 changes: 1 addition & 1 deletion x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
18 changes: 10 additions & 8 deletions x/evm/keeper/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(),
)
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions x/evm/statedb/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ 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)

// 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
}
2 changes: 1 addition & 1 deletion x/evm/statedb/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions x/evm/statedb/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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")
Expand Down

0 comments on commit a794975

Please sign in to comment.