Skip to content

Commit

Permalink
fix(evm-keeper): better utilize ERC20 metadata during FunToken creati…
Browse files Browse the repository at this point in the history
…on (#2074)

* fix(evm-keeper): better utilize ERC20 metadata during FunToken creation

* chore: changelog
  • Loading branch information
Unique-Divine authored Oct 11, 2024
1 parent f450c79 commit 62d4b1a
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#2060](https://github.com/NibiruChain/nibiru/pull/2060) - fix(evm-precompiles): add assertNumArgs validation
- [#2056](https://github.com/NibiruChain/nibiru/pull/2056) - feat(evm): add oracle precompile
- [#2065](https://github.com/NibiruChain/nibiru/pull/2065) - refactor(evm)!: Refactor out dead code from the evm.Params
- [#2073](https://github.com/NibiruChain/nibiru/pull/2073) - fix(evm-keeper): better utilize ERC20 metadata during FunToken creation


#### Dapp modules: perp, spot, oracle, etc
Expand Down
5 changes: 3 additions & 2 deletions proto/buf.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
version: v1
name: buf.build/NibiruChain/nibiru
# Corresponds to Buf Schema Registry repo: https://buf.build/nibiru-chain/nibiru
name: buf.build/nibiru-chain/nibiru
deps:
- buf.build/cosmos/cosmos-proto
- buf.build/cosmos/cosmos-sdk:v0.47.3
Expand All @@ -22,4 +23,4 @@ lint:
- PACKAGE_DIRECTORY_MATCH

ignore:
- tendermint
- tendermint
84 changes: 68 additions & 16 deletions x/evm/keeper/funtoken_from_erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ func (k Keeper) FindERC20Metadata(
}, nil
}

// ERC20Metadata: Optional metadata fields parsed from an ERC20 contract.
// The [Wrapped Ether contract] is a good example for reference.
//
// ```solidity
// constract WETH9 {
// string public name = "Wrapped Ether";
// string public symbol = "WETH"
// uint8 public decimals = 18;
// }
// ```
//
// Note that the name and symbol fields may be empty, according to the [ERC20
// specification].
//
// [Wrapped Ether contract]: https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
// [ERC20 specification]: https://eips.ethereum.org/EIPS/eip-20
type ERC20Metadata struct {
Name string
Symbol string
Expand Down Expand Up @@ -98,7 +114,7 @@ func (k *Keeper) createFunTokenFromERC20(
}

// 2 | Get existing ERC20 metadata
info, err := k.FindERC20Metadata(ctx, erc20)
erc20Info, err := k.FindERC20Metadata(ctx, erc20)
if err != nil {
return funtoken, err
}
Expand All @@ -115,21 +131,7 @@ func (k *Keeper) createFunTokenFromERC20(
}

// 4 | Set bank coin denom metadata in state
bankMetadata := bank.Metadata{
Description: fmt.Sprintf(
"ERC20 token \"%s\" represented as a bank coin with a corresponding FunToken mapping", erc20.String(),
),
DenomUnits: []*bank.DenomUnit{
{
Denom: bankDenom,
Exponent: 0, // TODO(k-yang): determine which exponent to use
},
},
Base: bankDenom,
Display: bankDenom,
Name: bankDenom,
Symbol: info.Symbol,
}
bankMetadata := erc20Info.ToBankMetadata(bankDenom, erc20)

err = bankMetadata.Validate()
if err != nil {
Expand All @@ -150,3 +152,53 @@ func (k *Keeper) createFunTokenFromERC20(
ctx, erc20, bankDenom, false,
)
}

// ToBankMetadata produces the "bank.Metadata" corresponding to a FunToken
// mapping created from an ERC20 token.
//
// The first argument of DenomUnits is required and the official base unit
// onchain, meaning the denom must be equivalent to bank.Metadata.Base.
//
// Decimals for an ERC20 are synonymous to "bank.DenomUnit.Exponent" in what
// they mean for external clients like wallets.
func (erc20Info ERC20Metadata) ToBankMetadata(
bankDenom string, erc20 gethcommon.Address,
) bank.Metadata {
var symbol string
if erc20Info.Symbol != "" {
symbol = erc20Info.Symbol
} else {
symbol = bankDenom
}

var name string
if erc20Info.Name != "" {
name = erc20Info.Name
} else {
name = bankDenom
}

denomUnits := []*bank.DenomUnit{
{
Denom: bankDenom,
Exponent: 0,
},
}
display := symbol
if erc20Info.Decimals > 0 {
denomUnits = append(denomUnits, &bank.DenomUnit{
Denom: display,
Exponent: uint32(erc20Info.Decimals),
})
}
return bank.Metadata{
Description: fmt.Sprintf(
"ERC20 token \"%s\" represented as a Bank Coin with a corresponding FunToken mapping", erc20.String(),
),
DenomUnits: denomUnits,
Base: bankDenom,
Display: display,
Name: name,
Symbol: symbol,
}
}
17 changes: 17 additions & 0 deletions x/evm/keeper/funtoken_from_erc20_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/suite"

Expand Down Expand Up @@ -101,6 +102,22 @@ func (s *FunTokenFromErc20Suite) TestCreateFunTokenFromERC20() {
IsMadeFromCoin: false,
},
)
bankMetadata, _ := deps.App.BankKeeper.GetDenomMetaData(deps.Ctx, expectedBankDenom)
s.Require().Equal(bank.Metadata{
Description: fmt.Sprintf(
"ERC20 token \"%s\" represented as a Bank Coin with a corresponding FunToken mapping", erc20Addr.String(),
),
DenomUnits: []*bank.DenomUnit{
{Denom: expectedBankDenom, Exponent: 0},
{Denom: metadata.Symbol, Exponent: uint32(metadata.Decimals)},
},
Base: expectedBankDenom,
Display: metadata.Symbol,
Name: metadata.Name,
Symbol: metadata.Symbol,
URI: "",
URIHash: "",
}, bankMetadata)

s.T().Log("sad: CreateFunToken for the ERC20: already registered")
// Give the sender funds for the fee
Expand Down

0 comments on commit 62d4b1a

Please sign in to comment.