Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ members = [
version = "0.0.1"
authors = ["Artur Troian <troian.ap@gmail.com>"]
edition = "2021"
rust-version = "1.93.0"
rust-version = "1.86.0"

[profile.release]
opt-level = 3
Expand Down
10 changes: 5 additions & 5 deletions _docs/pyth-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -693,12 +693,12 @@ cat > oracle-params-proposal.json << 'EOF'
"summary": "Add the pyth contract address to authorized sources and configure oracle parameters for Pyth integration.",
"messages": [
{
"@type": "/akash.oracle.v1.MsgUpdateParams",
"@type": "/akash.oracle.v2.MsgUpdateParams",
"authority": "akash10d07y265gmmuvt4z0w9aw880jnsr700jhe7z0f",
"params": {
"sources": ["<pyth-contract-address>"],
"min_price_sources": 1,
"max_price_staleness_blocks": 60,
"max_price_staleness_period": 60,
"twap_window": 180,
"max_price_deviation_bps": 150,
"feed_contracts_params": [
Expand Down Expand Up @@ -734,7 +734,7 @@ akash tx gov submit-proposal oracle-params-proposal.json \
|------------------------------|----------|----------------------------------|-----------------|
| `sources` | []String | Authorized contract addresses | `[]` |
| `min_price_sources` | u32 | Minimum sources for valid price | `1` |
| `max_price_staleness_blocks` | i64 | Max age in blocks (~6s/block) | `60` (~6 min) |
| `max_price_staleness_period` | i64 | Max age in seconds (~6s/block) | `60` |
| `twap_window` | i64 | TWAP calculation window (blocks) | `180` (~18 min) |
| `max_price_deviation_bps` | u64 | Max deviation in basis points | `150` (1.5%) |

Expand All @@ -757,7 +757,7 @@ cat > guardian-update-proposal.json << 'EOF'
"summary": "Update guardian addresses to Wormhole Guardian Set 5",
"messages": [
{
"@type": "/akash.oracle.v1.MsgUpdateParams",
"@type": "/akash.oracle.v2.MsgUpdateParams",
"authority": "akash10d07y265gmmuvt4z0w9aw880jnsr700jhe7z0f",
"params": {
"feed_contracts_params": [
Expand Down Expand Up @@ -885,7 +885,7 @@ journalctl -u hermes-client -f
|----------------------------------|-----------------------------------|---------------------------------------------------------------|
| `Unsupported query type: custom` | Node missing custom Akash querier | Upgrade to node v2.x+ with custom querier support |
| `unauthorized oracle provider` | Contract not in `sources` param | Add contract address via governance proposal |
| `price timestamp is too old` | Stale price data | Submit fresher price update or increase `staleness_threshold` |
| `price timestamp is too old` | Stale price data | Submit fresher price update or increase `max_price_staleness_period` |
| `VAA verification failed` | Invalid guardian signatures | Verify guardian set matches current Wormhole mainnet |
| `source not authorized` | Missing from oracle sources | Update oracle params via governance |
| `price timestamp is from future` | Clock skew | Check publisher/relayer clock synchronization |
Expand Down
47 changes: 25 additions & 22 deletions _run/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,12 @@ configure_genesis() {
| jq -M '.app_state.wasm.params.instantiate_default_permission = "Everybody"' \
| jq -M --argjson guardians "$guardian_json" --arg feed_id "$AKT_PRICE_FEED_ID" '
.app_state.oracle.params.min_price_sources = 1 |
.app_state.oracle.params.max_price_staleness_blocks = 100 |
.app_state.oracle.params.max_price_staleness_period = 30 |
.app_state.oracle.params.twap_window = 50 |
.app_state.oracle.params.max_price_deviation_bps = 1000' \
.app_state.oracle.params.max_price_deviation_bps = 1000 |
.app_state.oracle.params.price_retention = "86400s" |
.app_state.oracle.params.prune_epoch = "hour" |
.app_state.oracle.params.max_prune_per_epoch = 1000' \
> "${GENESIS_PATH}"

log "Genesis configuration complete"
Expand Down Expand Up @@ -236,7 +239,7 @@ EOF
{
"admin": "$admin_addr",
"wormhole_contract": "$wormhole_addr",
"update_fee": "1000000",
"update_fee": "1000",
"price_feed_id": "$AKT_PRICE_FEED_ID",
"data_sources": [
{
Expand All @@ -258,8 +261,8 @@ EOF
pyth_addr=$(akash query wasm list-contract-by-code "$pyth_code_id" -o json | jq -r '.contracts[-1]')
log "Pyth contract address: $pyth_addr"

# Register Pyth as authorized oracle source
register_oracle_source "$pyth_addr"
# Register Pyth as authorized oracle source and fund BME vault via gov proposal
register_oracle_source "$pyth_addr" "$admin_addr"

# Write configuration for Hermes
write_hermes_config "$pyth_addr"
Expand All @@ -271,37 +274,37 @@ EOF

register_oracle_source() {
local pyth_addr=$1
log "Registering Pyth contract as authorized oracle source..."
local admin_addr=$2
log "Registering Pyth contract as authorized oracle source and funding BME vault..."

# Build guardian addresses JSON array for the proposal
local guardian_json="["
for i in "${!GUARDIAN_ADDRESSES[@]}"; do
if [ "$i" -gt 0 ]; then
guardian_json+=","
fi
guardian_json+="\"${GUARDIAN_ADDRESSES[$i]}\""
done
guardian_json+="]"

# Create proposal JSON
# Create proposal JSON with both oracle params and BME vault funding
cat > /tmp/oracle-params.json <<EOF
{
"messages": [
{
"@type": "/akash.oracle.v1.MsgUpdateParams",
"@type": "/akash.oracle.v2.MsgUpdateParams",
"authority": "akash10d07y265gmmuvt4z0w9aw880jnsr700jhe7z0f",
"params": {
"sources": ["$pyth_addr"],
"min_price_sources": 1,
"max_price_staleness_blocks": 100,
"max_price_staleness_period": 30,
"twap_window": 50,
"max_price_deviation_bps": 1000
"max_price_deviation_bps": 1000,
"price_retention": "86400s",
"prune_epoch": "hour",
"max_prune_per_epoch": 1000
}
},
{
"@type": "/akash.bme.v1.MsgFundVault",
"authority": "akash10d07y265gmmuvt4z0w9aw880jnsr700jhe7z0f",
"amount": {"denom": "${CHAIN_TOKEN_DENOM}", "amount": "1000000000000"},
"source": "$admin_addr"
}
],
"deposit": "10000000uakt",
"title": "Register Pyth Contract",
"summary": "Authorize pyth contract as oracle source"
"title": "Register Pyth Contract and Fund BME Vault",
"summary": "Authorize pyth contract as oracle source and seed BME vault with initial AKT"
}
EOF

Expand Down
13 changes: 5 additions & 8 deletions _run/node/prop.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
{
"messages": [
{
"@type": "/akash.oracle.v1.MsgUpdateParams",
"@type": "/akash.oracle.v2.MsgUpdateParams",
"authority": "akash10d07y265gmmuvt4z0w9aw880jnsr700jhe7z0f",
"params": {
"sources": [
"akash1xcfl5u6g2yprvpr4q8j2pp5h6l5ys3nuf529qa"
],
"min_price_sources": 1,
"max_price_staleness_blocks": "60",
"max_price_staleness_period": "30",
"twap_window": "50",
"max_price_deviation_bps": "150",
"feed_contracts_params": [
{
"@type": "/akash.oracle.v1.PythContractParams",
"akt_price_feed_id": "0x4ea5bb4d2f5900cc2e97ba534240950740b4d3b89fe712a94a7304fd2fd92702"
}
]
"price_retention": "86400s",
"prune_epoch": "hour",
"max_prune_per_epoch": "1000"
}
}
],
Expand Down
2 changes: 1 addition & 1 deletion app/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
ante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler, options.SigVerifyOptions...),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
}

Expand Down
11 changes: 9 additions & 2 deletions app/types/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import (
etypes "pkg.akt.dev/go/node/escrow/module"
mtypes "pkg.akt.dev/go/node/market/v1"
mvbeta "pkg.akt.dev/go/node/market/v1beta5"
otypes "pkg.akt.dev/go/node/oracle/v1"
otypes "pkg.akt.dev/go/node/oracle/v2"
ptypes "pkg.akt.dev/go/node/provider/v1beta4"
wtypes "pkg.akt.dev/go/node/wasm/v1"
"pkg.akt.dev/go/sdkutil"
Expand Down Expand Up @@ -276,6 +276,7 @@ func (app *App) InitNormalKeepers(
addresscodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()),
AccountAddressPrefix,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
authkeeper.WithUnorderedTransactions(true),
)

app.Keepers.Cosmos.Bank = bankkeeper.NewBaseKeeper(
Expand Down Expand Up @@ -420,12 +421,14 @@ func (app *App) InitNormalKeepers(
app.Keepers.Akash.Oracle = okeeper.NewKeeper(
cdc,
app.keys[otypes.StoreKey],
app.tkeys[otypes.TStoreKey],
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

app.Keepers.Akash.Bme = bmekeeper.NewKeeper(
cdc,
app.keys[bmetypes.StoreKey],
app.tkeys[bmetypes.TStoreKey],
app.AC,
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
app.Keepers.Cosmos.Acct,
Expand Down Expand Up @@ -570,7 +573,9 @@ func (app *App) SetupHooks() {
app.Keepers.Akash.Escrow.AddOnAccountClosedHook(hook.OnEscrowAccountClosed)
app.Keepers.Akash.Escrow.AddOnPaymentClosedHook(hook.OnEscrowPaymentClosed)

app.Keepers.Akash.Epochs.SetHooks(epochstypes.NewMultiEpochHooks())
app.Keepers.Akash.Epochs.SetHooks(epochstypes.NewMultiEpochHooks(
okeeper.EpochHooksFor(app.Keepers.Akash.Oracle),
))
}

// initParamsKeeper init params keeper and its subspaces
Expand Down Expand Up @@ -634,6 +639,8 @@ func kvStoreKeys() []string {
func transientStoreKeys() []string {
return []string{
paramstypes.TStoreKey,
bmetypes.TStoreKey,
otypes.TStoreKey,
}
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/pyth/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pyth"
version = "1.0.0"
version = "1.0.1"
authors = ["Artur Troian <troian.ap@gmail.com"]
edition = "2021"
description = "Pyth price feed consumer contract for Akash Network"
Expand Down
28 changes: 16 additions & 12 deletions contracts/pyth/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,21 +247,25 @@ pub fn execute_update_price_feed(
// Load existing price feed to get previous publish time
let mut price_feed = PRICE_FEED.load(deps.storage)?;

// Ensure new price is not older than current price
if publish_time <= price_feed.publish_time {
// Reject truly older prices
if publish_time < price_feed.publish_time {
return Err(ContractError::InvalidPriceData {
reason: "price data is not newer than current data".to_string(),
reason: "price data is older than current data".to_string(),
});
}

// Update price feed in contract storage
price_feed.prev_publish_time = price_feed.publish_time;
price_feed.price = price;
price_feed.conf = conf;
price_feed.expo = expo;
price_feed.publish_time = publish_time;

PRICE_FEED.save(deps.storage, &price_feed)?;
// Update contract storage for same or newer timestamps.
// Pyth may submit multiple prices within the same timestamp
// but from different slots — all should be accepted.
if publish_time >= price_feed.publish_time {
price_feed.prev_publish_time = price_feed.publish_time;
price_feed.price = price;
price_feed.conf = conf;
price_feed.expo = expo;
price_feed.publish_time = publish_time;

PRICE_FEED.save(deps.storage, &price_feed)?;
}

// Convert Pyth price to decimal string for x/oracle module
let price_decimal = pyth_price_to_decimal(pyth_price.price, expo);
Expand All @@ -281,7 +285,7 @@ pub fn execute_update_price_feed(

// Create Any message to submit price to x/oracle module
let oracle_cosmos_msg: CosmosMsg = CosmosMsg::Any(AnyMsg {
type_url: "/akash.oracle.v1.MsgAddPriceEntry".to_string(),
type_url: "/akash.oracle.v2.MsgAddPriceEntry".to_string(),
value: oracle_data.clone(),
});

Expand Down
Loading
Loading