fn emit_contract_call(
bytecode: &mut Vec<u8>,
use_callt: bool,
token_patches: &mut Vec<MethodTokenPatch>,
) {
emit_native_contract_call(
bytecode,
ir::NativeContract::StdLib,
"deserialize",
1,
use_callt,
token_patches,
);
push_integer_bigint(bytecode, &BigInt::from(CALLFLAGS_ALL));
bytecode.push(0x50); bytecode.push(0x54); emit_syscall(bytecode, "System.Contract.Call");
emit_serialize_single_return(bytecode, use_callt, token_patches);
}
fn emit_contract_call_with_flags(
bytecode: &mut Vec<u8>,
use_callt: bool,
token_patches: &mut Vec<MethodTokenPatch>,
) {
bytecode.push(0x50); emit_native_contract_call(
bytecode,
ir::NativeContract::StdLib,
"deserialize",
1,
use_callt,
token_patches,
);
bytecode.push(0x54); emit_syscall(bytecode, "System.Contract.Call");
emit_serialize_single_return(bytecode, use_callt, token_patches);
}
fn emit_serialize_single_return(
bytecode: &mut Vec<u8>,
use_callt: bool,
token_patches: &mut Vec<MethodTokenPatch>,
) {
bytecode.push(0x4A); bytecode.push(0xD8); let jmp_if_not_null_pos = bytecode.len();
bytecode.push(0x27); let jmp_if_not_null_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
bytecode.push(0x45); push_data(bytecode, &[]);
let jmp_end_pos = bytecode.len();
bytecode.push(0x23); let jmp_end_operand = bytecode.len();
bytecode.extend_from_slice(&[0, 0, 0, 0]);
let not_null_pos = bytecode.len();
bytecode.push(0x11); bytecode.push(0xC0); emit_native_contract_call(
bytecode,
ir::NativeContract::StdLib,
"serialize",
1,
use_callt,
token_patches,
);
let end_pos = bytecode.len();
let rel_not_null = (not_null_pos as i32)
.checked_sub(jmp_if_not_null_pos as i32)
.unwrap_or(0);
bytecode[jmp_if_not_null_operand..jmp_if_not_null_operand + 4]
.copy_from_slice(&rel_not_null.to_le_bytes());
let rel_end = (end_pos as i32)
.checked_sub(jmp_end_pos as i32)
.unwrap_or(0);
bytecode[jmp_end_operand..jmp_end_operand + 4].copy_from_slice(&rel_end.to_le_bytes());
}