质押池核心合约 - ext_contract 宏和回调
Staking-pool core contract - ext_contract macro and callbacks
在internal_restake
函数中,为什么我们必须访问on_stake_action
函数,就好像它是一个外部交叉合约调用,而它的函数是调用的一部分合同?我们不能只做 .then(self.on_stake_action())
吗?我假设它与面部有关,它是 stake()
promise 调用的回调。
在什么情况下你会像ext_self
一样为合约本身制作一个接口?
简而言之,#[ext_contract()] 宏的作用是什么?
-------- 下面的质押池合约代码--------------------
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);
}
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());
}
}
/// 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,
));
}
合同的“外部”接口的原因是对方法的调用是外部的,因为它是作为承诺操作的一部分“调用”的。
/// 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);
}
首先,在 Rust 过程宏中,输入和输出中的标记流(pub
、trait
、SelfContract
、...)。在这种情况下,输出不是一个特征,而是一个名为 ext_self
的模块](https://doc.rust-lang.org/reference/items/modules.html)。然后将函数 on_stake_action
添加到模块并进行修改,删除 self 参数并添加三个新参数和 returns a 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,
));
注意ext_self
是模块::
是访问的路径分隔符on_stake_action
和&env::current_account_id()
是接收者,NO_DEPOSIT
是附加存款, ON_STAKE_ACTION_GAS
是 promise 调用的 gas。此外,还生成了实现该功能的代码;它对函数的参数进行编码(在这种情况下没有任何参数)并创建一个调用方法 on_stake_action
.
的承诺
这个初始声明是一个特征的原因是它不需要实现,IDE 具有良好的 Rust 支持已经扩展了这个宏,允许你使用 ext_self
作为一个模块,即使你看不到它是什么。
尽管 ext_contract
宏将对同一合同的调用与其他合同的调用视为相同,但您提出了一个很好的观点。因此,也许一个新的有用功能是创建一个已经使用 env::current_account_id()
.
的新宏
在
internal_restake
函数中,为什么我们必须访问on_stake_action
函数,就好像它是一个外部交叉合约调用,而它的函数是调用的一部分合同?我们不能只做.then(self.on_stake_action())
吗?我假设它与面部有关,它是stake()
promise 调用的回调。在什么情况下你会像
ext_self
一样为合约本身制作一个接口?简而言之,#[ext_contract()] 宏的作用是什么?
-------- 下面的质押池合约代码-------------------- 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);
}
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());
}
}
/// 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,
));
}
合同的“外部”接口的原因是对方法的调用是外部的,因为它是作为承诺操作的一部分“调用”的。
/// 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);
}
首先,在 Rust 过程宏中,输入和输出中的标记流(pub
、trait
、SelfContract
、...)。在这种情况下,输出不是一个特征,而是一个名为 ext_self
的模块](https://doc.rust-lang.org/reference/items/modules.html)。然后将函数 on_stake_action
添加到模块并进行修改,删除 self 参数并添加三个新参数和 returns a 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,
));
注意ext_self
是模块::
是访问的路径分隔符on_stake_action
和&env::current_account_id()
是接收者,NO_DEPOSIT
是附加存款, ON_STAKE_ACTION_GAS
是 promise 调用的 gas。此外,还生成了实现该功能的代码;它对函数的参数进行编码(在这种情况下没有任何参数)并创建一个调用方法 on_stake_action
.
这个初始声明是一个特征的原因是它不需要实现,IDE 具有良好的 Rust 支持已经扩展了这个宏,允许你使用 ext_self
作为一个模块,即使你看不到它是什么。
尽管 ext_contract
宏将对同一合同的调用与其他合同的调用视为相同,但您提出了一个很好的观点。因此,也许一个新的有用功能是创建一个已经使用 env::current_account_id()
.