neo_solidity/ir/expressions/calls/builtins/
member_storage.rs

1fn try_lower_storage_member_builtin(
2    base: &Identifier,
3    member: &Identifier,
4    args: &[Expression],
5    ctx: &mut LoweringContext,
6    instructions: &mut Vec<Instruction>,
7) -> Option<bool> {
8    if base.name != "Storage" {
9        return None;
10    }
11
12    match member.name.as_str() {
13        "getUsage" => {
14            if !args.is_empty() {
15                ctx.record_error(format!(
16                    "Storage.getUsage requires 0 argument(s), got {}",
17                    args.len()
18                ));
19                return Some(false);
20            }
21
22            // The compiler does not track byte-level storage usage on Neo N3.
23            // Return a stable default to keep diagnostics-style helpers working.
24            instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
25                BigInt::zero(),
26            )));
27            Some(true)
28        }
29        "putContractMetadata" => {
30            if args.len() != 4 {
31                ctx.record_error(format!(
32                    "Storage.putContractMetadata requires 4 argument(s), got {}",
33                    args.len()
34                ));
35                return Some(false);
36            }
37
38            // putContractMetadata(name, version, author, extra) expands to:
39            // Storage.put("__CONTRACT_METADATA__", abi.encode(name, version, author, extra, block.timestamp))
40            //
41            // We emit the key first so the encoded metadata lands above it on the stack.
42            instructions.push(Instruction::PushLiteral(LiteralValue::String(
43                b"__CONTRACT_METADATA__".to_vec(),
44            )));
45
46            let mut success = true;
47            for arg in args {
48                if !lower_expression(arg, ctx, instructions) {
49                    success = false;
50                }
51            }
52
53            if !success {
54                return Some(false);
55            }
56
57            instructions.push(Instruction::LoadRuntimeValue(RuntimeValue::BlockTimestamp));
58            instructions.push(Instruction::CallBuiltin {
59                builtin: BuiltinCall::AbiEncode,
60                arg_count: 5,
61            });
62            instructions.push(Instruction::CallBuiltin {
63                builtin: BuiltinCall::StoragePut,
64                arg_count: 2,
65            });
66            Some(true)
67        }
68        _ => None,
69    }
70}