diff --git a/.circleci/config.yml b/.circleci/config.yml
index fd8abd4538..bae052e68f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -356,15 +356,15 @@ jobs:
       - run:
           name: Build library for native target (all features)
           working_directory: ~/project/packages/std
-          command: cargo build --locked --features abort,iterator,staking,stargate,cosmwasm_1_3
+          command: cargo build --locked --features abort,iterator,staking,stargate,cosmwasm_1_4
       - run:
           name: Build library for wasm target (all features)
           working_directory: ~/project/packages/std
-          command: cargo wasm --locked --features abort,iterator,staking,stargate,cosmwasm_1_3
+          command: cargo wasm --locked --features abort,iterator,staking,stargate,cosmwasm_1_4
       - run:
           name: Run unit tests (all features)
           working_directory: ~/project/packages/std
-          command: cargo test --locked --features abort,iterator,staking,stargate,cosmwasm_1_3
+          command: cargo test --locked --features abort,iterator,staking,stargate,cosmwasm_1_4
       - save_cache:
           paths:
             - /usr/local/cargo/registry
@@ -907,7 +907,7 @@ jobs:
       - run:
           name: Clippy linting on std (all feature flags)
           working_directory: ~/project/packages/std
-          command: cargo clippy --all-targets --features abort,iterator,staking,stargate,cosmwasm_1_3 -- -D warnings
+          command: cargo clippy --all-targets --features abort,iterator,staking,stargate,cosmwasm_1_4 -- -D warnings
       - run:
           name: Clippy linting on storage (no feature flags)
           working_directory: ~/project/packages/storage
@@ -984,7 +984,7 @@ jobs:
             CRYPTO=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/crypto  --packages cosmwasm-crypto"
             DERIVE=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/derive  --packages cosmwasm-derive"
             SCHEMA=" cargo tarpaulin --skip-clean --out Xml --output-dir reports/schema  --packages cosmwasm-schema"
