1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#![no_std]
#![allow(clippy::string_lit_as_bytes)]
#[macro_use]
extern crate elrond_wasm;
imports!();
pub const FEATURE_NOT_SET: u8 = 0;
pub const FEATURE_ON: u8 = 1;
pub const FEATURE_OFF: u8 = 2;
#[elrond_wasm_derive::module(FeaturesModuleImpl)]
pub trait FeaturesModule {
#[storage_get("feat:")]
fn get_feature_flag(&self, feature_name: FeatureName) -> u8;
#[storage_set("feat:")]
fn set_feature_flag(&self, feature_name: FeatureName, value: u8);
fn check_feature_on(&self, feature_name: &'static [u8], default: bool) -> SCResult<()> {
let flag = self.get_feature_flag(FeatureName(feature_name));
let value = match flag {
FEATURE_NOT_SET => default,
FEATURE_ON => true,
_ => false,
};
if value {
Ok(())
} else {
let mut msg = feature_name.to_vec();
msg.extend_from_slice(&b" currently disabled"[..]);
SCResult::Err(msg.into())
}
}
#[endpoint(setFeatureFlag)]
fn set_feature_flag_endpoint(&self, feature_name: Vec<u8>, value: bool) -> SCResult<()> {
require!(
self.get_caller() == self.get_owner_address(),
"only owner allowed to change features"
);
self.set_feature_flag(
FeatureName(feature_name.as_slice()),
if value { FEATURE_ON } else { FEATURE_OFF },
);
Ok(())
}
}
pub struct FeatureName<'a>(&'a [u8]);
use elrond_wasm::elrond_codec::*;
impl<'a> NestedEncode for FeatureName<'a> {
#[inline]
fn dep_encode<O: NestedEncodeOutput>(&self, dest: &mut O) -> Result<(), EncodeError> {
dest.write(&self.0[..]);
Result::Ok(())
}
#[inline]
fn dep_encode_or_exit<O: NestedEncodeOutput, ExitCtx: Clone>(
&self,
dest: &mut O,
_: ExitCtx,
_: fn(ExitCtx, EncodeError) -> !,
) {
dest.write(&self.0[..]);
}
}
#[macro_export]
macro_rules! feature_guard {
($feature_module: expr, $feature_name:expr, $default:expr) => {
sc_try!($feature_module.check_feature_on(&$feature_name[..], $default));
};
}