fuels_types/
offsets.rs

1use fuel_asm::Instruction;
2use fuel_tx::{
3    field::{Salt, Script},
4    Bytes32, ConsensusParameters, InputRepr,
5};
6use fuel_types::{bytes::padded_len_usize, ContractId};
7
8/// Gets the base offset for a script or a predicate. The offset depends on the `max_inputs`
9/// field of the `ConsensusParameters` and the static offset.
10pub fn base_offset_script(consensus_parameters: &ConsensusParameters) -> usize {
11    consensus_parameters.tx_offset() + fuel_tx::Script::script_offset_static()
12}
13
14/// Gets the base offset for a script or a predicate. The offset depends on the `max_inputs`
15/// field of the `ConsensusParameters` and the static offset.
16pub fn base_offset_create(consensus_parameters: &ConsensusParameters) -> usize {
17    // The easiest way to get the offset of `fuel_tx::Create` is to get the offset of the last field
18    // of `Create` -- i.e. `salt` and skip it by adding its length.
19    // This should be updated if `fuel_tx::Create` ever adds more fields after `salt`.
20    consensus_parameters.tx_offset() + fuel_tx::Create::salt_offset_static() + Bytes32::LEN
21}
22
23/// Calculates the length of the script based on the number of contract calls it
24/// has to make and returns the offset at which the script data begins
25pub fn call_script_data_offset(
26    consensus_parameters: &ConsensusParameters,
27    calls_instructions_len: usize,
28) -> usize {
29    // Instruction::SIZE is a placeholder for the RET instruction which is added later for returning
30    // from the script. This doesn't happen in the predicate.
31    let opcode_len = Instruction::SIZE;
32
33    base_offset_script(consensus_parameters) + padded_len_usize(calls_instructions_len + opcode_len)
34}
35
36pub fn coin_predicate_data_offset(code_len: usize) -> usize {
37    InputRepr::Coin
38        .coin_predicate_offset()
39        .expect("should have predicate offset")
40        + padded_len_usize(code_len)
41}
42
43pub fn message_predicate_data_offset(message_data_len: usize, code_len: usize) -> usize {
44    InputRepr::Message
45        .data_offset()
46        .expect("should have data offset")
47        + padded_len_usize(message_data_len)
48        + padded_len_usize(code_len)
49}
50
51pub fn coin_signed_data_offset() -> usize {
52    InputRepr::Coin
53        .coin_predicate_offset()
54        .expect("should have coin offset")
55}
56
57pub fn message_signed_data_offset(message_data_len: usize) -> usize {
58    InputRepr::Message
59        .data_offset()
60        .expect("should have data offset")
61        + padded_len_usize(message_data_len)
62}
63
64pub fn contract_input_offset() -> usize {
65    // The easiest way to get the contract input offset is to get the offset of the last field of
66    // `InputRepr::Contract` -- i.e. the `contract_id` and then add its len to skip the last field.
67    // Care should be taken to update this should `InputRepr::Contract` ever get another field after
68    // this last one.
69    InputRepr::Contract.contract_id_offset().unwrap() + ContractId::LEN
70}