Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(str): Apply changes from internal audit #2476

Merged
merged 5 commits into from
Apr 12, 2024

Conversation

ramacarlucho
Copy link
Contributor

@ramacarlucho ramacarlucho commented Apr 8, 2024

Description

  • Deprecate register coin and update tests
  • Dont allow convertions for native coins.
  • Fix suicide contract for precompile
  • Fix evm consensus version
  • Fix sorted params in evm

Closes: EVM-63


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • tackled an existing issue or discussed with a team member
  • left instructions on how to review the changes
  • targeted the correct branch (see PR Targeting)

Reviewers Checklist

All items are required.
Please add a note if the item is not applicable
and please add your handle next to the items reviewed
if you only reviewed selected items.

I have...

  • added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • confirmed all author checklist items have been addressed
  • confirmed that this PR does not change production code
  • reviewed content
  • tested instructions (if applicable)
  • confirmed all CI checks have passed

@ramacarlucho ramacarlucho requested a review from a team as a code owner April 8, 2024 13:41
@ramacarlucho ramacarlucho requested review from facs95 and 0xstepit and removed request for a team April 8, 2024 13:41
@ramacarlucho ramacarlucho changed the title fix(str): first changes after audit fix(str): Apply changes from internal audit Apr 8, 2024
Copy link

linear bot commented Apr 8, 2024

Copy link
Contributor

@GAtom22 GAtom22 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @ramacarlucho!!

Please, address linter issues
Also, tests are failing

precompiles/bank/integration_test.go Outdated Show resolved Hide resolved
precompiles/outposts/stride/utils_test.go Outdated Show resolved Hide resolved
Copy link
Contributor

@Vvaradinov Vvaradinov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Left some nits, pending passing tests.

x/erc20/keeper/ibc_callbacks.go Outdated Show resolved Hide resolved
x/erc20/keeper/ibc_callbacks.go Show resolved Hide resolved
)

return &types.MsgConvertERC20Response{}, nil
return nil, types.ErrUndefinedOwner
}

// convertERC20NativeToken handles the erc20 conversion for a native erc20 token
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment needs to be updated

Copy link
Contributor

@GAtom22 GAtom22 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Great work @ramacarlucho!!

Copy link
Contributor

@Vvaradinov Vvaradinov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Contributor

@MalteHerrmann MalteHerrmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @ramacarlucho! 🙏 left some comments

testutil/integration/evmos/utils/genesis.go Outdated Show resolved Hide resolved
x/evm/keeper/params.go Outdated Show resolved Hide resolved
Comment on lines 44 to 48
if pair.IsNativeERC20() {
return k.convertERC20IntoCoinsForNativeToken(ctx, pair, msg, receiver, sender) // case 2.1
}

// Check expected receiver balance after transfer
balanceCoinAfter := k.bankKeeper.GetBalance(ctx, receiver, pair.Denom)
expCoin := balanceCoin.Add(coins[0])
if ok := balanceCoinAfter.IsEqual(expCoin); !ok {
return nil, errorsmod.Wrapf(
types.ErrBalanceInvariance,
"invalid coin balance - expected: %v, actual: %v",
expCoin, balanceCoinAfter,
)
}

// Check expected Sender balance after transfer
tokens := coins[0].Amount.BigInt()
balanceTokenAfter := k.BalanceOf(ctx, erc20, contract, sender)
if balanceTokenAfter == nil {
return nil, errorsmod.Wrap(types.ErrEVMCall, "failed to retrieve balance")
}

expToken := big.NewInt(0).Sub(balanceToken, tokens)
if r := balanceTokenAfter.Cmp(expToken); r != 0 {
return nil, errorsmod.Wrapf(
types.ErrBalanceInvariance,
"invalid token balance - expected: %v, actual: %v",
expToken, balanceTokenAfter,
)
}

defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "convert", "erc20", "total"},
1,
[]metrics.Label{
telemetry.NewLabel("denom", pair.Denom),
},
)

if msg.Amount.IsInt64() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "convert", "erc20", "amount", "total"},
float32(msg.Amount.Int64()),
[]metrics.Label{
telemetry.NewLabel("denom", pair.Denom),
},
)
}
}()

ctx.EventManager().EmitEvents(
sdk.Events{
sdk.NewEvent(
types.EventTypeConvertERC20,
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender),
sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
sdk.NewAttribute(types.AttributeKeyCosmosCoin, pair.Denom),
sdk.NewAttribute(types.AttributeKeyERC20Token, msg.ContractAddress),
),
},
)

return &types.MsgConvertERC20Response{}, nil
return nil, types.ErrUndefinedOwner
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the error raised in case it's not a native ERC-20 is incorrect for the native coins, because it claims that the owner is undefined.
We should rather check if it's not an ERC-20 and then return a corresponding error:

