-
Notifications
You must be signed in to change notification settings - Fork 12
/
upgradable.rs
60 lines (50 loc) · 2.1 KB
/
upgradable.rs
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
use crate::utils::cratename;
use darling::FromDeriveInput;
use proc_macro::{self, TokenStream};
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[derive(FromDeriveInput, Default)]
#[darling(default, attributes(upgradable), forward_attrs(allow, doc, cfg))]
struct Opts {
code_storage_key: Option<String>,
}
/// Generates the token stream for the `Upgradable` macro.
pub fn derive_upgradable(input: TokenStream) -> TokenStream {
let cratename = cratename();
let input = parse_macro_input!(input);
let opts = Opts::from_derive_input(&input).expect("Wrong options");
let DeriveInput { ident, .. } = input;
let code_storage_key = opts
.code_storage_key
.unwrap_or_else(|| "__CODE__".to_string());
let output = quote! {
#[near_bindgen]
impl Upgradable for #ident {
fn up_storage_key(&self) -> Vec<u8>{
(#code_storage_key).as_bytes().to_vec()
}
#[#cratename::only(owner)]
fn up_stage_code(&mut self, #[serializer(borsh)] code: Vec<u8>) {
if code.is_empty() {
near_sdk::env::storage_remove(self.up_storage_key().as_ref());
} else {
near_sdk::env::storage_write(self.up_storage_key().as_ref(), code.as_ref());
}
}
#[result_serializer(borsh)]
fn up_staged_code(&self) -> Option<Vec<u8>> {
near_sdk::env::storage_read(self.up_storage_key().as_ref())
}
fn up_staged_code_hash(&self) -> Option<::near_sdk::CryptoHash> {
self.up_staged_code()
.map(|code| std::convert::TryInto::try_into(near_sdk::env::sha256(code.as_ref())).unwrap())
}
#[#cratename::only(owner)]
fn up_deploy_code(&mut self) -> near_sdk::Promise {
near_sdk::Promise::new(near_sdk::env::current_account_id())
.deploy_contract(self.up_staged_code().unwrap_or_else(|| ::near_sdk::env::panic_str("Upgradable: No staged code")))
}
}
};
output.into()
}