1. Dalam fungsi internal_restake, mengapa kita harus mengakses fungsi on_stake_action seolah-olah itu adalah panggilan kontrak silang eksternal padahal fungsinya adalah bagian dari kontrak panggilan? Tidak bisakah kita melakukan .then(self.on_stake_action()) saja? Saya berasumsi itu ada hubungannya dengan wajah bahwa itu adalah panggilan balik dari panggilan janji stake().

  2. Dalam situasi apa Anda akan membuat antarmuka untuk kontrak itu sendiri seperti ext_self?

  3. Apa yang dilakukan makro #[ext_contract()] secara singkat?


    -------- Kode Kontrak Staking Pool Di Bawah -------------------- lib.rs lines 155~162

/// Interface for the contract itself.
#[ext_contract(ext_self)]
pub trait SelfContract {
    /// A callback to check the result of the staking action.
    fn on_stake_action(&mut self);
}

lib.rs baris 399~421

   pub fn on_stake_action(&mut self) {
        assert_eq!(
            env::current_account_id(),
            env::predecessor_account_id(),
            "Can be called only as a callback"
        );

        assert_eq!(
            env::promise_results_count(),
            1,
            "Contract expected a result on the callback"
        );
        let stake_action_succeeded = match env::promise_result(0) {
            PromiseResult::Successful(_) => true,
            _ => false,
        };

        // If the stake action failed and the current locked amount is positive, then the contract
        // has to unstake.
        if !stake_action_succeeded && env::account_locked_balance() > 0 {
            Promise::new(env::current_account_id()).stake(0, self.stake_public_key.clone());
        }
    }

internal.rs baris 8~22

    /// Restakes the current `total_staked_balance` again.
    pub(crate) fn internal_restake(&mut self) {
        if self.paused {
            return;
        }
        // Stakes with the staking public key. If the public key is invalid the entire function
        // call will be rolled back.
        Promise::new(env::current_account_id())
            .stake(self.total_staked_balance, self.stake_public_key.clone())
            .then(ext_self::on_stake_action(
                &env::current_account_id(),
                NO_DEPOSIT,
                ON_STAKE_ACTION_GAS,
            ));
    }
0
j00yn 11 Mei 2021, 08:06

1 menjawab

Jawaban Terbaik

Alasan antarmuka "eksternal" untuk kontrak adalah karena panggilan ke metode bersifat eksternal karena "dipanggil" sebagai bagian dari tindakan janji.

/// Interface for the contract itself.
#[ext_contract(ext_self)]
pub trait SelfContract {
    /// A callback to check the result of the staking action.
    fn on_stake_action(&mut self);
}

Pertama di rust prosedural makro aliran token (pub, trait, SelfContract, ...) di input dan output. Dalam hal ini outputnya bukan sifat melainkan modul](https:/ /doc.rust-lang.org/reference/items/modules.html) bernama ext_self. Kemudian fungsi on_stake_action ditambahkan ke modul dan dimodifikasi dengan argumen diri dihapus dan tiga argumen baru ditambahkan dan mengembalikan Promise.

        Promise::new(env::current_account_id())
            .stake(self.total_staked_balance, self.stake_public_key.clone())
            .then(ext_self::on_stake_action(
                &env::current_account_id(),
                NO_DEPOSIT,
                ON_STAKE_ACTION_GAS,
            ));

Catatan ext_self adalah modul :: adalah pemisah jalur untuk mengakses on_stake_action dan &env::current_account_id() adalah penerima, NO_DEPOSIT adalah setoran terlampir, dan ON_STAKE_ACTION_GAS adalah gas untuk panggilan janji. Selanjutnya kode untuk implementasi fungsi dihasilkan; itu mengkodekan argumen ke fungsi (dalam hal ini tidak ada) dan membuat janji yang memanggil metode on_stake_action.

Alasan deklarasi awal untuk ini adalah suatu sifat adalah karena tidak memerlukan implementasi dan IDE dengan dukungan karat yang baik sudah akan memperluas makro ini memungkinkan Anda untuk menggunakan ext_self sebagai modul meskipun Anda tidak dapat melihatnya itu adalah apa itu.

Anda mengemukakan poin yang bagus meskipun makro ext_contract memperlakukan panggilan ke kontrak yang sama sama seperti yang lain. Jadi mungkin fitur baru yang berguna adalah membuat makro baru yang sudah menggunakan env::current_account_id().

1
sirwillem 11 Mei 2021, 14:47