#[derive(Debug)]
pub struct Module {
pub functions: Vec<Function>,
pub state_variables: Vec<StateVariable>,
pub events: Vec<Event>,
}
impl Module {
pub fn constructor(&self) -> Option<&Function> {
self.functions.iter().find(|f| f.kind == FunctionKind::Constructor)
}
pub fn get_function(&self, name: &str) -> Option<&Function> {
self.functions.iter().find(|f| f.name == name)
}
pub fn instruction_count(&self) -> usize {
self.functions.iter()
.flat_map(|f| &f.basic_blocks)
.map(|bb| bb.instructions.len())
.sum()
}
}
#[derive(Debug)]
pub struct Function {
pub name: String,
pub kind: FunctionKind,
pub parameters: Vec<ValueType>,
pub returns: Vec<ValueType>,
pub basic_blocks: Vec<BasicBlock>,
pub local_count: u16,
}
impl Function {
pub fn is_constructor(&self) -> bool {
self.kind == FunctionKind::Constructor
}
pub fn instruction_count(&self) -> usize {
self.basic_blocks.iter().map(|bb| bb.instructions.len()).sum()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FunctionKind {
Constructor,
Regular,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StateVariable {
pub name: Option<String>,
pub ty: ValueType,
pub is_constant: bool,
pub is_immutable: bool,
pub storage_key: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Event {
pub name: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EventParamInfo {
pub canonical_type: String,
pub indexed: bool,
pub is_dynamic: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EventSignature {
pub canonical: String,
pub topic0: [u8; 32],
pub params: Vec<EventParamInfo>,
pub is_anonymous: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ErrorAbiSignature {
pub param_names: Vec<Option<String>>,
pub param_types: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BasicBlock {
pub instructions: Vec<Instruction>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RuntimeValue {
MsgSender,
MsgValue,
MsgData,
TxOrigin,
BlockTimestamp,
BlockNumber,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instruction {
Drop(ValueType),
Dup,
Swap,
LoadParameter(usize),
StoreParameter(usize),
PushLiteral(LiteralValue),
Return,
ReturnVoid,
ReturnDefault(ValueType),
BinaryOp(BinaryOperator),
LoadState(usize),
StoreState(usize),
LoadStorageDynamic,
LoadLocal(usize),
StoreLocal(usize),
LoadMappingElement {
state_index: usize,
key_types: Vec<ValueType>,
},
StoreMappingElement {
state_index: usize,
key_types: Vec<ValueType>,
},
StoreArrayDeepCopy {
state_index: usize,
key_types: Vec<ValueType>,
},
LoadStructField {
state_index: usize,
key_types: Vec<ValueType>,
field_keys: Vec<[u8; 32]>,
field_type: ValueType,
},
StoreStructField {
state_index: usize,
key_types: Vec<ValueType>,
field_keys: Vec<[u8; 32]>,
field_type: ValueType,
},
LoadStructArrayElement {
state_index: usize,
key_types: Vec<ValueType>,
field_keys: Vec<[u8; 32]>,
element_type: ValueType,
},
StoreStructArrayElement {
state_index: usize,
key_types: Vec<ValueType>,
field_keys: Vec<[u8; 32]>,
element_type: ValueType,
},
LoadStructFieldMappingElement {
state_index: usize,
key_types: Vec<ValueType>,
field_keys: Vec<[u8; 32]>,
trailing_key_types: Vec<ValueType>,
value_type: ValueType,
},
StoreStructFieldMappingElement {
state_index: usize,
key_types: Vec<ValueType>,
field_keys: Vec<[u8; 32]>,
trailing_key_types: Vec<ValueType>,
},
LoadRuntimeValue(RuntimeValue),
GetSize,
CallFunction {
name: String,
arg_count: usize,
},
PushFunctionOffset {
name: String,
},
CallIndirect {
arg_count: usize,
has_return: bool,
},
CallBuiltin {
builtin: BuiltinCall,
arg_count: usize,
},
EmitEvent {
event_index: usize,
arg_count: usize,
},
EmitEventByName {
name: String,
arg_count: usize,
},
Convert {
target: ConvertTarget,
},
IsType {
target: ConvertTarget,
},
NewBuffer,
NewArray {
element_type: ValueType,
},
NewMap,
ArrayGet,
ArraySet,
HasKey,
MemCpy,
Substr,
ReverseItems,
BitwiseNot,
LogicalNot,
Try {
catch_target: usize,
},
EndTry {
target: usize,
},
Jump {
target: usize,
},
JumpIf {
target: usize,
},
Label(usize),
Throw,
AbortMsg,
Abort,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LiteralValue {
Integer(BigInt),
Boolean(bool),
String(Vec<u8>),
ByteArray(Vec<u8>),
Address(Vec<u8>),
Null,
}
impl LiteralValue {
pub fn int(value: impl Into<BigInt>) -> Self {
Self::Integer(value.into())
}
pub fn bool(value: bool) -> Self {
Self::Boolean(value)
}
pub fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
pub fn type_name(&self) -> &'static str {
match self {
Self::Integer(_) => "integer",
Self::Boolean(_) => "boolean",
Self::String(_) => "string",
Self::ByteArray(_) => "bytes",
Self::Address(_) => "address",
Self::Null => "null",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConvertTarget {
Any,
Boolean,
Integer,
ByteArray,
Array,
Map,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValueType {
Integer {
signed: bool,
bits: u16,
},
Boolean,
String,
Address,
ByteArray {
fixed_len: Option<u16>,
},
Array(Box<ValueType>),
Mapping {
key: Box<ValueType>,
value: Box<ValueType>,
},
Struct {
name: String,
fields: Vec<StructField>,
},
Any,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ManifestType {
Integer,
Boolean,
String,
Hash160,
Hash256,
ByteArray,
Array,
Map,
Any,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructField {
pub name: String,
pub ty: ValueType,
pub key: [u8; 32],
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOperator {
Add,
Sub,
Mul,
Div,
Mod,
BitAnd,
BitOr,
BitXor,
Shl,
Shr,
Lt,
Le,
Gt,
Ge,
Eq,
Ne,
}
impl BinaryOperator {
pub fn is_arithmetic(&self) -> bool {
matches!(self, Self::Add | Self::Sub | Self::Mul | Self::Div | Self::Mod)
}
pub fn is_comparison(&self) -> bool {
matches!(self, Self::Lt | Self::Le | Self::Gt | Self::Ge | Self::Eq | Self::Ne)
}
pub fn is_bitwise(&self) -> bool {
matches!(self, Self::BitAnd | Self::BitOr | Self::BitXor | Self::Shl | Self::Shr)
}
pub fn symbol(&self) -> &'static str {
match self {
Self::Add => "+",
Self::Sub => "-",
Self::Mul => "*",
Self::Div => "/",
Self::Mod => "%",
Self::BitAnd => "&",
Self::BitOr => "|",
Self::BitXor => "^",
Self::Shl => "<<",
Self::Shr => ">>",
Self::Lt => "<",
Self::Le => "<=",
Self::Gt => ">",
Self::Ge => ">=",
Self::Eq => "==",
Self::Ne => "!=",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NativeContract {
Neo,
Gas,
ContractManagement,
Policy,
Oracle,
RoleManagement,
Notary,
Treasury,
Ledger,
CryptoLib,
StdLib,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BuiltinCall {
RuntimeNotify,
RuntimeCheckWitness,
AbiEncode,
AbiEncodePacked,
AbiEncodeCall,
AbiEncodeWithSignature,
AbiDecode,
Keccak256,
Ecrecover,
StorageFind,
StoragePut,
StorageGet,
StorageDelete,
ContractCall,
ContractCallWithFlags,
NotifySerialized,
VerifySignature,
DeployContract,
GetContract,
GetContractScript,
GetNeoAccountState,
NativeCall {
contract: NativeContract,
method: String,
},
Syscall(String),
TypeOf,
BytesConcat,
PrecompileEcrecover,
PrecompileModexp,
}