对象与燃气¶
介绍¶
在单笔交易中,可以创建的对象数量上限为2048,如果一笔交易尝试创建超过2048个对象,则该笔交易将被拒绝。
在单笔交易中,可以发出的事件数量上限为1024,如果一笔交易尝试发出超过1024个事件,则该笔交易将被拒绝。
每一笔交易都可以通过--gas-budget
来设置交易费预算,如果当前交易超过了该预算,则该笔交易将被拒绝。
--gas-budget
并非一个必须的参数,如果不手动设置,则会有一个默认的上限。
例题¶
接下来,考虑这么一个问题:
module obj_gas::obj_gas;
use std::string::String;
use sui::event;
use sui::random::Random;
public struct FailureMark has key {
id: UID
}
public struct Flag has copy, drop {
owner: address,
mark: String
}
entry fun get_flag(random: &Random, ctx: &mut TxContext) {
let mut generator = random.new_generator(ctx);
if (generator.generate_u8_in_range(1, 3) == generator.generate_u8_in_range(1, 3)) {
event::emit(Flag {
owner: ctx.sender(),
mark: b"success".to_string()
});
} else {
let failure_mark = FailureMark {
id: object::new(ctx)
};
let mark = 'mark: {
10u64.do!(|i| {
object::id(&failure_mark).to_bytes()
.map!(|byte| (generator.generate_u64() % ((byte as u64) + 1)) as u8)
.try_to_string().do!(|str| if (i > 5) return 'mark str);
});
b"fail".to_string()
};
event::emit(Flag {
owner: ctx.sender(),
mark
});
let FailureMark { id } = failure_mark;
id.delete();
}
}
重复调用,总有一次成功!!!但是,如果成功概率没这么高呢?或者合约限制了尝试次数呢?
可以发现,失败的逻辑明显比成功的逻辑复杂,消耗的计算资源更大,将导致交易的gas
费也相应提高,那么,就可以通过--gas-budget
将预算设置为成功与失败之间,使得每一笔上链的交易都是能够得到success
标记的。
另一个解决办法就是利用2048
这个限制,因为失败的逻辑中会额外创建一个对象,虽然该对象最终被销毁,但是只需要在创建时超过了阈值,这笔交易就会失败。也就是说,我们需要另写一个合约,创建很多很多个对象,再组合get_flag
为一个PTB
,以此来达到目的。
拓展¶
更多限制约束¶
相关限制和约束旨在防止滥用,并确保网络保持稳定高效,更多详情可以点击查看。
Random¶
sui::random
模块提供的生成安全随机性的功能,与Clock
一样,都是由官方提供的系统对象,地址为0x8
。
以下为Random
在源码中的定义:
/// Singleton shared object which stores the global randomness state.
/// The actual state is stored in a versioned inner field.
public struct Random has key {
id: UID,
// The inner object must never be accessed outside this module as it could be used for accessing global
// randomness via deserialization of RandomInner.
inner: Versioned,
}
Macro¶
宏函数是一种定义函数的方式,它不像普通函数那样被立即求值,而是用表达式进行替换。在本文中,10u64.do!
,vector<u8>.map!
等均为宏函数调用。
在move-book提供的Code Quality Checklist中明确表明,用宏来代替部分循环或者Option
的用法是更被推荐的。