-            STD="    cargo tarpaulin --skip-clean --out Xml --output-dir reports/std     --packages cosmwasm-std     --features abort,iterator,staking,stargate,cosmwasm_1_3"
+            STD="    cargo tarpaulin --skip-clean --out Xml --output-dir reports/std     --packages cosmwasm-std     --features abort,iterator,staking,stargate,cosmwasm_1_4"
             STORAGE="cargo tarpaulin --skip-clean --out Xml --output-dir reports/storage --packages cosmwasm-storage"
             docker run --security-opt seccomp=unconfined -v "${PWD}:/volume" xd009642/tarpaulin:0.21.0 \
               sh -c "$CRYPTO && $DERIVE && $SCHEMA && $STD && $STORAGE"
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3105948a84..a9e08224c1 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,8 @@
 {
-  "rust-analyzer.cargo.features": ["abort", "stargate", "staking", "cosmwasm_1_3"]
+  "rust-analyzer.cargo.features": [
+    "abort",
+    "stargate",
+    "staking",
+    "cosmwasm_1_4"
+  ]
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9fd9de9720..0f79ddbe7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,14 @@ and this project adheres to
 
 ## [Unreleased]
 
+### Added
+
+- cosmwasm-std: Add
+  `DistributionQuery::{DelegationRewards, DelegationTotalRewards, DelegatorValidators}`.
+  This requires the `cosmwasm_1_4` feature to be enabled. ([#1788])
+
+[#1788]: https://github.com/CosmWasm/cosmwasm/pull/1788
+
 ## [1.4.0-beta.1] - 2023-08-29
 
 ### Added
diff --git a/docs/CAPABILITIES-BUILT-IN.md b/docs/CAPABILITIES-BUILT-IN.md
index 2f2268e4e7..bf31681e9d 100644
--- a/docs/CAPABILITIES-BUILT-IN.md
+++ b/docs/CAPABILITIES-BUILT-IN.md
@@ -19,3 +19,7 @@ might define others.
   `BankQuery::DenomMetadata` and `DistributionQuery::DelegatorWithdrawAddress`
   queries, as well as `DistributionMsg::FundCommunityPool`. Only chains running
   CosmWasm `1.3.0` or higher support this.
+- `cosmwasm_1_4` enables the `DistributionQuery::DelegationRewards`,
+  `DistributionQuery::DelegationTotalRewards` and
+  `DistributionQuery::DelegatorValidators` queries. Only chains running CosmWasm
+  `1.4.0` or higher support this.
diff --git a/docs/USING_COSMWASM_STD.md b/docs/USING_COSMWASM_STD.md
index 36730f9945..19a04bdb66 100644
--- a/docs/USING_COSMWASM_STD.md
+++ b/docs/USING_COSMWASM_STD.md
@@ -45,6 +45,7 @@ The libarary comes with the following features:
 | cosmwasm_1_1 |                    | Features that require CosmWasm 1.1+ on the chain                          |
 | cosmwasm_1_2 |                    | Features that require CosmWasm 1.2+ on the chain                          |
 | cosmwasm_1_3 |                    | Features that require CosmWasm 1.3+ on the chain                          |
+| cosmwasm_1_4 |                    | Features that require CosmWasm 1.4+ on the chain                          |
 
 ## The cosmwasm-std dependency for contract developers
 
diff --git a/packages/check/src/main.rs b/packages/check/src/main.rs
index 6ba097470f..48998f889f 100644
--- a/packages/check/src/main.rs
+++ b/packages/check/src/main.rs
@@ -11,7 +11,7 @@ use cosmwasm_vm::capabilities_from_csv;
 use cosmwasm_vm::internals::{check_wasm, compile, make_compiling_engine};
 
 const DEFAULT_AVAILABLE_CAPABILITIES: &str =
-    "iterator,staking,stargate,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3";
+    "iterator,staking,stargate,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4";
 
 pub fn main() {
     let matches = Command::new("Contract checking")
diff --git a/packages/go-gen/Cargo.toml b/packages/go-gen/Cargo.toml
index 5f3ad6ed74..5b0a24d80e 100644
--- a/packages/go-gen/Cargo.toml
+++ b/packages/go-gen/Cargo.toml
@@ -9,7 +9,7 @@ publish = false
 
 [dependencies]
 schemars = "0.8.3"
-cosmwasm-std = { path = "../std", version = "1.4.0-beta.1", features = ["cosmwasm_1_3", "staking", "stargate", "ibc3"] }
+cosmwasm-std = { path = "../std", version = "1.4.0-beta.1", features = ["cosmwasm_1_4", "staking", "stargate", "ibc3"] }
 cosmwasm-schema = { path = "../schema", version = "1.4.0-beta.1" }
 anyhow = "1"
 Inflector = "0.11.4"
diff --git a/packages/go-gen/src/main.rs b/packages/go-gen/src/main.rs
index 7688db1878..8d3dcc3d40 100644
--- a/packages/go-gen/src/main.rs
+++ b/packages/go-gen/src/main.rs
@@ -352,6 +352,9 @@ mod tests {
         // compare_codes!(cosmwasm_std::ValidatorResponse); // does not use "omitempty" for `Validator` field
         // distribution
         compare_codes!(cosmwasm_std::DelegatorWithdrawAddressResponse);
+        compare_codes!(cosmwasm_std::DelegationRewardsResponse);
+        compare_codes!(cosmwasm_std::DelegationTotalRewardsResponse);
+        compare_codes!(cosmwasm_std::DelegatorValidatorsResponse);
         // wasm
         compare_codes!(cosmwasm_std::ContractInfoResponse);
         // compare_codes!(cosmwasm_std::CodeInfoResponse); // TODO: Checksum type and "omitempty"
diff --git a/packages/go-gen/src/schema.rs b/packages/go-gen/src/schema.rs
index 22e6fd7c97..9d9a3fa866 100644
--- a/packages/go-gen/src/schema.rs
+++ b/packages/go-gen/src/schema.rs
@@ -264,6 +264,7 @@ pub fn custom_type_of(ty: &str) -> Option<&str> {
         "HexBinary" => Some("Checksum"),
         "Addr" => Some("string"),
         "Decimal" => Some("string"),
+        "Decimal256" => Some("string"),
         _ => None,
     }
 }
diff --git a/packages/go-gen/tests/cosmwasm_std__DelegationRewardsResponse.go b/packages/go-gen/tests/cosmwasm_std__DelegationRewardsResponse.go
new file mode 100644
index 0000000000..8779f696dc
--- /dev/null
+++ b/packages/go-gen/tests/cosmwasm_std__DelegationRewardsResponse.go
@@ -0,0 +1,10 @@
+// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L169-L178>
+type DelegationRewardsResponse struct {
+	Rewards []DecCoin `json:"rewards"`
+}
+
+// A coin type with decimal amount. Modeled after the Cosmos SDK's [DecCoin](https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/base/v1beta1/coin.proto#L32-L41) type
+type DecCoin struct {
+	Amount string `json:"amount"`
+	Denom  string `json:"denom"`
+}
\ No newline at end of file
diff --git a/packages/go-gen/tests/cosmwasm_std__DelegationTotalRewardsResponse.go b/packages/go-gen/tests/cosmwasm_std__DelegationTotalRewardsResponse.go
new file mode 100644
index 0000000000..772861c71b
--- /dev/null
+++ b/packages/go-gen/tests/cosmwasm_std__DelegationTotalRewardsResponse.go
@@ -0,0 +1,16 @@
+// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L189-L200>
+type DelegationTotalRewardsResponse struct {
+	Rewards []DelegatorReward `json:"rewards"`
+	Total   []DecCoin         `json:"total"`
+}
+
+// A coin type with decimal amount. Modeled after the Cosmos SDK's [DecCoin](https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/base/v1beta1/coin.proto#L32-L41) type
+type DecCoin struct {
+	Amount string `json:"amount"`
+	Denom  string `json:"denom"`
+}
+
+type DelegatorReward struct {
+	Reward           []DecCoin `json:"reward"`
+	ValidatorAddress string    `json:"validator_address"`
+}
\ No newline at end of file
diff --git a/packages/go-gen/tests/cosmwasm_std__DelegatorValidatorsResponse.go b/packages/go-gen/tests/cosmwasm_std__DelegatorValidatorsResponse.go
new file mode 100644
index 0000000000..3b831e04ad
--- /dev/null
+++ b/packages/go-gen/tests/cosmwasm_std__DelegatorValidatorsResponse.go
@@ -0,0 +1,4 @@
+// See <https://github.com/cosmos/cosmos-sdk/blob/b0acf60e6c39f7ab023841841fc0b751a12c13ff/proto/cosmos/distribution/v1beta1/query.proto#L212-L220>
+type DelegatorValidatorsResponse struct {
+	Validators []string `json:"validators"`
+}
\ No newline at end of file
diff --git a/packages/go-gen/tests/cosmwasm_std__DistributionQuery.go b/packages/go-gen/tests/cosmwasm_std__DistributionQuery.go
index 79b541a7a1..5d33c3805d 100644
--- a/packages/go-gen/tests/cosmwasm_std__DistributionQuery.go
+++ b/packages/go-gen/tests/cosmwasm_std__DistributionQuery.go
@@ -1,8 +1,24 @@
-
 type DelegatorWithdrawAddressQuery struct {
 	DelegatorAddress string `json:"delegator_address"`
 }
+type DelegationRewardsQuery struct {
+	DelegatorAddress string `json:"delegator_address"`
+	ValidatorAddress string `json:"validator_address"`
+}
+type DelegationTotalRewardsQuery struct {
+	DelegatorAddress string `json:"delegator_address"`
+}
+type DelegatorValidatorsQuery struct {
+	DelegatorAddress string `json:"delegator_address"`
+}
 
 type DistributionQuery struct {
+	// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L222-L230>
 	DelegatorWithdrawAddress *DelegatorWithdrawAddressQuery `json:"delegator_withdraw_address,omitempty"`
+	// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L157-L167>
+	DelegationRewards *DelegationRewardsQuery `json:"delegation_rewards,omitempty"`
+	// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L180-L187>
+	DelegationTotalRewards *DelegationTotalRewardsQuery `json:"delegation_total_rewards,omitempty"`
+	// See <https://github.com/cosmos/cosmos-sdk/blob/b0acf60e6c39f7ab023841841fc0b751a12c13ff/proto/cosmos/distribution/v1beta1/query.proto#L202-L210>
+	DelegatorValidators *DelegatorValidatorsQuery `json:"delegator_validators,omitempty"`
 }
\ No newline at end of file
diff --git a/packages/std/Cargo.toml b/packages/std/Cargo.toml
index 8b2487fb7c..b617ef8392 100644
--- a/packages/std/Cargo.toml
+++ b/packages/std/Cargo.toml
@@ -44,6 +44,8 @@ cosmwasm_1_2 = ["cosmwasm_1_1"]
 cosmwasm_1_3 = ["cosmwasm_1_2"]
 # Together with the `iterator` feature this enables additional imports for more
 # efficient iteration over DB keys or values.
+# It also makes `DistributionQuery::{DelegationRewards, DelegationTotalRewards, DelegatorValidators}`
+# available for the contract to call.
 # It requires the host blockchain to run CosmWasm `1.4.0` or higher.
 cosmwasm_1_4 = ["cosmwasm_1_3"]
 
diff --git a/packages/std/src/exports.rs b/packages/std/src/exports.rs
index 473f63a36b..8f057712d4 100644
--- a/packages/std/src/exports.rs
+++ b/packages/std/src/exports.rs
@@ -53,6 +53,10 @@ extern "C" fn requires_cosmwasm_1_2() -> () {}
 #[no_mangle]
 extern "C" fn requires_cosmwasm_1_3() -> () {}
 
+#[cfg(feature = "cosmwasm_1_4")]
+#[no_mangle]
+extern "C" fn requires_cosmwasm_1_4() -> () {}
+
 /// interface_version_* exports mark which Wasm VM interface level this contract is compiled for.
 /// They can be checked by cosmwasm_vm.
 /// Update this whenever the Wasm VM interface breaks.
diff --git a/packages/std/src/lib.rs b/packages/std/src/lib.rs
index 6bccc14595..99706aa22b 100644
--- a/packages/std/src/lib.rs
+++ b/packages/std/src/lib.rs
@@ -69,10 +69,11 @@ pub use crate::pagination::PageRequest;
 pub use crate::query::{
     AllBalanceResponse, AllDelegationsResponse, AllDenomMetadataResponse, AllValidatorsResponse,
     BalanceResponse, BankQuery, BondedDenomResponse, ChannelResponse, CodeInfoResponse,
-    ContractInfoResponse, CustomQuery, Delegation, DelegationResponse,
-    DelegatorWithdrawAddressResponse, DenomMetadataResponse, DistributionQuery, FullDelegation,
-    IbcQuery, ListChannelsResponse, PortIdResponse, QueryRequest, StakingQuery, SupplyResponse,
-    Validator, ValidatorResponse, WasmQuery,
+    ContractInfoResponse, CustomQuery, DecCoin, Delegation, DelegationResponse,
+    DelegationRewardsResponse, DelegationTotalRewardsResponse, DelegatorReward,
+    DelegatorValidatorsResponse, DelegatorWithdrawAddressResponse, DenomMetadataResponse,
+    DistributionQuery, FullDelegation, IbcQuery, ListChannelsResponse, PortIdResponse,
+    QueryRequest, StakingQuery, SupplyResponse, Validator, ValidatorResponse, WasmQuery,
 };
 #[allow(deprecated)]
 pub use crate::results::SubMsgExecutionResponse;
diff --git a/packages/std/src/query/distribution.rs b/packages/std/src/query/distribution.rs
index bd60fa2654..0414ef7927 100644
--- a/packages/std/src/query/distribution.rs
+++ b/packages/std/src/query/distribution.rs
@@ -9,11 +9,23 @@ use super::query_response::QueryResponseType;
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
 #[serde(rename_all = "snake_case")]
 pub enum DistributionQuery {
-    // https://github.com/cosmos/cosmos-sdk/blob/4f6f6c00021f4b5ee486bbb71ae2071a8ceb47c9/x/distribution/types/query.pb.go#L792-L795
+    /// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L222-L230>
     DelegatorWithdrawAddress { delegator_address: String },
+    /// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L157-L167>
+    #[cfg(feature = "cosmwasm_1_4")]
+    DelegationRewards {
+        delegator_address: String,
+        validator_address: String,
+    },
+    /// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L180-L187>
+    #[cfg(feature = "cosmwasm_1_4")]
+    DelegationTotalRewards { delegator_address: String },
+    /// See <https://github.com/cosmos/cosmos-sdk/blob/b0acf60e6c39f7ab023841841fc0b751a12c13ff/proto/cosmos/distribution/v1beta1/query.proto#L202-L210>
+    #[cfg(feature = "cosmwasm_1_4")]
+    DelegatorValidators { delegator_address: String },
 }
 
-// https://github.com/cosmos/cosmos-sdk/blob/4f6f6c00021f4b5ee486bbb71ae2071a8ceb47c9/x/distribution/types/query.pb.go#L832-L835
+/// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L232-L240>
 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
 #[serde(rename_all = "snake_case")]
 #[non_exhaustive]
@@ -22,5 +34,73 @@ pub struct DelegatorWithdrawAddressResponse {
 }
 
 impl_response_constructor!(DelegatorWithdrawAddressResponse, withdraw_address: Addr);
-
 impl QueryResponseType for DelegatorWithdrawAddressResponse {}
+
+/// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L169-L178>
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct DelegationRewardsResponse {
+    pub rewards: Vec<DecCoin>,
+}
+
+impl_response_constructor!(DelegationRewardsResponse, rewards: Vec<DecCoin>);
+impl QueryResponseType for DelegationRewardsResponse {}
+
+/// A coin type with decimal amount.
+/// Modeled after the Cosmos SDK's [DecCoin] type.
+/// However, in contrast to the Cosmos SDK the `amount` string MUST always have a dot at JSON level,
+/// see <https://github.com/cosmos/cosmos-sdk/issues/10863>.
+/// Also if Cosmos SDK choses to migrate away from fixed point decimals
+/// (as shown [here](https://github.com/cosmos/cosmos-sdk/blob/v0.47.4/x/group/internal/math/dec.go#L13-L21 and discussed [here](https://github.com/cosmos/cosmos-sdk/issues/11783)),
+/// wasmd needs to truncate the decimal places to 18.
+///
+/// [DecCoin]: (https://github.com/cosmos/cosmos-sdk/blob/v0.47.4/proto/cosmos/base/v1beta1/coin.proto#L28-L38)
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct DecCoin {
+    pub denom: String,
+    /// An amount in the base denom of the distributed token.
+    ///
+    /// Some chains have choosen atto (10^-18) for their token's base denomination. If we used `Decimal` here, we could only store
+    /// 340282366920938463463.374607431768211455atoken which is 340.28 TOKEN.
+    pub amount: crate::Decimal256,
+}
+
+impl DecCoin {
+    pub fn new(amount: crate::Decimal256, denom: impl Into<String>) -> Self {
+        Self {
+            denom: denom.into(),
+            amount,
+        }
+    }
+}
+
+/// See <https://github.com/cosmos/cosmos-sdk/blob/c74e2887b0b73e81d48c2f33e6b1020090089ee0/proto/cosmos/distribution/v1beta1/query.proto#L189-L200>
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+#[non_exhaustive]
+pub struct DelegationTotalRewardsResponse {
+    pub rewards: Vec<DelegatorReward>,
+    pub total: Vec<DecCoin>,
+}
+
+impl_response_constructor!(
+    DelegationTotalRewardsResponse,
+    rewards: Vec<DelegatorReward>,
+    total: Vec<DecCoin>
+);
+impl QueryResponseType for DelegationTotalRewardsResponse {}
+
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+pub struct DelegatorReward {
+    pub validator_address: String,
+    pub reward: Vec<DecCoin>,
+}
+
+/// See <https://github.com/cosmos/cosmos-sdk/blob/b0acf60e6c39f7ab023841841fc0b751a12c13ff/proto/cosmos/distribution/v1beta1/query.proto#L212-L220>
+#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
+pub struct DelegatorValidatorsResponse {
+    pub validators: Vec<String>,
+}
+
+impl_response_constructor!(DelegatorValidatorsResponse, validators: Vec<String>);
+impl QueryResponseType for DelegatorValidatorsResponse {}
diff --git a/packages/std/src/testing/mock.rs b/packages/std/src/testing/mock.rs
index e3b0248cbf..305af4afb1 100644
--- a/packages/std/src/testing/mock.rs
+++ b/packages/std/src/testing/mock.rs
@@ -5,6 +5,8 @@ use core::ops::Bound;
 use serde::de::DeserializeOwned;
 #[cfg(feature = "stargate")]
 use serde::Serialize;
+#[cfg(feature = "cosmwasm_1_3")]
+use std::collections::BTreeSet;
 use std::collections::HashMap;
 
 use crate::addresses::{Addr, CanonicalAddr};
@@ -39,12 +41,14 @@ use crate::traits::{Api, Querier, QuerierResult};
 use crate::types::{BlockInfo, ContractInfo, Env, MessageInfo, TransactionInfo};
 #[cfg(feature = "cosmwasm_1_3")]
 use crate::{
-    query::{AllDenomMetadataResponse, DenomMetadataResponse},
+    query::{AllDenomMetadataResponse, DecCoin, DenomMetadataResponse},
     PageRequest,
 };
 use crate::{Attribute, DenomMetadata};
 #[cfg(feature = "stargate")]
 use crate::{ChannelResponse, IbcQuery, ListChannelsResponse, PortIdResponse};
+#[cfg(feature = "cosmwasm_1_4")]
+use crate::{Decimal256, DelegationRewardsResponse, DelegatorValidatorsResponse};
 
 use super::riffle_shuffle;
 
@@ -935,12 +939,19 @@ impl StakingQuerier {
 #[derive(Clone, Default)]
 pub struct DistributionQuerier {
     withdraw_addresses: HashMap<String, String>,
+    /// Mock of accumulated rewards, indexed first by delegator and then validator address.
+    rewards: BTreeMap<String, BTreeMap<String, Vec<DecCoin>>>,
+    /// Mock of validators that a delegator has bonded to.
+    validators: BTreeMap<String, BTreeSet<String>>,
 }
 
 #[cfg(feature = "cosmwasm_1_3")]
 impl DistributionQuerier {
     pub fn new(withdraw_addresses: HashMap<String, String>) -> Self {
-        DistributionQuerier { withdraw_addresses }
+        DistributionQuerier {
+            withdraw_addresses,
+            ..Default::default()
+        }
     }
 
     pub fn set_withdraw_address(
@@ -969,6 +980,31 @@ impl DistributionQuerier {
         self.withdraw_addresses.clear();
     }
 
+    /// Sets accumulated rewards for a given validator and delegator pair.
+    pub fn set_rewards(
+        &mut self,
+        validator: impl Into<String>,
+        delegator: impl Into<String>,
+        rewards: Vec<DecCoin>,
+    ) {
+        self.rewards
+            .entry(delegator.into())
+            .or_default()
+            .insert(validator.into(), rewards);
+    }
+
+    /// Sets the validators a given delegator has bonded to.
+    pub fn set_validators(
+        &mut self,
+        delegator: impl Into<String>,
+        validators: impl IntoIterator<Item = impl Into<String>>,
+    ) {
+        self.validators.insert(
+            delegator.into(),
+            validators.into_iter().map(Into::into).collect(),
+        );
+    }
+
     pub fn query(&self, request: &DistributionQuery) -> QuerierResult {
         let contract_result: ContractResult<Binary> = match request {
             DistributionQuery::DelegatorWithdrawAddress { delegator_address } => {
@@ -981,10 +1017,78 @@ impl DistributionQuerier {
                 };
                 to_binary(&res).into()
             }
+            #[cfg(feature = "cosmwasm_1_4")]
+            DistributionQuery::DelegationRewards {
+                delegator_address,
+                validator_address,
+            } => {
+                let res = DelegationRewardsResponse {
+                    rewards: self
+                        .rewards
+                        .get(delegator_address)
+                        .and_then(|v| v.get(validator_address))
+                        .cloned()
+                        .unwrap_or_default(),
+                };
+                to_binary(&res).into()
+            }
+            #[cfg(feature = "cosmwasm_1_4")]
+            DistributionQuery::DelegationTotalRewards { delegator_address } => {
+                let validator_rewards = self
+                    .validator_rewards(delegator_address)
+                    .unwrap_or_default();
+                let res = crate::DelegationTotalRewardsResponse {
+                    total: validator_rewards
+                        .iter()
+                        .fold(BTreeMap::<&str, DecCoin>::new(), |mut acc, rewards| {
+                            for coin in &rewards.reward {
+                                acc.entry(&coin.denom)
+                                    .or_insert_with(|| DecCoin {
+                                        denom: coin.denom.clone(),
+                                        amount: Decimal256::zero(),
+                                    })
+                                    .amount += coin.amount;
+                            }
+
+                            acc
+                        })
+                        .into_values()
+                        .collect(),
+                    rewards: validator_rewards,
+                };
+                to_binary(&res).into()
+            }
+            #[cfg(feature = "cosmwasm_1_4")]
+            DistributionQuery::DelegatorValidators { delegator_address } => {
+                let res = DelegatorValidatorsResponse {
+                    validators: self
+                        .validators
+                        .get(delegator_address)
+                        .map(|set| set.iter().cloned().collect())
+                        .unwrap_or_default(),
+                };
+                to_binary(&res).into()
+            }
         };
         // system result is always ok in the mock implementation
         SystemResult::Ok(contract_result)
     }
+
+    /// Helper method to get all rewards for a given delegator.
+    #[cfg(feature = "cosmwasm_1_4")]
+    fn validator_rewards(&self, delegator_address: &str) -> Option<Vec<crate::DelegatorReward>> {
+        let validator_rewards = self.rewards.get(delegator_address)?;
+
+        Some(
+            validator_rewards
+                .iter()
+                .map(|(validator, rewards)| crate::DelegatorReward {
+                    validator_address: validator.clone(),
+                    reward: rewards.clone(),
+                })
+                .collect(),
+        )
+    }
 }
 
 pub fn digit_sum(input: &[u8]) -> usize {
@@ -1545,6 +1649,104 @@ mod tests {
         assert_eq!(res.withdraw_address, "addr1");
     }
 
+    #[cfg(feature = "cosmwasm_1_4")]
+    #[test]
+    fn distribution_querier_delegator_validators() {
+        let mut distribution = DistributionQuerier::default();
+        distribution.set_validators("addr0", ["valoper1", "valoper2"]);
+
+        let query = DistributionQuery::DelegatorValidators {
+            delegator_address: "addr0".to_string(),
+        };
+
+        let res = distribution.query(&query).unwrap().unwrap();
+        let res: DelegatorValidatorsResponse = from_binary(&res).unwrap();
+        assert_eq!(res.validators, ["valoper1", "valoper2"]);
+
+        let query = DistributionQuery::DelegatorValidators {
+            delegator_address: "addr1".to_string(),
+        };
+
+        let res = distribution.query(&query).unwrap().unwrap();
+        let res: DelegatorValidatorsResponse = from_binary(&res).unwrap();
+        assert_eq!(res.validators, ([] as [String; 0]));
+    }
+
+    #[cfg(feature = "cosmwasm_1_4")]
+    #[test]
+    fn distribution_querier_delegation_rewards() {
+        use crate::{Decimal256, DelegationTotalRewardsResponse, DelegatorReward};
+
+        let mut distribution = DistributionQuerier::default();
+        let valoper0_rewards = vec![
+            DecCoin::new(Decimal256::from_atomics(1234u128, 0).unwrap(), "uatom"),
+            DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest"),
+        ];
+        distribution.set_rewards("valoper0", "addr0", valoper0_rewards.clone());
+
+        // both exist / are set
+        let query = DistributionQuery::DelegationRewards {
+            delegator_address: "addr0".to_string(),
+            validator_address: "valoper0".to_string(),
+        };
+        let res = distribution.query(&query).unwrap().unwrap();
+        let res: DelegationRewardsResponse = from_binary(&res).unwrap();
+        assert_eq!(res.rewards, valoper0_rewards);
+
+        // delegator does not exist
+        let query = DistributionQuery::DelegationRewards {
+            delegator_address: "nonexistent".to_string(),
+            validator_address: "valoper0".to_string(),
+        };
+        let res = distribution.query(&query).unwrap().unwrap();
+        let res: DelegationRewardsResponse = from_binary(&res).unwrap();
+        assert_eq!(res.rewards.len(), 0);
+
+        // validator does not exist
+        let query = DistributionQuery::DelegationRewards {
+            delegator_address: "addr0".to_string(),
+            validator_address: "valopernonexistent".to_string(),
+        };
+        let res = distribution.query(&query).unwrap().unwrap();
+        let res: DelegationRewardsResponse = from_binary(&res).unwrap();
+        assert_eq!(res.rewards.len(), 0);
+
+        // add one more validator
+        let valoper1_rewards = vec![DecCoin::new(Decimal256::one(), "uatom")];
+        distribution.set_rewards("valoper1", "addr0", valoper1_rewards.clone());
+
+        // total rewards
+        let query = DistributionQuery::DelegationTotalRewards {
+            delegator_address: "addr0".to_string(),
+        };
+        let res = distribution.query(&query).unwrap().unwrap();
+        let res: DelegationTotalRewardsResponse = from_binary(&res).unwrap();
+        assert_eq!(
+            res.rewards,
+            vec![
+                DelegatorReward {
+                    validator_address: "valoper0".into(),
+                    reward: valoper0_rewards
+                },
+                DelegatorReward {
+                    validator_address: "valoper1".into(),
+                    reward: valoper1_rewards
+                },
+            ]
+        );
+        assert_eq!(
+            res.total,
+            [
+                DecCoin::new(
+                    Decimal256::from_atomics(1234u128, 0).unwrap() + Decimal256::one(),
+                    "uatom"
+                ),
+                // total for utest should still be the same
+                DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest")
+            ]
+        );
+    }
+
     #[cfg(feature = "stargate")]
     #[test]
     fn ibc_querier_channel_existing() {
diff --git a/packages/std/src/traits.rs b/packages/std/src/traits.rs
index 2118e189d2..a5402660d1 100644
--- a/packages/std/src/traits.rs
+++ b/packages/std/src/traits.rs
@@ -322,6 +322,51 @@ impl<'a, C: CustomQuery> QuerierWrapper<'a, C> {
         self.query(&request)
     }
 
+    #[cfg(feature = "cosmwasm_1_4")]
+    pub fn query_delegation_rewards(
+        &self,
+        delegator: impl Into<String>,
+        validator: impl Into<String>,
+    ) -> StdResult<Vec<crate::DecCoin>> {
+        use crate::DelegationRewardsResponse;
+
+        let request = DistributionQuery::DelegationRewards {
+            delegator_address: delegator.into(),
+            validator_address: validator.into(),
+        }
+        .into();
+        let DelegationRewardsResponse { rewards } = self.query(&request)?;
+
+        Ok(rewards)
+    }
+
+    #[cfg(feature = "cosmwasm_1_4")]
+    pub fn query_delegation_total_rewards(
+        &self,
+        delegator: impl Into<String>,
+    ) -> StdResult<crate::DelegationTotalRewardsResponse> {
+        let request = DistributionQuery::DelegationTotalRewards {
+            delegator_address: delegator.into(),
+        }
+        .into();
+        self.query(&request)
+    }
+
+    #[cfg(feature = "cosmwasm_1_4")]
+    pub fn query_delegator_validators(
+        &self,
+        delegator: impl Into<String>,
+    ) -> StdResult<Vec<String>> {
+        use crate::DelegatorValidatorsResponse;
+
+        let request = DistributionQuery::DelegatorValidators {
+            delegator_address: delegator.into(),
+        }
+        .into();
+        let res: DelegatorValidatorsResponse = self.query(&request)?;
+        Ok(res.validators)
+    }
+
     /// Queries another wasm contract. You should know a priori the proper types for T and U
     /// (response and request) based on the contract API
     pub fn query_wasm_smart<T: DeserializeOwned>(
diff --git a/packages/vm/src/testing/instance.rs b/packages/vm/src/testing/instance.rs
index 0b94321d7e..ce1ba84c07 100644
--- a/packages/vm/src/testing/instance.rs
+++ b/packages/vm/src/testing/instance.rs
@@ -98,8 +98,9 @@ pub struct MockInstanceOptions<'a> {
 impl MockInstanceOptions<'_> {
     fn default_capabilities() -> HashSet<String> {
         #[allow(unused_mut)]
-        let mut out =
-            capabilities_from_csv("iterator,staking,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3");
+        let mut out = capabilities_from_csv(
+            "iterator,staking,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4",
+        );
         #[cfg(feature = "stargate")]
         out.insert("stargate".to_string());
         out