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

Added more tests to secret network, and new view methods to snapshot #14

Merged
merged 8 commits into from
Apr 1, 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
15 changes: 15 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,18 @@ jobs:
- name: Run tests
if: env.GIT_DIFF
run: npm run test
- uses: actions/upload-artifact@v4
if: env.GIT_DIFF
with:
name: secret-network-contract.tar.gz
path: contracts/secret_contract/contract.wasm.gz
if-no-files-found: error
overwrite: true
- uses: actions/upload-artifact@v4
if: env.GIT_DIFF
with:
name: snapshot-contract
path: target/near/voting_snapshot/*
if-no-files-found: error
overwrite: true

2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ data
node_modules

stake*
snapshot*
snapshot*.json*

.env
8 changes: 7 additions & 1 deletion contracts/secret_contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ pub fn instantiate(
_info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
if !MY_KEYS.is_empty(deps.storage) {
return Err(ContractError::AlreadyInitialized);
}

create_keys(deps, env, msg.end_time)?;

Ok(Response::default())
Expand Down Expand Up @@ -57,7 +61,9 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result<Binary, ContractErro
}

fn query_keys(deps: Deps, env: Env) -> Result<KeysResponse, ContractError> {
let my_keys = MY_KEYS.load(deps.storage)?;
let my_keys = MY_KEYS
.load(deps.storage)
.map_err(|_| ContractError::NotInitialized)?;
let private = (env.block.time > my_keys.end_time).then(|| my_keys.private_key);

Ok(KeysResponse {
Expand Down
6 changes: 6 additions & 0 deletions contracts/secret_contract/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ pub enum ContractError {

#[error("Invalid End Time")]
InvalidEndTime,

#[error("Already initialized")]
AlreadyInitialized,

#[error("Not initialized yet")]
NotInitialized,
}
54 changes: 53 additions & 1 deletion contracts/secret_contract/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use cosmwasm_std::{testing::*, Timestamp};
use secp256k1::{PublicKey, Secp256k1};

use crate::contract::{instantiate, query};
use crate::error::ContractError;
use crate::msg::{InstantiateMsg, KeysResponse, QueryMsg};

fn setup_contract(
Expand Down Expand Up @@ -43,6 +44,43 @@ fn proper_initialization() {
assert!(PublicKey::from_slice(&value.public).is_ok());
}

#[test]
fn user_cant_reinitialize() {
let time = Timestamp::from_seconds(500);
let mut mock_env = mock_env();

mock_env.block.time = time.minus_seconds(5);

let mut deps = setup_contract(time, mock_env.clone());

let info = mock_info(
"creator",
&[Coin {
denom: "earth".to_string(),
amount: Uint128::new(1000),
}],
);

let res = query(deps.as_ref(), mock_env.clone(), QueryMsg::GetKeys {}).unwrap();
let init: KeysResponse = from_binary(&res).unwrap();

assert_eq!(
instantiate(
deps.as_mut(),
mock_env.clone(),
info,
InstantiateMsg {
end_time: time.plus_seconds(10),
},
),
Err(ContractError::AlreadyInitialized)
);
let res = query(deps.as_ref(), mock_env, QueryMsg::GetKeys {}).unwrap();
let upd: KeysResponse = from_binary(&res).unwrap();

assert_eq!(init, upd);
}

#[test]
fn invalid_time_is_failure() {
let time = Timestamp::from_seconds(500);
Expand All @@ -60,7 +98,10 @@ fn invalid_time_is_failure() {

let init_msg = InstantiateMsg { end_time: time };

instantiate(deps.as_mut(), mock_env, info, init_msg).expect_err("Should fail");
assert_eq!(
instantiate(deps.as_mut(), mock_env, info, init_msg),
Err(ContractError::InvalidEndTime)
);
}

#[test]
Expand Down Expand Up @@ -92,3 +133,14 @@ fn secret_revealed_after_time_pass() {
PublicKey::from_slice(&value.public).unwrap()
);
}

#[test]
fn cannot_fetch_uninitialized_contract() {
let deps = mock_dependencies();
let mock_env = mock_env();

assert_eq!(
query(deps.as_ref(), mock_env, QueryMsg::GetKeys {}),
Err(ContractError::NotInitialized)
);
}
11 changes: 11 additions & 0 deletions contracts/voting_snapshot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ To deploy manually, install [`cargo-near`](https://github.com/near/cargo-near) a
cargo near deploy <account-id>
```

## How to load snapshot?

To load snapshot use js script prepared for it.

```bash
node ../../snapshotter/loadSnapshot.js --contract contractID --json ../../snapshot-108194270.json --network testnet --account adminId
```

## Contract interface

```rust
Expand Down Expand Up @@ -60,6 +68,9 @@ pub fn is_nominee(self, nominee: &AccountId) -> bool
pub fn is_eligible_voter(self, voter: &AccountId) -> bool
pub fn get_voter_information(self, voter: &AccountId) -> VoterInformation
pub fn get_voters_info(self, voters: Vec<AccountId>) -> Vec<(AccountId, VoterInformation)>
pub fn get_total_eligible_users(&self) -> u32
pub fn get_total_voters(&self) -> u32
pub fn get_eligible_voter_info(&self, account_id: &AccountId) -> Option<UserData>

// Callbacks:
pub fn on_refund_success(self, account_id: AccountId) -> ()
Expand Down
10 changes: 9 additions & 1 deletion contracts/voting_snapshot/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ impl Contract {
self.assert_initialization();
self.assert_admin();

self.eligible_voters.extend(voters);
let mut new_accounts = 0;
for (key, value) in voters.into_iter() {
if self.eligible_voters.insert(key, value).is_none() {
new_accounts += 1;
}
}
self.total_eligible_users += new_accounts;

self.eligible_voters.flush();
require!(
Expand Down Expand Up @@ -210,6 +216,8 @@ mod tests {
contract.bulk_load_voters(voters.clone());

assert!(contract.is_eligible_voter(&voters[0].0));

assert_eq!(contract.get_total_eligible_users(), 4);
}

#[test]
Expand Down
7 changes: 7 additions & 0 deletions contracts/voting_snapshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@ pub struct Contract {
// for full snapshot, please refer to the IPFS storage
// Will be cleaned on halt.
eligible_voters: LookupMap<AccountId, UserData>,
total_eligible_users: u32,

// We need to collect the ones who want to participate in the vote process
// We collect the public key of the voter to verify the signature
// in the encoded message.
// Also, this user indicates that he/she accepts conduct of fair voting
voters: LookupMap<AccountId, PublicKey>,
total_voters: u32,

nominees: LookupSet<AccountId>,

// People can deposit NEAR to challenge snapshot
Expand Down Expand Up @@ -74,6 +77,8 @@ impl Contract {
process_config,
vote_config,
end_time_in_millis: 0,
total_voters: 0,
total_eligible_users: 0,
eligible_voters: LookupMap::new(StorageKey::EligibleVoters),
voters: LookupMap::new(StorageKey::Voters),
nominees: LookupSet::new(StorageKey::Nominees),
Expand Down Expand Up @@ -103,6 +108,7 @@ impl Contract {
self.assert_eligible_voter(&signer);

self.voters.insert(signer, env::signer_account_pk());
self.total_voters += 1;

self.voters.flush();
require!(
Expand All @@ -129,6 +135,7 @@ impl Contract {
require!(!self.voters.contains_key(&user), ALREADY_REGISTERED);

self.voters.insert(user, public_key);
self.total_voters += 1;

self.voters.flush();

Expand Down
26 changes: 25 additions & 1 deletion contracts/voting_snapshot/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,28 @@ impl Contract {
.filter_map(|voter| self.get_voter_information(&voter).map(|info| (voter, info)))
.collect()
}

/// *View*: Returns amount of eligible users to become voters
pub fn get_total_eligible_users(&self) -> u32 {
self.total_eligible_users
}

/// *View*: Shows total number of voters that are registered
pub fn get_total_voters(&self) -> u32 {
self.total_voters
}

/// *View*: displays information about snapshot data for particular account
pub fn get_eligible_voter_info(&self, account_id: &AccountId) -> Option<UserData> {
self.eligible_voters.get(account_id).cloned()
}
}

#[cfg(test)]
mod tests {
use near_sdk::{testing_env, NearToken};

use crate::test_utils::*;
use crate::{test_utils::*, types::UserData};

#[test]
fn user_can_get_vote_config() {
Expand All @@ -116,6 +131,13 @@ mod tests {
let (_context, contract) = setup_ctr();

let vote_power = contract.get_vote_power(&acc(1)).unwrap();
assert_eq!(
Some(UserData {
stake: NearToken::from_near(1),
active_months: 1,
}),
contract.get_eligible_voter_info(&acc(1))
);
assert_eq!(vote_power, 11);
}

Expand All @@ -135,6 +157,8 @@ mod tests {

contract.register_as_voter();

assert_eq!(contract.get_total_voters(), 1);

let voter_info = contract.get_voter_information(&acc(1)).unwrap();
assert_eq!(voter_info.vote_weight, 11);
assert_eq!(voter_info.public_key, pk());
Expand Down
Loading
Loading