Шаблон контракта
Начнем с создания новых чернил! проект по созданию избирательного контракта.
В вашем рабочем каталоге запустите:
cargo contract new ballot
Замените содержимое файла lib.rs
шаблоном справа.
Хранилище контракта состоит из AccountId
, который мы инициализируем идентификатором вызывающего абонента в конструкторе. Реализована функция get_chair_person
, которая возвращает идентификатор председателя_person(владельца) контракта.
Структура
Возможно, вы встречали ключевое слово struct в предыдущих руководствах, но до сих пор мы использовали структуры для определения хранилища. контрактов. В этом контракте мы используем его для определения следующих пользовательских типов, которые будут использоваться позже в качестве части хранилища для бюллетеней:
Proposal
: эта структура хранит информацию о предложении. Каждое предложение содержит:name
: поле для хранения названия предложенияvote_count
: 32-битное целое число без знака для хранения количества голосов, полученных за предложение.
- «Избиратель»: для каждого избирателя в системе мы создаем структуру избирателя с помощью:
вес
: вес без знака, указывающий вес избирателя. Вес избирателя может варьироваться в зависимости от параметров выборов/сети.voted
: по умолчанию установлено значение false, но после того, как избиратель проголосовал, оно устанавливается в значение true, чтобы тот же избиратель не мог снова отдать свой голос.делегат
: избиратель может делегировать свой голос кому-то другому. Поскольку избирателям не обязательно делегировать полномочия, это поле создается как «Опция».vote
: индекс предложения, за которое проголосовал пользователь. Это создается как «Опция», установленная на «Нет» по умолчанию.
В отличие от нашей структуры контракта Ballot
, мы не используем макрос ink(storage)
для наших настраиваемых структур, поскольку для контракта может быть только одна структура хранения. Кроме того, наши структуры не являются общедоступными, поскольку пользователям не нужно взаимодействовать с ними напрямую.
Ink_Prelude
ink_pelude
crate предоставляет структуры данных, такие как HashMap
, Vector
и т. д., для работы с памятью контракта во время выполнения контракта. Мы будем импортировать эти коллекции в следующих частях этого руководства, поэтому, прежде чем двигаться дальше, обновите файл контракта cargo.toml со следующей зависимостью: ink_prelude = { version = "3.0.0-rc2", default-features = false}
Компиляция и предупреждения
Вы можете построить контракт, используя cargo +nightly build
, и запустить тесты, используя cargo +nightly test
. Контракт успешно скомпилируется и пройдет все тесты, но компилятор rust выдаст вам следующие предупреждения:
warning: struct is never constructed: `Proposal`
--> lib.rs:10:12
|
10 | struct Proposal {
| ^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: struct is never constructed: `Voter`
--> lib.rs:16:16
|
16 | pub struct Voter {
| ^^^^^
warning: 2 warnings emitted
Это связано с тем, что определенные нами структуры никогда не используются. Мы доберемся до этого в следующей части!
{% tabs %} {% tab title="🔨Starting Point" %}
#![cfg_attr(not(feature = "std"), no_std)]
use ink_lang as ink;
#[ink::contract]
mod ballot {
// Structure to store Proposal information
struct Proposal {
name: String,
vote_count: i32,
}
// Structure to store Proposal information
pub struct Voter {
weight: i32,
voted: bool,
delegate: Option<AccountId>,
vote: Option<i32>,
}
/// Defines the storage of your contract.
/// Add new fields to the below struct in order
/// to add new static storage fields to your contract.
#[ink(storage)]
pub struct Ballot {
chair_person: AccountId,
}
impl Ballot {
#[ink(constructor)]
pub fn new() -> Self {
let owner = Self::env().caller();
Self {
chair_person:owner,
}
}
#[ink(message)]
pub fn get_chairperson(&self) -> AccountId {
self.chair_person
}
}
/// Unit tests in Rust are normally defined within such a `#[cfg(test)]`
/// module and test functions are marked with a `#[test]` attribute.
/// The below code is technically just normal Rust code.
#[cfg(test)]
mod tests {
/// Imports all the definitions from the outer scope so we can use them here.
use super::*;
// Alias `ink_lang` so we can use `ink::test`.
use ink_lang as ink;
#[ink::test]
fn new_works() {
let ballot = Ballot::new();
assert_eq!(ballot.get_chairperson(),AccountId::from([0x1; 32]));
}
}
}
{% endtab %} {% endtabs %}