블록체인
[블록체인] 전자투표 웹 만들기 - 컨트랙트 디플로이
박은성/
2022. 7. 19. 16:57
반응형
<투표 컨트랙트(lib.rs)>
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::json_types::{U128, U64};
use near_sdk::{env, near_bindgen, AccountId, Balance, EpochHeight};
use std::collections::HashMap;
#[global_allocator]
static ALLOC: near_sdk::wee_alloc::WeeAlloc = near_sdk::wee_alloc::WeeAlloc::INIT;
type WrappedTimestamp = U64;
/// Voting contract for unlocking transfers. Once the majority of the stake holders agree to
/// unlock transfer, the time will be recorded and the voting ends.
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct VotingContract {
/// How much each validator votes
votes: HashMap<AccountId, Balance>,
/// Total voted balance so far.
total_voted_stake: Balance,
/// When the voting ended. `None` means the poll is still open.
result: Option<WrappedTimestamp>,
/// Epoch height when the contract is touched last time.
last_epoch_height: EpochHeight,
}
impl Default for VotingContract {
fn default() -> Self {
env::panic(b"Voting contract should be initialized before usage")
}
}
#[near_bindgen]
impl VotingContract {
#[init]
pub fn new() -> Self {
assert!(!env::state_exists(), "The contract is already initialized");
VotingContract {
votes: HashMap::new(),
total_voted_stake: 0,
result: None,
last_epoch_height: 0,
}
}
/// Ping to update the votes according to current stake of validators.
pub fn ping(&mut self) {
assert!(self.result.is_none(), "Voting has already ended");
let cur_epoch_height = env::epoch_height();
if cur_epoch_height != self.last_epoch_height {
let votes = std::mem::take(&mut self.votes);
self.total_voted_stake = 0;
for (account_id, _) in votes {
let account_current_stake = env::validator_stake(&account_id);
self.total_voted_stake += account_current_stake;
if account_current_stake > 0 {
self.votes.insert(account_id, account_current_stake);
}
}
self.check_result();
self.last_epoch_height = cur_epoch_height;
}
}
/// Check whether the voting has ended.
fn check_result(&mut self) {
assert!(
self.result.is_none(),
"check result is called after result is already set"
);
let total_stake = env::validator_total_stake();
if self.total_voted_stake > 2 * total_stake / 3 {
self.result = Some(U64::from(env::block_timestamp()));
}
}
/// Method for validators to vote or withdraw the vote.
/// Votes for if `is_vote` is true, or withdraws the vote if `is_vote` is false.
pub fn vote(&mut self, is_vote: bool) {
self.ping();
if self.result.is_some() {
return;
}
let account_id = env::predecessor_account_id();
let account_stake = if is_vote {
let stake = env::validator_stake(&account_id);
assert!(stake > 0, "{} is not a validator", account_id);
stake
} else {
0
};
let voted_stake = self.votes.remove(&account_id).unwrap_or_default();
assert!(
voted_stake <= self.total_voted_stake,
"invariant: voted stake {} is more than total voted stake {}",
voted_stake,
self.total_voted_stake
);
self.total_voted_stake = self.total_voted_stake + account_stake - voted_stake;
if account_stake > 0 {
self.votes.insert(account_id, account_stake);
self.check_result();
}
}
/// Get the timestamp of when the voting finishes. `None` means the voting hasn't ended yet.
pub fn get_result(&self) -> Option<WrappedTimestamp> {
self.result.clone()
}
/// Returns current a pair of `total_voted_stake` and the total stake.
/// Note: as a view method, it doesn't recompute the active stake. May need to call `ping` to
/// update the active stake.
pub fn get_total_voted_stake(&self) -> (U128, U128) {
(
self.total_voted_stake.into(),
env::validator_total_stake().into(),
)
}
/// Returns all active votes.
/// Note: as a view method, it doesn't recompute the active stake. May need to call `ping` to
/// update the active stake.
pub fn get_votes(&self) -> HashMap<AccountId, U128> {
self.votes
.iter()
.map(|(account_id, stake)| (account_id.clone(), (*stake).into()))
.collect()
}
}
이게 맞나 싶으니 컴파일해 봅시다.
cargo build --target wasm32-unknown-unknown --release
카고 명령어로 이 rs 파일을 wasm파일로 생성해 준다.
타겟 디렉토리에 wasm 파일이 생겼다.
near login
로그인을 하면 된다.
넥스트 누르고 verify 하면 된다
굿~
near deploy viimpt.testnet ./contract/target/wasm32-unknown-unknown/release/voting.wasm
아 드디어 ㅜㅜ 코드 컴파일 이후 해당 바이트 코드를 니어 프로토콜에 디플로이 했다.
아이고ㅜㅜ 드디어 ㅜㅜhttps://explorer.testnet.near.org/transactions/G4dmBKRZNn6sXRPrA63hPCS9a423oMx2CN5kFVNHqKcX
반응형