Skip to content

Commit

Permalink
feat: use ctx to get timestamp for query
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasmatt committed Oct 29, 2024
1 parent 9cf67f2 commit 3597fc7
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 101 deletions.
1 change: 1 addition & 0 deletions app/wasmext/stargate_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ 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
3 changes: 3 additions & 0 deletions proto/nibiru/oracle/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ message QueryDatedExchangeRateResponse {

// milliseconds since unix epoch
int64 timestamp_ms = 2;

// height of the block
uint64 height = 3;
}

// QueryExchangeRatesResponse is response type for the
Expand Down
122 changes: 122 additions & 0 deletions x/evm/embeds/artifacts/contracts/IOracle.sol/IChainlink.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{
"_format": "hh-sol-artifact-1",
"contractName": "IChainlink",
"sourceName": "contracts/IOracle.sol",
"abi": [
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "description",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint80",
"name": "_roundId",
"type": "uint80"
}
],
"name": "getRoundData",
"outputs": [
{
"internalType": "uint80",
"name": "roundId",
"type": "uint80"
},
{
"internalType": "int256",
"name": "answer",
"type": "int256"
},
{
"internalType": "uint256",
"name": "startedAt",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "updatedAt",
"type": "uint256"
},
{
"internalType": "uint80",
"name": "answeredInRound",
"type": "uint80"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "latestRoundData",
"outputs": [
{
"internalType": "uint80",
"name": "roundId",
"type": "uint80"
},
{
"internalType": "int256",
"name": "answer",
"type": "int256"
},
{
"internalType": "uint256",
"name": "startedAt",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "updatedAt",
"type": "uint256"
},
{
"internalType": "uint80",
"name": "answeredInRound",
"type": "uint80"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
],
"bytecode": "0x",
"deployedBytecode": "0x",
"linkReferences": {},
"deployedLinkReferences": {}
}
16 changes: 13 additions & 3 deletions x/evm/embeds/artifacts/contracts/IOracle.sol/IOracle.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@
"name": "queryExchangeRate",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
"internalType": "uint256",
"name": "price",
"type": "uint256"
},
{
"internalType": "uint64",
"name": "blockTimeMs",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "blockHeight",
"type": "uint64"
}
],
"stateMutability": "view",
Expand Down
44 changes: 41 additions & 3 deletions x/evm/embeds/contracts/IOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,50 @@ interface IOracle {
/// @notice Queries the dated exchange rate for a given pair
/// @param pair The asset pair to query. For example, "ubtc:uusd" is the
/// USD price of BTC and "unibi:uusd" is the USD price of NIBI.
/// @return The exchange rate (a decimal value) as a string and the block
/// at which it was cerated.
/// @return price The exchange rate for the given pair
/// @return blockTimeMs The block time in milliseconds when the price was
/// last updated
/// @return blockHeight The block height when the price was last updated
/// @dev This function is view-only and does not modify state.
function queryExchangeRate(
string memory pair
) external view returns (string memory, uint256);
)
external
view
returns (uint256 price, uint64 blockTimeMs, uint64 blockHeight);
}

// solhint-disable-next-line interface-starts-with-i
interface IChainlink {
function decimals() external view returns (uint8);

function description() external view returns (string memory);

function version() external view returns (uint256);

function getRoundData(
uint80 _roundId
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);

function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}

address constant ORACLE_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000801;
Expand Down
4 changes: 2 additions & 2 deletions x/evm/precompile/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ func (p precompileOracle) queryExchangeRate(
return nil, err
}

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

return method.Outputs.Pack(price.String())
return method.Outputs.Pack(price.BigInt(), uint64(blockTime), blockHeight)
}

func (p precompileOracle) decomposeQueryExchangeRateArgs(args []any) (
Expand Down
8 changes: 7 additions & 1 deletion x/evm/precompile/oracle_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package precompile_test

import (
"math/big"
"testing"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -55,7 +57,9 @@ func (s *OracleSuite) TestOracle_HappyPath() {

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"))

input, err := embeds.SmartContract_Oracle.ABI.Pack("queryExchangeRate", "unibi:uusd")
s.NoError(err)
resp, _, err := deps.EvmKeeper.CallContractWithInput(
Expand All @@ -68,7 +72,9 @@ func (s *OracleSuite) TestOracle_HappyPath() {
s.NoError(err)

// Check the response
s.Equal("exchange_rate:\"67000000000000000\" created_block:1 ", out[0].(string))
s.Equal(out[0].(*big.Int), big.NewInt(67000000000000000))
s.Equal(out[1].(uint64), uint64(69000))
s.Equal(out[2].(uint64), uint64(69))
}
}

Expand Down
21 changes: 7 additions & 14 deletions x/oracle/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,21 +187,14 @@ func (k Keeper) GetExchangeRate(ctx sdk.Context, pair asset.Pair) (price sdk.Dec
return
}

func (k Keeper) GetDatedExchangeRate(ctx sdk.Context, pair asset.Pair) (exchangeRate types.PriceSnapshot, err error) {
iterator := k.PriceSnapshots.Iterate(
ctx,
collections.PairRange[asset.Pair, time.Time]{}.
Prefix(pair).
Descending(),
)
defer iterator.Close()

if iterator.Valid() {
exchangeRate = iterator.Value()
return exchangeRate, nil
} else {
return types.PriceSnapshot{}, types.ErrInvalidExchangeRate.Wrapf("no snapshots for pair %s", pair.String())
func (k Keeper) GetDatedExchangeRate(ctx sdk.Context, pair asset.Pair) (price sdk.Dec, blockTimeMs int64, BlockHeight uint64, err error) {
exchangeRate, err := k.ExchangeRates.Get(ctx, pair)
if err != nil {
return
}
time := ctx.WithBlockHeight(int64(exchangeRate.CreatedBlock)).BlockTime()

return exchangeRate.ExchangeRate, time.UnixMilli(), exchangeRate.CreatedBlock, nil
}

// SetPrice sets the price for a pair as well as the price snapshot.
Expand Down
4 changes: 2 additions & 2 deletions x/oracle/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ func (q querier) DatedExchangeRate(c context.Context, req *types.QueryExchangeRa
}

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

// ExchangeRates queries exchange rates of all pairs
Expand Down
Loading

0 comments on commit 3597fc7

Please sign in to comment.