Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seperate pick #1

Merged
merged 2 commits into from
Apr 14, 2024
Merged
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ The contract is deployed on the Juno Network and integrates with the Nois protoc
- **Instantiation**: Sets up the contract with the Nois proxy address and participant count.
- **Execution**:
- **Request Randomness**: Initiates a randomness request to the Nois protocol, requiring a unique job ID and necessary funds.
- **Pick Winners (Nois Receive)**: Receives randomness from Nois, selects 100 winners, and handles different outcomes based on the job ID context ("test" or regular).
- **Nois Receive**: Receives randomness from Nois, then saves the randomness based on the job ID. If the job id constains the word "test", the contract will save the randomness as a test value. Otherwise, it will save the randomness as the final value. Test value can be reseted if another request is made. But the final value can only be set once.
- **Pick Test Winners**: Selects test winners based on the test randomness value.
- **Pick Winners**: Selects winners based on the final randomness value.
- **Queries**: Provides smart queries for accessing participant count, list of winners, admin details, etc.

# **Setup and Configuration**
Expand Down
2 changes: 1 addition & 1 deletion artifacts/checksums.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
12bf66626d6c7972664a19b0c6394cf65de38a831d84c2340a096656316a5859 raffle_drop.wasm
a9a6edecd2fc2c37a161d5a28a25c80cf2b577007d4350f92354b2920df476cf raffle_drop.wasm
2 changes: 1 addition & 1 deletion artifacts/checksums_intermediate.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
45da052c35dc16f3d2080236dbf00daac2d7c2e8850c897871c3b7d614b52152 /target/wasm32-unknown-unknown/release/raffle_drop.wasm
1fd30a662f8a48b58a6a9e6167085550b9fdfedbc06e338f81ec801f7f55c1d4 /target/wasm32-unknown-unknown/release/raffle_drop.wasm
Binary file modified artifacts/raffle_drop.wasm
Binary file not shown.
125 changes: 92 additions & 33 deletions src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
use crate::state::{ADMIN, NOIS_PROXY, PARTICIPANT_COUNT, TEST_WINNERS, WINNERS};
use crate::state::{
ADMIN, FINAL_RANDOMNESS, NOIS_PROXY, PARTICIPANT_COUNT, TEST_RANDOMNESS, TEST_WINNERS, WINNERS,
};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
Expand Down Expand Up @@ -46,34 +48,45 @@ pub fn execute(
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::RequestRandomness { job_id } => {
execute_request_randomness(deps, env, info, job_id)
}
ExecuteMsg::NoisReceive { callback } => execute_pick_winners(deps, env, info, callback),
ExecuteMsg::RequestRandomness {
job_id,
delay_in_mins,
} => execute_request_randomness(deps, env, info, job_id, delay_in_mins),
ExecuteMsg::NoisReceive { callback } => execute_set_randomness(deps, env, info, callback),
ExecuteMsg::PickTestWinners {} => pick_test_winners(deps, env, info),
ExecuteMsg::PickWinners {} => pick_winners(deps, env, info),
}
}

pub fn execute_request_randomness(
deps: DepsMut,
_env: Env,
env: Env,
info: MessageInfo,
job_id: String,
delay_in_mins: u64,
) -> Result<Response, ContractError> {
let nois_proxy = NOIS_PROXY.load(deps.storage)?;

if info.sender != ADMIN.load(deps.storage)? {
return Err(ContractError::Unauthorized {});
}

let res = Response::new().add_message(WasmMsg::Execute {
contract_addr: nois_proxy.into(),
msg: to_json_binary(&ProxyExecuteMsg::GetNextRandomness { job_id })?,
funds: info.funds.clone(),
});
let now = env.block.time;
let res = Response::new()
.add_message(WasmMsg::Execute {
contract_addr: nois_proxy.into(),
msg: to_json_binary(&ProxyExecuteMsg::GetRandomnessAfter {
after: now.plus_minutes(delay_in_mins),
job_id: job_id.clone(),
})?,
funds: info.funds.clone(),
})
.add_attribute("action", "request_randomness")
.add_attribute("job_id", job_id)
.add_attribute("after", now.plus_minutes(delay_in_mins).to_string());
Ok(res)
}

pub fn execute_pick_winners(
pub fn execute_set_randomness(
deps: DepsMut,
_env: Env,
info: MessageInfo,
Expand All @@ -86,34 +99,80 @@ pub fn execute_pick_winners(
job_id, randomness, ..
} = callback;

let randomness: [u8; 32] = randomness
.to_array()
.map_err(|_| ContractError::InvalidRandomness {})?;
if job_id.contains("test") {
TEST_RANDOMNESS.save(deps.storage, &randomness)?;
} else {
if FINAL_RANDOMNESS.may_load(deps.storage)?.is_some() {
return Err(ContractError::FinalRandomnessAlreadySet {});
}
FINAL_RANDOMNESS.save(deps.storage, &randomness)?;
}

let res = Response::new();
Ok(res)
}

pub fn pick_test_winners(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
) -> Result<Response, ContractError> {
let participant_count = PARTICIPANT_COUNT.load(deps.storage)?;
let participant_arr = (1..=participant_count).collect::<Vec<u32>>();
let participants = (1..=participant_count).collect::<Vec<u32>>();
let test_randomness = TEST_RANDOMNESS.load(deps.storage)?;
let test_randomness_vec: [u8; 32] = test_randomness[..].try_into().unwrap();

let winners = pick(randomness, 100, participant_arr);
let winners_string = winners
if test_randomness.is_empty() {
return Err(ContractError::TestRandomnessNotSet {});
}

let winners = pick(test_randomness_vec, 100, participants);
let winners_str = winners
.iter()
.map(|&x| x.to_string())
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(", ");
.join(",");
TEST_WINNERS.save(deps.storage, &winners)?;

match job_id.as_str() {
"test" => {
TEST_WINNERS.save(deps.storage, &winners)?;
}
_ => {
let old_winners = WINNERS.may_load(deps.storage)?;
if old_winners.is_some() {
return Err(ContractError::WinnersAlreadyPicked {});
}
WINNERS.save(deps.storage, &winners)?;
}
let res = Response::new()
.add_attribute("action", "pick_test_winners")
.add_attribute("test winners", winners_str);
Ok(res)
}

pub fn pick_winners(
deps: DepsMut,
_env: Env,
info: MessageInfo,
) -> Result<Response, ContractError> {
if info.sender != ADMIN.load(deps.storage)? {
return Err(ContractError::Unauthorized {});
}
if WINNERS.may_load(deps.storage)?.is_some() {
return Err(ContractError::WinnersAlreadyPicked {});
}

let res = Response::new().add_attribute("winners", winners_string);
let participant_count = PARTICIPANT_COUNT.load(deps.storage)?;
let participants = (1..=participant_count).collect::<Vec<u32>>();

let final_randomness = FINAL_RANDOMNESS
.load(deps.storage)
.map_err(|_| ContractError::FinalRandomnessNotSet {})?;
let final_randomness_vec: [u8; 32] = final_randomness[..].try_into().unwrap();

let winners = pick(final_randomness_vec, 100, participants);
let winners_str = winners
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(",");

WINNERS.save(deps.storage, &winners)?;

let res = Response::new()
.add_attribute("action", "pick_winners")
.add_attribute("winners", winners_str);

Ok(res)
}

Expand Down
9 changes: 9 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,13 @@ pub enum ContractError {

#[error("Winners already picked")]
WinnersAlreadyPicked {},

#[error("Test randomness not set")]
TestRandomnessNotSet {},

#[error("Final randomness not set")]
FinalRandomnessNotSet {},

#[error("Final randomness already set")]
FinalRandomnessAlreadySet {},
}
4 changes: 3 additions & 1 deletion src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ pub struct InstantiateMsg {

#[cw_serde]
pub enum ExecuteMsg {
RequestRandomness { job_id: String },
RequestRandomness { job_id: String, delay_in_mins: u64 },
NoisReceive { callback: NoisCallback },
PickTestWinners {},
PickWinners {},
}

#[cw_serde]
Expand Down
4 changes: 3 additions & 1 deletion src/state.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use cosmwasm_std::Addr;
use cosmwasm_std::{Addr, HexBinary};
use cw_storage_plus::Item;

pub const PARTICIPANT_COUNT: Item<u32> = Item::new("participant_count");
pub const NOIS_PROXY: Item<Addr> = Item::new("nois_proxy");
pub const ADMIN: Item<Addr> = Item::new("admin");
pub const WINNERS: Item<Vec<u32>> = Item::new("winners");
pub const TEST_WINNERS: Item<Vec<u32>> = Item::new("test_winners");
pub const TEST_RANDOMNESS: Item<HexBinary> = Item::new("test_randomness");
pub const FINAL_RANDOMNESS: Item<HexBinary> = Item::new("final_randomness");
Loading