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

Airdrop | improved privacy #164

Merged
merged 9 commits into from
Jan 17, 2022
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
50 changes: 43 additions & 7 deletions contracts/airdrop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
* Messages
* [CreateAccount](#CreateAccount)
* [UpdateAccount](#UpdateAccount)
* [DisablePermitKey](#DisablePermitKey)
* [Claim](#Claim)
* Queries
* [GetConfig](#GetConfig)
* [GetDates](#GetDates)
* [GetAccount](#GetAccount)
* [Config](#Config)
* [Dates](#Dates)
* [TotalClaimed](#TotalClaimed)
* [Account](#Account)

# Introduction
Contract responsible to handle snip20 airdrop
Expand All @@ -42,6 +44,7 @@ Contract responsible to handle snip20 airdrop
|max_amount | String | Used to limit the user permit amounts (lowers exploit possibility) | no|
|default_claim | String | The default amount to be gifted regardless of tasks | no |
|task_claim | RequiredTasks | The amounts per tasks to gift | no |
|query_rounding | string | To prevent leaking information, total claimed is rounded off to this value | no

##Admin

Expand All @@ -57,13 +60,15 @@ Updates the given values
|start_date | u64 | When the airdrop starts in UNIX time | yes |
|end_date | u64 | When the airdrop ends in UNIX time | yes |
|decay_start | u64 | When the airdrop decay starts in UNIX time | yes |
|padding | string | Allows for enforcing constant length messages | yes |

#### AddTasks
Adds more tasks to complete
##### Request
|Name |Type |Description | optional |
|------|-------|---------------------------|----------|
|Tasks | Tasks | The new tasks to be added | no |
|tasks | Tasks | The new tasks to be added | no |
|padding | string | Allows for enforcing constant length messages | yes |

##### Response
```json
Expand Down Expand Up @@ -96,6 +101,7 @@ Complete that address' tasks for a given user
|Name |Type |Description | optional |
|--------|--------|-------------------------------------|----------|
|address | String | The address that completed the task | no |
|padding | string | Allows for enforcing constant length messages | yes |

##### Response
```json
Expand All @@ -117,6 +123,7 @@ Creates an account from which the user will claim all of his given addresses' re
|-----------|----------------------------------|------------------------------------------|----------|
| addresses | Array of [AddressProofPermit](#AddressProofPermit) | Proof that the user owns those addresses | no |
| partial_tree | Array of string | An array of nodes that serve as a proof for the addresses | no |
|padding | string | Allows for enforcing constant length messages | yes |

##### Response
```json
Expand All @@ -134,6 +141,7 @@ Updates a users accounts with more addresses
|-----------|-----------------------------|------------------------------------------|----------|
| addresses | Array of [AddressProofPermit](#AddressProofPermit) | Proof that the user owns those addresses | no |
| partial_tree | Array of string | An array of nodes that serve as a proof for the addresses | no |
|padding | string | Allows for enforcing constant length messages | yes |

##### Response
```json
Expand All @@ -144,6 +152,23 @@ Updates a users accounts with more addresses
}
```

### DisablePermitKey
Disables that permit's key. Any permit that has that key for that address will be declined.
##### Request
| Name | Type | Description | optional |
|-----------|-----------------------------|------------------------------------------|----------|
| key | string | Permit key | no |
|padding | string | Allows for enforcing constant length messages | yes |

##### Response
```json
{
"disable_permit_key": {
"status": "success"
}
}
```

#### Claim
Claim the user's available claimable amount

Expand All @@ -169,7 +194,7 @@ Gets the contract's config
}
```

## GetDates
## Dates
Get the contracts airdrop timeframe, can calculate the decay factor if a time is given
##### Request
|Name |Type |Description | optional |
Expand All @@ -186,7 +211,18 @@ Get the contracts airdrop timeframe, can calculate the decay factor if a time is
}
```

## GetAccount
## TotalClaimed
Shows the total amount of the token that has been claimed. If airdrop hasn't ended then it'll just show an estimation.
##### Request
```json
{
"total_claimed": {
"claimed": "Claimed amount"
}
}
```

## Account
Get the account's information
##### Request
|Name |Type |Description | optional |
Expand All @@ -195,7 +231,7 @@ Get the account's information
|current_date | u64 | Current time in UNIT format | yes |
```json
{
"eligibility": {
"account": {
"total": "Total airdrop amount",
"claimed": "Claimed amount",
"unclaimed": "Amount available to claim",
Expand Down
150 changes: 97 additions & 53 deletions contracts/airdrop/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
use cosmwasm_std::{to_binary, Api, Binary, Env, Extern, HandleResponse, InitResponse, Querier, StdResult, Storage, Uint128, StdError};
use shade_protocol::{
airdrop::{
InitMsg, HandleMsg,
QueryMsg, Config, claim_info::RequiredTask
}
use crate::{
handle::{
try_add_tasks,
try_claim,
try_claim_decay,
try_complete_task,
try_create_account,
try_disable_permit_key,
try_update_account,
try_update_config,
},
query,
state::{config_w, decay_claimed_w, total_claimed_w},
};
use cosmwasm_std::{
to_binary,
Api,
Binary,
Env,
Extern,
HandleResponse,
InitResponse,
Querier,
StdError,
StdResult,
Storage,
Uint128,
};
use crate::{state::{config_w, total_claimed_w},
handle::{try_update_config, try_add_tasks, try_complete_task, try_create_account,
try_update_account, try_disable_permit_key, try_claim, try_claim_decay},
query };
use crate::state::decay_claimed_w;
use shade_protocol::airdrop::{claim_info::RequiredTask, Config, HandleMsg, InitMsg, QueryMsg};
use secret_toolkit::utils::{pad_handle_result, pad_query_result};

// Used to pad up responses for better privacy.
pub const RESPONSE_BLOCK_SIZE: usize = 256;

pub fn init<S: Storage, A: Api, Q: Querier>(
deps: &mut Extern<S, A, Q>,
env: Env,
msg: InitMsg,
) -> StdResult<InitResponse> {
// Setup task claim
let mut task_claim= vec![RequiredTask {
let mut task_claim = vec![RequiredTask {
address: env.contract.address.clone(),
percent: msg.default_claim
percent: msg.default_claim,
}];
let mut claim = msg.task_claim;
task_claim.append(&mut claim);
Expand All @@ -31,41 +52,46 @@ pub fn init<S: Storage, A: Api, Q: Querier>(
}

if count > Uint128(100) {
return Err(StdError::GenericErr { msg: "tasks above 100%".to_string(), backtrace: None })
return Err(StdError::GenericErr {
msg: "tasks above 100%".to_string(),
backtrace: None,
});
}

let start_date = match msg.start_date {
None => env.block.time,
Some(date) => date
Some(date) => date,
};

if let Some(end_date) = msg.end_date {
if end_date < start_date {
return Err(StdError::generic_err("Start date must come before end date"))
return Err(StdError::generic_err(
"Start date must come before end date",
));
}
}

// Avoid decay collisions
if let Some(start_decay) = msg.decay_start {
if start_decay < start_date {
return Err(StdError::generic_err("Decay cannot start before start date"))
return Err(StdError::generic_err(
"Decay cannot start before start date",
));
}
if let Some(end_date) = msg.end_date {
if start_decay > end_date {
return Err(StdError::generic_err("Decay cannot start after the end date"))
return Err(StdError::generic_err(
"Decay cannot start after the end date",
));
}
}
else {
return Err(StdError::generic_err("Decay must have an end date"))
} else {
return Err(StdError::generic_err("Decay must have an end date"));
}
}

let config = Config{
admin: match msg.admin {
None => { env.message.sender.clone() }
Some(admin) => { admin }
},
contract: env.contract.address.clone(),
let config = Config {
admin: msg.admin.unwrap_or(env.message.sender),
contract: env.contract.address,
dump_address: msg.dump_address,
airdrop_snip20: msg.airdrop_token.clone(),
airdrop_amount: msg.airdrop_amount,
Expand All @@ -76,7 +102,7 @@ pub fn init<S: Storage, A: Api, Q: Querier>(
merkle_root: msg.merkle_root,
total_accounts: msg.total_accounts,
max_amount: msg.max_amount,
query_rounding: msg.query_rounding
query_rounding: msg.query_rounding,
};

config_w(&mut deps.storage).save(&config)?;
Expand All @@ -88,7 +114,7 @@ pub fn init<S: Storage, A: Api, Q: Querier>(

Ok(InitResponse {
messages: vec![],
log: vec![]
log: vec![],
})
}

Expand All @@ -97,36 +123,54 @@ pub fn handle<S: Storage, A: Api, Q: Querier>(
env: Env,
msg: HandleMsg,
) -> StdResult<HandleResponse> {
match msg {
pad_handle_result(match msg {
HandleMsg::UpdateConfig {
admin, dump_address, query_rounding: redeem_step_size,
start_date, end_date, decay_start: start_decay
} => try_update_config(deps, env, admin, dump_address, redeem_step_size,
start_date, end_date, start_decay),
HandleMsg::AddTasks { tasks
} => try_add_tasks(deps, &env, tasks),
HandleMsg::CompleteTask { address
} => try_complete_task(deps, &env, address),
HandleMsg::CreateAccount { addresses, partial_tree
admin,
dump_address,
query_rounding: redeem_step_size,
start_date,
end_date,
decay_start: start_decay,
..
} => try_update_config(
deps,
env,
admin,
dump_address,
redeem_step_size,
start_date,
end_date,
start_decay,
),
HandleMsg::AddTasks { tasks, .. } => try_add_tasks(deps, &env, tasks),
HandleMsg::CompleteTask { address, .. } => try_complete_task(deps, &env, address),
HandleMsg::CreateAccount {
addresses,
partial_tree,
..
} => try_create_account(deps, &env, addresses, partial_tree),
HandleMsg::UpdateAccount { addresses, partial_tree
HandleMsg::UpdateAccount {
addresses,
partial_tree,
..
} => try_update_account(deps, &env, addresses, partial_tree),
HandleMsg::DisablePermitKey { key
} => try_disable_permit_key(deps, &env, key),
HandleMsg::Claim { } => try_claim(deps, &env),
HandleMsg::ClaimDecay { } => try_claim_decay(deps, &env),
}
HandleMsg::DisablePermitKey { key, .. } => try_disable_permit_key(deps, &env, key),
HandleMsg::Claim { .. } => try_claim(deps, &env),
HandleMsg::ClaimDecay { .. } => try_claim_decay(deps, &env),
}, RESPONSE_BLOCK_SIZE)
}

pub fn query<S: Storage, A: Api, Q: Querier>(
deps: &Extern<S, A, Q>,
msg: QueryMsg,
) -> StdResult<Binary> {
match msg {
QueryMsg::Config { } => to_binary(&query::config(&deps)?),
QueryMsg::Dates { current_date } => to_binary(&query::dates(&deps, current_date)?),
QueryMsg::TotalClaimed {} => to_binary(&query::total_claimed(&deps)?),
QueryMsg::Account { permit, current_date } => to_binary(
&query::account(&deps, permit, current_date)?),
}
}
pad_query_result(match msg {
QueryMsg::Config {} => to_binary(&query::config(deps)?),
QueryMsg::Dates { current_date } => to_binary(&query::dates(deps, current_date)?),
QueryMsg::TotalClaimed {} => to_binary(&query::total_claimed(deps)?),
QueryMsg::Account {
permit,
current_date,
} => to_binary(&query::account(deps, permit, current_date)?),
}, RESPONSE_BLOCK_SIZE)
}
Loading