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
82
83
84
use super::*;
impl ExecutionContext {
pub(crate) fn invoke_native_neo(&mut self, method: &str, params: StackItem) -> StackItem {
match method {
"symbol" => StackItem::byte_array(b"NEO".to_vec()),
"decimals" => StackItem::UnsignedInteger(0),
"totalsupply" => StackItem::UnsignedInteger(self.neo_total_supply),
"getgasperblock" => StackItem::UnsignedInteger(5),
"getcommittee" => {
// Return deterministic committee ECPoint public keys (ByteString).
let member1 = (0u8..33u8).collect::<Vec<_>>();
let member2 = (33u8..66u8).collect::<Vec<_>>();
StackItem::array(vec![
StackItem::byte_array(member1),
StackItem::byte_array(member2),
])
}
"getnextblockvalidators" => {
// Return deterministic validator ECPoint public keys (ByteString).
let validator = (100u8..133u8).collect::<Vec<_>>();
StackItem::array(vec![StackItem::byte_array(validator)])
}
"getcandidates" => {
// Neo N3: getCandidates() -> Array<Struct(ECPoint publicKey, BigInteger votes)>
//
// Represent structs as arrays in the runtime, matching the compiler's
// array-backed struct lowering.
let cand1_key = (10u8..43u8).collect::<Vec<_>>();
let cand2_key = (43u8..76u8).collect::<Vec<_>>();
StackItem::array(vec![
StackItem::array(vec![
StackItem::byte_array(cand1_key),
StackItem::UnsignedInteger(1_000),
]),
StackItem::array(vec![
StackItem::byte_array(cand2_key),
StackItem::UnsignedInteger(2_000),
]),
])
}
"getaccountstate" => {
// Neo N3: getAccountState(account) -> NeoAccountState? (nullable)
// Shape: [balance, balanceHeight, voteTo (ECPoint bytes or null), lastGasPerVote]
if let StackItem::Array(args) = params {
if let Some(StackItem::ByteArray(acc)) = args.borrow().first() {
if let Some(balance) =
self.neo_balances.get(acc.borrow().as_slice()).copied()
{
let height = self.block_height.unwrap_or(self.default_block_height);
return StackItem::array(vec![
StackItem::UnsignedInteger(balance),
StackItem::UnsignedInteger(height),
// Return `null` for voteTo by default so the compiler's
// helper can normalize it to empty bytes.
StackItem::Null,
StackItem::UnsignedInteger(0),
]);
}
}
}
StackItem::Null
}
"vote" | "registercandidate" | "unregistercandidate" | "setgasperblock" => {
// Keep these as deterministic placeholders for now.
StackItem::Boolean(true)
}
"balanceof" => {
if let StackItem::Array(args) = params {
if let Some(StackItem::ByteArray(acc)) = args.borrow().first() {
let bal = *self.neo_balances.get(acc.borrow().as_slice()).unwrap_or(&0);
StackItem::UnsignedInteger(bal)
} else {
StackItem::UnsignedInteger(0)
}
} else {
StackItem::UnsignedInteger(0)
}
}
"transfer" => self.handle_native_transfer(true, params),
_ => StackItem::Null,
}
}
}