Suggested change
if pair.IsNativeERC20() {
return k.convertERC20IntoCoinsForNativeToken(ctx, pair, msg, receiver, sender) // case 2.1
}
// Check expected receiver balance after transfer
balanceCoinAfter := k.bankKeeper.GetBalance(ctx, receiver, pair.Denom)
expCoin := balanceCoin.Add(coins[0])
if ok := balanceCoinAfter.IsEqual(expCoin); !ok {
return nil, errorsmod.Wrapf(
types.ErrBalanceInvariance,
"invalid coin balance - expected: %v, actual: %v",
expCoin, balanceCoinAfter,
)
}
// Check expected Sender balance after transfer
tokens := coins[0].Amount.BigInt()
balanceTokenAfter := k.BalanceOf(ctx, erc20, contract, sender)
if balanceTokenAfter == nil {
return nil, errorsmod.Wrap(types.ErrEVMCall, "failed to retrieve balance")
}
expToken := big.NewInt(0).Sub(balanceToken, tokens)
if r := balanceTokenAfter.Cmp(expToken); r != 0 {
return nil, errorsmod.Wrapf(
types.ErrBalanceInvariance,
"invalid token balance - expected: %v, actual: %v",
expToken, balanceTokenAfter,
)
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "convert", "erc20", "total"},
1,
[]metrics.Label{
telemetry.NewLabel("denom", pair.Denom),
},
)
if msg.Amount.IsInt64() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "convert", "erc20", "amount", "total"},
float32(msg.Amount.Int64()),
[]metrics.Label{
telemetry.NewLabel("denom", pair.Denom),
},
)
}
}()
ctx.EventManager().EmitEvents(
sdk.Events{
sdk.NewEvent(
types.EventTypeConvertERC20,
sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender),
sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
sdk.NewAttribute(types.AttributeKeyCosmosCoin, pair.Denom),
sdk.NewAttribute(types.AttributeKeyERC20Token, msg.ContractAddress),
),
},
)
return &types.MsgConvertERC20Response{}, nil
return nil, types.ErrUndefinedOwner
if !pair.IsNativeERC20() {
return nil, errors.New("converting erc-20s to coins is only supported for native erc-20 tokens")
}
return k.convertERC20IntoCoinsForNativeToken(ctx, pair, msg, receiver, sender)

We also need to delete or adjust the ErrUndefinedOwner in the types if it's not used somewhere else

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ErrUndefinedOwner is used when its an empty token pair.

Comment on lines 66 to 77
// Remove token pair if contract is suicided
acc := k.evmKeeper.GetAccountWithoutBalance(ctx, pair.GetERC20Contract())
if acc == nil || !acc.IsContract() {
k.DeleteTokenPair(ctx, pair)
k.Logger(ctx).Debug(
"deleting selfdestructed token pair from state",
"contract", pair.Erc20Address,
)
// NOTE: return nil error to persist the changes from the deletion
return nil, nil
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm IMO this should remain on the higher level of abstraction in ConvertERC20 - was there a specific reason to move it into this method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved it outside the function, but inside the pair.IsNativeERC20 check to garantee safety

@@ -210,6 +105,8 @@ func (k Keeper) convertERC20NativeToken(
}

// Check expected escrow balance after transfer execution
// NOTE: coin fields already validated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: would be good to mention where it was validated

Suggested change
// NOTE: coin fields already validated
// NOTE: coin fields already validated in the ValidateBasic() of the message

x/erc20/keeper/integration_test.go Show resolved Hide resolved
@@ -34,23 +35,24 @@ func TestPrecompileTestSuite(t *testing.T) {

func (s *PrecompileTestSuite) SetupTest() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not possible for me to comment in that line but in line 20 of this file there is: var _ *PrecompileTestSuite which we should remove I think

precompiles/outposts/stride/utils_test.go Outdated Show resolved Hide resolved
Comment on lines 368 to +370

err = evmosutils.FundAccountWithBaseDenom(s.unitNetwork.GetContext(), s.unitNetwork.App.BankKeeper, sender, 1000000000000000000)
s.Require().NoError(err, "failed to fund account")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this necessary? We should rather set up the test suite with enough funds or adjust the test case to make use of the existing balance I think - also not sure where this amount comes from, why exactly 1000000000000000000?

@@ -32,7 +32,7 @@ type PrecompileTestSuite struct {
network *network.UnitTestNetwork
factory factory.TxFactory
grpcHandler grpc.Handler
keyring testkeyring.Keyring
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would leave this as it was, when renaming the import we are shadowing the import name with the keyring variable below

Suggested change
keyring testkeyring.Keyring
keyring testkeyring.Keyring

@ramacarlucho ramacarlucho merged commit 6d5d101 into Vvaradinov/feat-strv2-feature-branch Apr 12, 2024
31 of 33 checks passed
@ramacarlucho ramacarlucho deleted the rama/str-audit branch April 12, 2024 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants