Skip to content

Commit

Permalink
Added more tests to secret network, and new view method to snapshot (#14
Browse files Browse the repository at this point in the history
)

* Added new tests and bug fix to secret network contract
* Added js script to load snapshot into contract
* Added two new view methods for snapshot contract
* Updated readme to cover new details
  • Loading branch information
akorchyn committed Apr 1, 2024
1 parent 579215a commit db70a7f
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 11 deletions.
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

0 comments on commit db70a7f

Please sign in to comment.