在 NEAR 协议上借用 rust 的混乱

Borrowing confusion in rust on the NEAR protocol

我正在 NEAR 平台上开发智能合约,这是一种彩票。我的结构是一个主合约,它持有一个 Vec 彩票。

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct LottoList{
    owner_id: AccountId,
    lotteries: Vec<NearLotto>,
}

每个彩票由以下结构表示。

#[derive(BorshDeserialize, BorshSerialize)]
pub struct NearLotto {
    lotto_id: u32,
    owner_id: AccountId,
    entries: Vector<AccountId>, //UnorderedMap<u64, AccountId>,
    entry_fee: Balance,
    prize_pool: Balance, 
    climate_pool: Balance,
    winner: AccountId, 
    closed: bool, 
    rand: u128
}

init 创建一个空数组,之后我们可以开始添加新彩票。

#[init]
    pub fn new(owner_id: AccountId) -> Self {
        assert!(env::is_valid_account_id(owner_id.as_bytes()), "Invalid owner account");
        assert!(!env::state_exists(), "Already initialized");
        
        Self {
            owner_id,
            lotteries: Vec::new()
        } 
    }

    pub fn add_lotto(&mut self, owner_id: AccountId, entry_fee:u128, start_pool:u128){
        assert!(self.owner_id == env::signer_account_id(), "Only account owner cna make more lottos");
        let lotto = NearLotto {
            lotto_id: self.lotteries.len() as u32,
            owner_id,
            entries: Vector::new(b'e'),  //UnorderedMap::new(b"entries".to_vec()),
            entry_fee: entry_fee, 
            prize_pool: start_pool,
            climate_pool:0,
            winner: "".to_string(),
            closed: false, 
            rand: 78
        };
        self.lotteries.push(lotto);
    }

我遇到的问题是进入抽奖的功能。具体如下。

#[payable]
    pub fn enter_draw(&mut self, lotto_id:u32){
        // charge some storage fee 
        let mut lotto = &self.lotteries[lotto_id as usize];
        let attached = env::attached_deposit();
        assert!(attached >= lotto.entry_fee, "Entry fee not enough");
        assert!(lotto.entries.len() < MAX_ENTRIES, "Entries are full");
        env::log(format!("money matches, add entry").as_bytes());
        lotto.prize_pool = lotto.prize_pool + (env::attached_deposit()/4)*3; // 75% of entries fees goes into prize pool 
        lotto.climate_pool = lotto.climate_pool + (env::attached_deposit()/4)*3; //25% of entries go to climate change
        lotto.entries.push(&env::signer_account_id()); //self.entries.insert(&k, &near_sdk::env::signer_account_id());
        env::log(format!("{} Entering the lottery", env::signer_account_id()).as_bytes());
        self.lotteries[lotto_id as usize] = lotto;
    }

最后一行给出了错误。

mismatched types

expected struct `NearLotto`, found `&NearLotto` 

我还没有生锈的基础,不知道问题的解决方案。任何想法感激地接受。

我觉得

self.lotteries[lotto_id as usize] = lotto;

应该是

self.lotteries[lotto_id as usize] = *lotto;

您想用乐透参考值更新彩票

您当前的合约设计存在几个问题。

首先是您在内存中使用数据结构。这意味着当您的合约启动时,它必须将整个状态加载到内存中。想为单个乐透做抽奖,但需要支付加载所有乐透的费用。这不会扩展。您应该使用持久性集合,请参阅 https://www.near-sdk.io/contract-structure/collections.

关于你的类型问题。

let mut lotto = &self.lotteries[lotto_id as usize];

这一行创建了一个可变引用,&NearLotto

self.lotteries[lotto_id as usize] = lotto;

然后您尝试在它期望 NearLotto.

时设置引用

由于您正在更新对向量中某个位置的可变引用,因此您无需将其写回,因为您已就地对其进行了变异。因此不需要这一行。