Skip to content

Commit

Permalink
Combine rewards queries
Browse files Browse the repository at this point in the history
  • Loading branch information
ismellike committed Feb 13, 2024
1 parent e4477df commit 30bfeab
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,18 @@
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"receive"
],
"properties": {
"receive": {
"$ref": "#/definitions/Cw20ReceiveMsg"
}
},
"additionalProperties": false
}
],
"definitions": {
Expand Down Expand Up @@ -237,6 +249,31 @@
}
]
},
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.",
"type": "string"
},
"Cw20ReceiveMsg": {
"description": "Cw20ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg",
"type": "object",
"required": [
"amount",
"msg",
"sender"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"msg": {
"$ref": "#/definitions/Binary"
},
"sender": {
"type": "string"
}
},
"additionalProperties": false
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
Expand Down Expand Up @@ -292,6 +329,10 @@
}
]
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
Expand Down Expand Up @@ -353,7 +394,7 @@
"additionalProperties": false
},
{
"description": "Returns the claimable rewards for the given address.",
"description": "Returns the rewards for the given address.",
"type": "object",
"required": [
"rewards"
Expand All @@ -375,13 +416,13 @@
"additionalProperties": false
},
{
"description": "Returns the expected rewards for the given address",
"description": "Returns the votes count for the given address",
"type": "object",
"required": [
"expected_rewards"
"votes"
],
"properties": {
"expected_rewards": {
"votes": {
"type": "object",
"required": [
"address"
Expand Down Expand Up @@ -478,65 +519,6 @@
},
"additionalProperties": false
},
"expected_rewards": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "RewardResponse",
"type": "object",
"required": [
"amount",
"denom"
],
"properties": {
"amount": {
"$ref": "#/definitions/Uint128"
},
"denom": {
"$ref": "#/definitions/CheckedDenom"
}
},
"additionalProperties": false,
"definitions": {
"Addr": {
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
"type": "string"
},
"CheckedDenom": {
"description": "A denom that has been checked to point to a valid asset. This enum should never be constructed literally and should always be built by calling `into_checked` on an `UncheckedDenom` instance.",
"oneOf": [
{
"description": "A native (bank module) asset.",
"type": "object",
"required": [
"native"
],
"properties": {
"native": {
"type": "string"
}
},
"additionalProperties": false
},
{
"description": "A cw20 asset.",
"type": "object",
"required": [
"cw20"
],
"properties": {
"cw20": {
"$ref": "#/definitions/Addr"
}
},
"additionalProperties": false
}
]
},
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
},
"ownership": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Ownership_for_String",
Expand Down Expand Up @@ -690,6 +672,12 @@
"type": "string"
}
}
},
"votes": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Uint128",
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
}
5 changes: 1 addition & 4 deletions contracts/external/dao-voting-incentives/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,7 @@ pub fn execute(
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::Rewards { address } => to_json_binary(&query::rewards(deps, address)?),
QueryMsg::ExpectedRewards { address } => {
to_json_binary(&query::expected_rewards(deps, env, address)?)
}
QueryMsg::Rewards { address } => to_json_binary(&query::rewards(deps, env, address)?),
QueryMsg::Config {} => to_json_binary(&query::config(deps)?),
QueryMsg::Ownership {} => to_json_binary(&get_ownership(deps.storage)?),
QueryMsg::Votes { address } => to_json_binary(&query::votes(deps, address)?),
Expand Down
9 changes: 6 additions & 3 deletions contracts/external/dao-voting-incentives/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ use crate::{
ContractError,
};

pub fn claim(deps: DepsMut, _env: Env, info: MessageInfo) -> Result<Response, ContractError> {
pub fn claim(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
// Ensure the user has something to claim
if !USER_VOTE_COUNT.has(deps.storage, &info.sender) {
return Err(ContractError::NothingToClaim {});
}

// Get reward information
let reward = reward(deps.as_ref(), &info.sender)?;
let reward = reward(deps.as_ref(), &env.contract.address, &info.sender)?;

// If the user has rewards, then we should generate a message
let mut msgs = vec![];
Expand Down Expand Up @@ -212,13 +212,16 @@ pub fn expire(deps: DepsMut, env: Env, _info: MessageInfo) -> Result<Response, C

pub fn receive_cw20(
deps: DepsMut,
_env: Env,
env: Env,
info: MessageInfo,
_cw20_receive_msg: Cw20ReceiveMsg,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;

// Do not accept unexpected cw20
if config.expiration.is_expired(&env.block) {
return Err(ContractError::AlreadyExpired {});
}
match &config.denom {
CheckedDenom::Native(_) => {
return Err(ContractError::UnexpectedFunds {
Expand Down
5 changes: 1 addition & 4 deletions contracts/external/dao-voting-incentives/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,9 @@ pub enum QueryMsg {
/// Returns the config
#[returns(Config)]
Config {},
/// Returns the claimable rewards for the given address.
/// Returns the rewards for the given address.
#[returns(RewardResponse)]
Rewards { address: String },
/// Returns the expected rewards for the given address
#[returns(RewardResponse)]
ExpectedRewards { address: String },
/// Returns the votes count for the given address
#[returns(Uint128)]
Votes { address: String },
Expand Down
10 changes: 2 additions & 8 deletions contracts/external/dao-voting-incentives/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,10 @@ use crate::{
state::{self, Config, CONFIG, USER_VOTE_COUNT},
};

pub fn rewards(deps: Deps, address: String) -> StdResult<RewardResponse> {
pub fn rewards(deps: Deps, env: Env, address: String) -> StdResult<RewardResponse> {
let address = deps.api.addr_validate(&address)?;

state::reward(deps, &address).map_err(|x| StdError::GenericErr { msg: x.to_string() })
}

pub fn expected_rewards(deps: Deps, env: Env, address: String) -> StdResult<RewardResponse> {
let address = deps.api.addr_validate(&address)?;

state::expected_reward(deps, env, &address)
state::reward(deps, &env.contract.address, &address)
.map_err(|x| StdError::GenericErr { msg: x.to_string() })
}

Expand Down
47 changes: 16 additions & 31 deletions contracts/external/dao-voting-incentives/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{Addr, CheckedMultiplyFractionError, Deps, Env, Uint128};
use cosmwasm_std::{Addr, CheckedMultiplyFractionError, Deps, Uint128};
use cw_denom::CheckedDenom;
use cw_storage_plus::{Item, Map};
use cw_utils::Expiration;
Expand Down Expand Up @@ -34,50 +34,35 @@ pub const GENERIC_PROPOSAL_INFO: Map<(&Addr, u64), GenericProposalInfo> =
Map::new("generic_proposal_info");

/// A method to load reward information
pub fn reward(deps: Deps, addr: &Addr) -> Result<RewardResponse, ContractError> {
pub fn reward(deps: Deps, contract: &Addr, addr: &Addr) -> Result<RewardResponse, ContractError> {
let config = CONFIG.load(deps.storage)?;

// Get the user's votes
let user_votes = USER_VOTE_COUNT
.may_load(deps.storage, addr)?
.unwrap_or_default();

match config.expiration_balance {
Some(balance) => {
// Get the user's votes
let user_votes = USER_VOTE_COUNT
.may_load(deps.storage, addr)?
.unwrap_or_default();
// Calculate the reward
Ok(RewardResponse {
denom: config.denom,
amount: calculate_reward(config.total_votes, user_votes, balance)?,
})
}
None => {
// Get the current voting incentives balance
let balance = config.denom.query_balance(&deps.querier, contract)?;

// Calculate the reward
Ok(RewardResponse {
denom: config.denom,
amount: calculate_reward(config.total_votes, user_votes, balance)?,
})
}
None => Err(ContractError::NotExpired {
expiration: config.expiration,
}),
}
}

/// A method to load the expected reward information
/// The expected reward method can differ from the actual reward, because the balance is saved in state after expiration
pub fn expected_reward(deps: Deps, env: Env, addr: &Addr) -> Result<RewardResponse, ContractError> {
let config = CONFIG.load(deps.storage)?;

// Get the voting incentives balance
let balance = config
.denom
.query_balance(&deps.querier, &env.contract.address)?;

// Get the user's votes
let user_votes = USER_VOTE_COUNT
.may_load(deps.storage, addr)?
.unwrap_or_default();

// Calculate the reward
Ok(RewardResponse {
denom: config.denom,
amount: calculate_reward(config.total_votes, user_votes, balance)?,
})
}

fn calculate_reward(
total_votes: Uint128,
user_votes: Uint128,
Expand Down

0 comments on commit 30bfeab

Please sign in to comment.