名称: mvx_flash_loan_patterns 描述: 原子借出-执行-验证模式 — 重入防护、分片验证、端点检查。
MultiversX 原子借出-执行-验证模式
借出资产,执行回调,验证还款 — 全部在一个事务中原子性地完成。
何时使用
- 闪电贷、原子交换、临时授权
- 不适用于跨分片操作(会破坏原子性)
安全检查清单
- 重入防护 — 防止嵌套操作
- 分片验证 — 目标必须在同一分片
- 端点验证 — 回调不能是内置函数
- 还款验证 — 检查回调后的合约余额
- 防护清理 — 始终清除标志
核心流程
#[endpoint(atomicOperation)]
fn atomic_operation(&self, asset: TokenIdentifier, amount: BigUint, target: ManagedAddress, callback: ManagedBuffer) {
self.require_not_ongoing();
self.require_same_shard(&target);
require!(!callback.is_empty() && !self.blockchain().is_builtin_function(&callback), "Invalid endpoint");
let fee = &amount * self.fee_bps().get() / 10_000u64;
let balance_before = self.blockchain().get_sc_balance(&asset.clone().into(), 0);
self.operation_ongoing().set(true);
self.tx().to(&target).raw_call(callback).single_esdt(&asset, 0, &amount).sync_call();
let balance_after = self.blockchain().get_sc_balance(&asset.into(), 0);
require!(balance_after >= balance_before + &fee, "Repayment insufficient");
self.operation_ongoing().set(false);
}
重入防护
#[storage_mapper("operationOngoing")]
fn operation_ongoing(&self) -> SingleValueMapper<bool>;
fn require_not_ongoing(&self) {
require!(!self.operation_ongoing().get(), "Operation already in progress");
}
分片验证
fn require_same_shard(&self, target: &ManagedAddress) {
let target_shard = self.blockchain().get_shard_of_address(target);
let self_shard = self.blockchain().get_shard_of_address(&self.blockchain().get_sc_address());
require!(target_shard == self_shard, "Must be same shard");
}
为什么: 跨分片调用在不同的区块中执行,会破坏原子性。
反模式
- 检查存储值而不是实际的
get_sc_balance来验证还款 - 没有分片验证(跨分片同步调用会无声地变为异步)
- 内置函数回调绕过还款逻辑