Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/github_actions/bufbuild/buf-setup…
Browse files Browse the repository at this point in the history
…-action-1.47.2
  • Loading branch information
Unique-Divine authored Nov 26, 2024
2 parents d7fa6c9 + 0f96d63 commit 67d6d89
Show file tree
Hide file tree
Showing 20 changed files with 513 additions and 682 deletions.
13 changes: 10 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,18 @@ tests for race conditions within funtoken precompile
- [#2101](https://github.com/NibiruChain/nibiru/pull/2101) - fix(evm): tx receipt proper marshalling
- [#2105](https://github.com/NibiruChain/nibiru/pull/2105) - test(evm): precompile call with revert
- [#2106](https://github.com/NibiruChain/nibiru/pull/2106) - chore: scheduled basic e2e tests for evm testnet endpoint
- [#2107](https://github.com/NibiruChain/nibiru/pull/2107) -
feat(evm-funtoken-precompile): Implement methods: balance, bankBalance, whoAmI
- [#2107](https://github.com/NibiruChain/nibiru/pull/2107) - feat(evm-funtoken-precompile): Implement methods: balance, bankBalance, whoAmI
- [#2108](https://github.com/NibiruChain/nibiru/pull/2108) - fix(evm): removed deprecated root key from eth_getTransactionReceipt
- [#2110](https://github.com/NibiruChain/nibiru/pull/2110) - fix(evm): Restore StateDB to its state prior to ApplyEvmMsg call to ensure deterministic gas usage. This fixes an issue where the StateDB pointer field in NibiruBankKeeper was being updated during readonly query endpoints like eth_estimateGas, leading to non-deterministic gas usage in subsequent transactions.
- [#2111](https://github.com/NibiruChain/nibiru/pull/2111) - fix: e2e-evm-cron.yml
- [#2114](https://github.com/NibiruChain/nibiru/pull/2114) - fix(evm): make gas cost zero in conditional bank keeper flow
- [#2116](https://github.com/NibiruChain/nibiru/pull/2116) - fix(precompile-funtoken.go): Fixes a bug where the err != nil check is missing in the bankBalance precompile method
- [#2117](https://github.com/NibiruChain/nibiru/pull/2117) - fix(oracle): The
timestamps resulting from ctx.WithBlock* don't actually correspond to the block
header information from specified blocks in the chain's history, so the oracle
exchange rates need a way to correctly retrieve this information. This change
fixes that discrepency, giving the expected block timesamp for the EVM's oracle
precompiled contract. The change also simplifies and corrects the code in x/oracle.

#### Nibiru EVM | Before Audit 1 - 2024-10-18

Expand Down Expand Up @@ -235,7 +242,7 @@ feat(evm-funtoken-precompile): Implement methods: balance, bankBalance, whoAmI
- Bump `github.com/holiman/uint256` from 1.2.3 to 1.2.4 ([#1730](https://github.com/NibiruChain/nibiru/pull/1730))
- Bump `github.com/dvsekhvalnov/jose2go` from 1.5.0 to 1.6.0 ([#1733](https://github.com/NibiruChain/nibiru/pull/1733))
- Bump `github.com/spf13/cast` from 1.5.1 to 1.6.0 ([#1689](https://github.com/NibiruChain/nibiru/pull/1689))
- Bump `cosmossdk.io/math` from 1.1.2 to 1.2.0 ([#1676](https://github.com/NibiruChain/nibiru/pull/1676))
- Bump `cosmossdk.io/math` from 1.1.2 to 1.4.0 ([#1676](https://github.com/NibiruChain/nibiru/pull/1676), [#2115](https://github.com/NibiruChain/nibiru/pull/2115))
- Bump `github.com/grpc-ecosystem/grpc-gateway/v2` from 2.18.0 to 2.18.1 ([#1675](https://github.com/NibiruChain/nibiru/pull/1675))
- Bump `actions/setup-go` from 4 to 5 ([#1696](https://github.com/NibiruChain/nibiru/pull/1696))
- Bump `golang` from 1.19 to 1.21 ([#1698](https://github.com/NibiruChain/nibiru/pull/1698))
Expand Down
1 change: 0 additions & 1 deletion app/wasmext/stargate_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ func WasmAcceptedStargateQueries() wasmkeeper.AcceptedStargateQueries {

// nibiru oracle
"/nibiru.oracle.v1.Query/ExchangeRate": new(oracle.QueryExchangeRateResponse),
"/nibiru.oracle.v1.Query/DatedExchangeRate": new(oracle.QueryDatedExchangeRateResponse),
"/nibiru.oracle.v1.Query/ExchangeRateTwap": new(oracle.QueryExchangeRateResponse),
"/nibiru.oracle.v1.Query/ExchangeRates": new(oracle.QueryExchangeRatesResponse),
"/nibiru.oracle.v1.Query/Actives": new(oracle.QueryActivesResponse),
Expand Down
4 changes: 3 additions & 1 deletion eth/rpc/backend/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ func (s *BackendSuite) TestBlockNumber() {
latestHeight, _ := s.network.LatestHeight()
resp, err := s.backend.BlockNumber()
s.Require().NoError(err, resp)
s.Require().Equal(uint64(latestHeight), uint64(blockHeight))
// Rather than checking exact equality, which might not be true due to
// latency. Add a cushion of 2 blocks.
s.Require().LessOrEqual(uint64(latestHeight)-uint64(blockHeight), uint64(2))
}

func (s *BackendSuite) TestGetBlockByNumberr() {
Expand Down
3 changes: 3 additions & 0 deletions evm-e2e/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ test-basic:
# Format
fmt:
npm run format

gen-types:
npx hardhat typechain
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
require (
cosmossdk.io/api v0.7.0 // indirect
cosmossdk.io/errors v1.0.1
cosmossdk.io/math v1.3.0
cosmossdk.io/math v1.4.0
cosmossdk.io/simapp v0.0.0-20230608160436-666c345ad23d
github.com/MakeNowJust/heredoc/v2 v2.0.1
github.com/armon/go-metrics v0.4.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI=
cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM=
cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k=
cosmossdk.io/math v1.4.0 h1:XbgExXFnXmF/CccPPEto40gOO7FpWu9yWNAZPN3nkNQ=
cosmossdk.io/math v1.4.0/go.mod h1:O5PkD4apz2jZs4zqFdTr16e1dcaQCc5z6lkEnrrppuk=
cosmossdk.io/simapp v0.0.0-20230608160436-666c345ad23d h1:E/8y0oG3u9hBR8l4F9MtC0LdZIamPCUwUoLlrHrX86I=
cosmossdk.io/simapp v0.0.0-20230608160436-666c345ad23d/go.mod h1:xbjky3L3DJEylaho6gXplkrMvJ5sFgv+qNX+Nn47bzY=
cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw=
Expand Down
7 changes: 6 additions & 1 deletion proto/nibiru/oracle/v1/oracle.proto
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,19 @@ message ExchangeRateTuple {
];
}

message DatedPrice {
message ExchangeRateAtBlock {
string exchange_rate = 1 [
(gogoproto.moretags) = "yaml:\"exchange_rate\"",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];

uint64 created_block = 2 [ (gogoproto.moretags) = "yaml:\"created_block\"" ];

// Block timestamp for the block where the oracle came to consensus for this
// price. This timestamp is a conventional Unix millisecond time, i.e. the
// number of milliseconds elapsed since January 1, 1970 UTC.
int64 block_timestamp_ms = 3 [ (gogoproto.moretags) = "yaml:\"block_timestamp_ms\"" ];
}

// Rewards defines a credit object towards validators
Expand Down
28 changes: 7 additions & 21 deletions proto/nibiru/oracle/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ option go_package = "github.com/NibiruChain/nibiru/v2/x/oracle/types";

// Query defines the gRPC querier service.
service Query {
// ExchangeRate returns exchange rate of a pair
// ExchangeRate returns exchange rate of a pair along with the block height and
// block time that the exchange rate was set by the oracle module.
rpc ExchangeRate(QueryExchangeRateRequest)
returns (QueryExchangeRateResponse) {
option (google.api.http).get = "/nibiru/oracle/v1beta1/exchange_rate";
Expand All @@ -22,12 +23,6 @@ service Query {
option (google.api.http).get = "/nibiru/oracle/v1beta1/exchange_rate_twap";
}

// DatedExchangeRate returns latest price of a pair
rpc DatedExchangeRate(QueryExchangeRateRequest)
returns (QueryDatedExchangeRateResponse) {
option (google.api.http).get = "/nibiru/oracle/v1beta1/dated_exchange_rate";
}

// ExchangeRates returns exchange rates of all pairs
rpc ExchangeRates(QueryExchangeRatesRequest)
returns (QueryExchangeRatesResponse) {
Expand Down Expand Up @@ -114,20 +109,6 @@ message QueryExchangeRateResponse {
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}

// QueryExchangeRatesRequest is the request type for the Query/ExchangeRates RPC
// method.
message QueryExchangeRatesRequest {
}

// QueryDatedExchangeRateResponse is the request type for the
// Query/DatedExchangeRate RPC method.
message QueryDatedExchangeRateResponse {
string price = 1 [
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];

// Block timestamp for the block where the oracle came to consensus for this
// price. This timestamp is a conventional Unix millisecond time, i.e. the
Expand All @@ -138,6 +119,11 @@ message QueryDatedExchangeRateResponse {
uint64 block_height = 3;
}

// QueryExchangeRatesRequest is the request type for the Query/ExchangeRates RPC
// method.
message QueryExchangeRatesRequest {
}

// QueryExchangeRatesResponse is response type for the
// Query/ExchangeRates RPC method.
message QueryExchangeRatesResponse {
Expand Down
9 changes: 9 additions & 0 deletions x/evm/keeper/bank_extension.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper

import (
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
auth "github.com/cosmos/cosmos-sdk/x/auth/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
Expand Down Expand Up @@ -84,6 +85,14 @@ func (bk *NibiruBankKeeper) SyncStateDBWithAccount(
if bk.StateDB == nil {
return
}

cachedGasConfig := ctx.KVGasConfig()
defer func() {
ctx = ctx.WithKVGasConfig(cachedGasConfig)
}()

// set gas cost to zero for this conditional operation
ctx = ctx.WithKVGasConfig(storetypes.GasConfig{})
balanceWei := evm.NativeToWei(
bk.GetBalance(ctx, acc, evm.EVMBankDenom).Amount.BigInt(),
)
Expand Down
8 changes: 7 additions & 1 deletion x/evm/precompile/funtoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func (p precompileFunToken) sendToBank(

erc20, amount, to, err := p.parseArgsSendToBank(args)
if err != nil {
err = ErrInvalidArgs(err)
return
}

Expand Down Expand Up @@ -376,6 +377,10 @@ func (p precompileFunToken) bankBalance(
}

addrEth, addrBech32, bankDenom, err := p.parseArgsBankBalance(args)
if err != nil {
err = ErrInvalidArgs(err)
return
}
bankBal := p.evmKeeper.Bank.GetBalance(ctx, addrBech32, bankDenom).Amount.BigInt()

return method.Outputs.Pack([]any{
Expand Down Expand Up @@ -455,7 +460,8 @@ func (p precompileFunToken) whoAmI(

addrEth, addrBech32, err := p.parseArgsWhoAmI(args)
if err != nil {
return bz, err
err = ErrInvalidArgs(err)
return
}

return method.Outputs.Pack([]any{
Expand Down
8 changes: 6 additions & 2 deletions x/evm/precompile/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,16 @@ func (p precompileOracle) queryExchangeRate(
return nil, err
}

price, blockTime, blockHeight, err := p.oracleKeeper.GetDatedExchangeRate(ctx, assetPair)
priceAtBlock, err := p.oracleKeeper.ExchangeRates.Get(ctx, assetPair)
if err != nil {
return nil, err
}

return method.Outputs.Pack(price.BigInt(), uint64(blockTime), blockHeight)
return method.Outputs.Pack(
priceAtBlock.ExchangeRate.BigInt(),
uint64(priceAtBlock.BlockTimestampMs),
priceAtBlock.CreatedBlock,
)
}

func (p precompileOracle) parseQueryExchangeRateArgs(args []any) (
Expand Down
55 changes: 43 additions & 12 deletions x/evm/precompile/oracle_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package precompile_test

import (
"fmt"
"math/big"
"testing"
"time"
Expand All @@ -9,6 +10,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/suite"

"github.com/NibiruChain/nibiru/v2/x/evm"
"github.com/NibiruChain/nibiru/v2/x/evm/embeds"
"github.com/NibiruChain/nibiru/v2/x/evm/evmtest"
"github.com/NibiruChain/nibiru/v2/x/evm/precompile"
Expand Down Expand Up @@ -56,14 +58,12 @@ func (s *OracleSuite) TestOracle_FailToPackABI() {

func (s *OracleSuite) TestOracle_HappyPath() {
deps := evmtest.NewTestDeps()

s.T().Log("Query exchange rate")
{
deps.Ctx = deps.Ctx.WithBlockTime(time.Unix(69, 420)).WithBlockHeight(69)
deps.App.OracleKeeper.SetPrice(deps.Ctx, "unibi:uusd", sdk.MustNewDecFromStr("0.067"))

resp, err := deps.EvmKeeper.CallContract(
deps.Ctx,
runQuery := func(ctx sdk.Context) (
resp *evm.MsgEthereumTxResponse,
err error,
) {
return deps.EvmKeeper.CallContract(
ctx,
embeds.SmartContract_Oracle.ABI,
deps.Sender.EthAddr,
&precompile.PrecompileAddr_Oracle,
Expand All @@ -72,16 +72,47 @@ func (s *OracleSuite) TestOracle_HappyPath() {
"queryExchangeRate",
"unibi:uusd",
)
}

s.T().Log("Query exchange rate")
{
// 69 seconds + 420 nanoseconds === 69000 milliseconds for the
// return value from the UnixMilli() function
deps.Ctx = deps.Ctx.WithBlockTime(time.Unix(69, 420)).WithBlockHeight(69)
deps.App.OracleKeeper.SetPrice(deps.Ctx, "unibi:uusd", sdk.MustNewDecFromStr("0.067"))

resp, err := runQuery(deps.Ctx)
s.NoError(err)

// Check the response
out, err := embeds.SmartContract_Oracle.ABI.Unpack(string(precompile.OracleMethod_queryExchangeRate), resp.Ret)
out, err := embeds.SmartContract_Oracle.ABI.Unpack(
string(precompile.OracleMethod_queryExchangeRate), resp.Ret,
)
s.NoError(err)
s.Equal(out[0].(*big.Int), big.NewInt(67_000_000_000_000_000))
s.Equal(fmt.Sprintf("%d", out[1].(uint64)), "69000")
s.Equal(fmt.Sprintf("%d", out[2].(uint64)), "69")
}

s.T().Log("Query from a later time")
{
secondsLater := deps.Ctx.BlockTime().Add(100 * time.Second)
resp, err := runQuery(deps.Ctx.
WithBlockTime(secondsLater).
WithBlockHeight(deps.Ctx.BlockHeight() + 50),
)
s.NoError(err)

// Check the response
s.Equal(out[0].(*big.Int), big.NewInt(67000000000000000))
s.Equal(out[1].(uint64), uint64(69000))
s.Equal(out[2].(uint64), uint64(69))
out, err := embeds.SmartContract_Oracle.ABI.Unpack(
string(precompile.OracleMethod_queryExchangeRate), resp.Ret,
)
s.NoError(err)
// These terms should still be equal because the latest exchange rate
// has not changed.
s.Equal(out[0].(*big.Int), big.NewInt(67_000_000_000_000_000))
s.Equal(fmt.Sprintf("%d", out[1].(uint64)), "69000")
s.Equal(fmt.Sprintf("%d", out[2].(uint64)), "69")
}
}

Expand Down
7 changes: 6 additions & 1 deletion x/oracle/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ func TestExportInitGenesis(t *testing.T) {

input.OracleKeeper.Params.Set(input.Ctx, types.DefaultParams())
input.OracleKeeper.FeederDelegations.Insert(input.Ctx, keeper.ValAddrs[0], keeper.Addrs[1])
input.OracleKeeper.ExchangeRates.Insert(input.Ctx, "pair1:pair2", types.DatedPrice{ExchangeRate: math.LegacyNewDec(123), CreatedBlock: 0})
input.OracleKeeper.ExchangeRates.Insert(input.Ctx, "pair1:pair2",
types.ExchangeRateAtBlock{
ExchangeRate: math.LegacyNewDec(123),
CreatedBlock: 0,
BlockTimestampMs: 0,
})
input.OracleKeeper.Prevotes.Insert(input.Ctx, keeper.ValAddrs[0], types.NewAggregateExchangeRatePrevote(types.AggregateVoteHash{123}, keeper.ValAddrs[0], uint64(2)))
input.OracleKeeper.Votes.Insert(input.Ctx, keeper.ValAddrs[0], types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Pair: "foo", ExchangeRate: math.LegacyNewDec(123)}}, keeper.ValAddrs[0]))
input.OracleKeeper.WhitelistedPairs.Insert(input.Ctx, "pair1:pair1")
Expand Down
27 changes: 6 additions & 21 deletions x/oracle/keeper/querier.go → x/oracle/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ func (q querier) ExchangeRate(c context.Context, req *types.QueryExchangeRateReq
}

ctx := sdk.UnwrapSDKContext(c)
exchangeRate, err := q.Keeper.GetExchangeRate(ctx, req.Pair)
out, err := q.Keeper.ExchangeRates.Get(ctx, req.Pair)
if err != nil {
return nil, err
}

return &types.QueryExchangeRateResponse{ExchangeRate: exchangeRate}, nil
return &types.QueryExchangeRateResponse{
ExchangeRate: out.ExchangeRate,
BlockTimestampMs: out.BlockTimestampMs,
BlockHeight: out.CreatedBlock,
}, nil
}

/*
Expand All @@ -79,24 +82,6 @@ func (q querier) ExchangeRateTwap(c context.Context, req *types.QueryExchangeRat
return &types.QueryExchangeRateResponse{ExchangeRate: twap}, nil
}

// get the latest price snapshot from the oracle for a pair
func (q querier) DatedExchangeRate(c context.Context, req *types.QueryExchangeRateRequest) (response *types.QueryDatedExchangeRateResponse, err error) {
if _, err = q.ExchangeRate(c, req); err != nil {
return
}

ctx := sdk.UnwrapSDKContext(c)
price, blockTime, blockHeight, err := q.Keeper.GetDatedExchangeRate(ctx, req.Pair)
if err != nil {
return &types.QueryDatedExchangeRateResponse{}, err
}
return &types.QueryDatedExchangeRateResponse{
Price: price,
BlockTimestampMs: blockTime,
BlockHeight: blockHeight,
}, nil
}

// ExchangeRates queries exchange rates of all pairs
func (q querier) ExchangeRates(c context.Context, _ *types.QueryExchangeRatesRequest) (*types.QueryExchangeRatesResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
Expand Down
Loading

0 comments on commit 67d6d89

Please sign in to comment.