(* Generated by coq-of-rust *)
Require Import CoqOfRust.CoqOfRust.

Module extension.
  Module reallocate.
    (*
    pub fn process_reallocate(
        program_id: &Pubkey,
        accounts: &[AccountInfo],
        new_extension_types: Vec<ExtensionType>,
    ) -> ProgramResult {
        let account_info_iter = &mut accounts.iter();
        let token_account_info = next_account_info(account_info_iter)?;
        let payer_info = next_account_info(account_info_iter)?;
        let system_program_info = next_account_info(account_info_iter)?;
        let authority_info = next_account_info(account_info_iter)?;
        let authority_info_data_len = authority_info.data_len();
    
        // check that account is the right type and validate owner
        let (mut current_extension_types, native_token_amount) = {
            let token_account = token_account_info.data.borrow();
            let account = StateWithExtensions::<Account>::unpack(&token_account)?;
            Processor::validate_owner(
                program_id,
                &account.base.owner,
                authority_info,
                authority_info_data_len,
                account_info_iter.as_slice(),
            )?;
            let native_token_amount = account.base.is_native().then_some(account.base.amount);
            (account.get_extension_types()?, native_token_amount)
        };
    
        // check that all desired extensions are for the right account type
        if new_extension_types
            .iter()
            .any(|extension_type| extension_type.get_account_type() != AccountType::Account)
        {
            return Err(TokenError::InvalidState.into());
        }
        // ExtensionType::try_calculate_account_len() dedupes types, so just a dumb
        // concatenation is fine here
        current_extension_types.extend_from_slice(&new_extension_types);
        let needed_account_len =
            ExtensionType::try_calculate_account_len::<Account>(&current_extension_types)?;
    
        // if account is already large enough, return early
        if token_account_info.data_len() >= needed_account_len {
            return Ok(());
        }
    
        // reallocate
        msg!(
            "account needs realloc, +{:?} bytes",
            needed_account_len - token_account_info.data_len()
        );
        token_account_info.realloc(needed_account_len, false)?;
    
        // if additional lamports needed to remain rent-exempt, transfer them
        let rent = Rent::get()?;
        let new_rent_exempt_reserve = rent.minimum_balance(needed_account_len);
    
        let current_lamport_reserve = token_account_info
            .lamports()
            .checked_sub(native_token_amount.unwrap_or(0))
            .ok_or(TokenError::Overflow)?;
        let lamports_diff = new_rent_exempt_reserve.saturating_sub(current_lamport_reserve);
        if lamports_diff > 0 {
            invoke(
                &system_instruction::transfer(payer_info.key, token_account_info.key, lamports_diff),
                &[
                    payer_info.clone(),
                    token_account_info.clone(),
                    system_program_info.clone(),
                ],
            )?;
        }
    
        // set account_type, if needed
        let mut token_account_data = token_account_info.data.borrow_mut();
        set_account_type::<Account>(&mut token_account_data)?;
    
        // sync the rent exempt reserve for native accounts
        if let Some(native_token_amount) = native_token_amount {
            let mut token_account = StateWithExtensionsMut::<Account>::unpack(&mut token_account_data)?;
            // sanity check that there are enough lamports to cover the token amount
            // and the rent exempt reserve
            let minimum_lamports = new_rent_exempt_reserve
                .checked_add(native_token_amount)
                .ok_or(TokenError::Overflow)?;
            if token_account_info.lamports() < minimum_lamports {
                return Err(TokenError::InvalidState.into());
            }
            token_account.base.is_native = COption::Some(new_rent_exempt_reserve);
            token_account.pack_base();
        }
    
        Ok(())
    }
    *)
    Definition process_reallocate (τ : list Ty.t) (α : list Value.t) : M :=
      match τ, α with
      | [], [ program_id; accounts; new_extension_types ] =>
        ltac:(M.monadic
          (let program_id := M.alloc (| program_id |) in
          let accounts := M.alloc (| accounts |) in
          let new_extension_types := M.alloc (| new_extension_types |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let account_info_iter :=
                  M.alloc (|
                    M.alloc (|
                      M.call_closure (|
                        M.get_associated_function (|
                          Ty.apply
                            (Ty.path "slice")
                            [ Ty.path "solana_program::account_info::AccountInfo" ],
                          "iter",
                          []
                        |),
                        [ M.read (| accounts |) ]
                      |)
                    |)
                  |) in
                let token_account_info :=
                  M.copy (|
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              [
                                Ty.apply
                                  (Ty.path "&")
                                  [ Ty.path "solana_program::account_info::AccountInfo" ];
                                Ty.path "solana_program::program_error::ProgramError"
                              ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_function (|
                                "solana_program::account_info::next_account_info",
                                [
                                  Ty.apply
                                    (Ty.path "core::slice::iter::Iter")
                                    [ Ty.path "solana_program::account_info::AccountInfo" ]
                                ]
                              |),
                              [ M.read (| account_info_iter |) ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Break",
                                0
                              |) in
                            let residual := M.copy (| γ0_0 |) in
                            M.alloc (|
                              M.never_to_any (|
                                M.read (|
                                  M.return_ (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::try_trait::FromResidual",
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          [
                                            Ty.tuple [];
                                            Ty.path "solana_program::program_error::ProgramError"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "solana_program::program_error::ProgramError"
                                            ]
                                        ],
                                        "from_residual",
                                        []
                                      |),
                                      [ M.read (| residual |) ]
                                    |)
                                  |)
                                |)
                              |)
                            |)));
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Continue",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |)
                  |) in
                let payer_info :=
                  M.copy (|
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              [
                                Ty.apply
                                  (Ty.path "&")
                                  [ Ty.path "solana_program::account_info::AccountInfo" ];
                                Ty.path "solana_program::program_error::ProgramError"
                              ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_function (|
                                "solana_program::account_info::next_account_info",
                                [
                                  Ty.apply
                                    (Ty.path "core::slice::iter::Iter")
                                    [ Ty.path "solana_program::account_info::AccountInfo" ]
                                ]
                              |),
                              [ M.read (| account_info_iter |) ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Break",
                                0
                              |) in
                            let residual := M.copy (| γ0_0 |) in
                            M.alloc (|
                              M.never_to_any (|
                                M.read (|
                                  M.return_ (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::try_trait::FromResidual",
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          [
                                            Ty.tuple [];
                                            Ty.path "solana_program::program_error::ProgramError"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "solana_program::program_error::ProgramError"
                                            ]
                                        ],
                                        "from_residual",
                                        []
                                      |),
                                      [ M.read (| residual |) ]
                                    |)
                                  |)
                                |)
                              |)
                            |)));
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Continue",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |)
                  |) in
                let system_program_info :=
                  M.copy (|
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              [
                                Ty.apply
                                  (Ty.path "&")
                                  [ Ty.path "solana_program::account_info::AccountInfo" ];
                                Ty.path "solana_program::program_error::ProgramError"
                              ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_function (|
                                "solana_program::account_info::next_account_info",
                                [
                                  Ty.apply
                                    (Ty.path "core::slice::iter::Iter")
                                    [ Ty.path "solana_program::account_info::AccountInfo" ]
                                ]
                              |),
                              [ M.read (| account_info_iter |) ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Break",
                                0
                              |) in
                            let residual := M.copy (| γ0_0 |) in
                            M.alloc (|
                              M.never_to_any (|
                                M.read (|
                                  M.return_ (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::try_trait::FromResidual",
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          [
                                            Ty.tuple [];
                                            Ty.path "solana_program::program_error::ProgramError"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "solana_program::program_error::ProgramError"
                                            ]
                                        ],
                                        "from_residual",
                                        []
                                      |),
                                      [ M.read (| residual |) ]
                                    |)
                                  |)
                                |)
                              |)
                            |)));
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Continue",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |)
                  |) in
                let authority_info :=
                  M.copy (|
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              [
                                Ty.apply
                                  (Ty.path "&")
                                  [ Ty.path "solana_program::account_info::AccountInfo" ];
                                Ty.path "solana_program::program_error::ProgramError"
                              ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_function (|
                                "solana_program::account_info::next_account_info",
                                [
                                  Ty.apply
                                    (Ty.path "core::slice::iter::Iter")
                                    [ Ty.path "solana_program::account_info::AccountInfo" ]
                                ]
                              |),
                              [ M.read (| account_info_iter |) ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Break",
                                0
                              |) in
                            let residual := M.copy (| γ0_0 |) in
                            M.alloc (|
                              M.never_to_any (|
                                M.read (|
                                  M.return_ (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::try_trait::FromResidual",
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          [
                                            Ty.tuple [];
                                            Ty.path "solana_program::program_error::ProgramError"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "solana_program::program_error::ProgramError"
                                            ]
                                        ],
                                        "from_residual",
                                        []
                                      |),
                                      [ M.read (| residual |) ]
                                    |)
                                  |)
                                |)
                              |)
                            |)));
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Continue",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |)
                  |) in
                let authority_info_data_len :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "solana_program::account_info::AccountInfo",
                        "data_len",
                        []
                      |),
                      [ M.read (| authority_info |) ]
                    |)
                  |) in
                M.match_operator (|
                  let token_account :=
                    M.alloc (|
                      M.call_closure (|
                        M.get_associated_function (|
                          Ty.apply
                            (Ty.path "core::cell::RefCell")
                            [
                              Ty.apply
                                (Ty.path "&mut")
                                [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]
                            ],
                          "borrow",
                          []
                        |),
                        [
                          M.call_closure (|
                            M.get_trait_method (|
                              "core::ops::deref::Deref",
                              Ty.apply
                                (Ty.path "alloc::rc::Rc")
                                [
                                  Ty.apply
                                    (Ty.path "core::cell::RefCell")
                                    [
                                      Ty.apply
                                        (Ty.path "&mut")
                                        [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]
                                    ];
                                  Ty.path "alloc::alloc::Global"
                                ],
                              [],
                              "deref",
                              []
                            |),
                            [
                              M.SubPointer.get_struct_record_field (|
                                M.read (| token_account_info |),
                                "solana_program::account_info::AccountInfo",
                                "data"
                              |)
                            ]
                          |)
                        ]
                      |)
                    |) in
                  let account :=
                    M.copy (|
                      M.match_operator (|
                        M.alloc (|
                          M.call_closure (|
                            M.get_trait_method (|
                              "core::ops::try_trait::Try",
                              Ty.apply
                                (Ty.path "core::result::Result")
                                [
                                  Ty.apply
                                    (Ty.path "spl_token_2022::extension::StateWithExtensions")
                                    [ Ty.path "spl_token_2022::state::Account" ];
                                  Ty.path "solana_program::program_error::ProgramError"
                                ],
                              [],
                              "branch",
                              []
                            |),
                            [
                              M.call_closure (|
                                M.get_associated_function (|
                                  Ty.apply
                                    (Ty.path "spl_token_2022::extension::StateWithExtensions")
                                    [ Ty.path "spl_token_2022::state::Account" ],
                                  "unpack",
                                  []
                                |),
                                [
                                  M.read (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::deref::Deref",
                                        Ty.apply
                                          (Ty.path "core::cell::Ref")
                                          [
                                            Ty.apply
                                              (Ty.path "&mut")
                                              [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]
                                          ],
                                        [],
                                        "deref",
                                        []
                                      |),
                                      [ token_account ]
                                    |)
                                  |)
                                ]
                              |)
                            ]
                          |)
                        |),
                        [
                          fun γ =>
                            ltac:(M.monadic
                              (let γ0_0 :=
                                M.SubPointer.get_struct_tuple_field (|
                                  γ,
                                  "core::ops::control_flow::ControlFlow::Break",
                                  0
                                |) in
                              let residual := M.copy (| γ0_0 |) in
                              M.alloc (|
                                M.never_to_any (|
                                  M.read (|
                                    M.return_ (|
                                      M.call_closure (|
                                        M.get_trait_method (|
                                          "core::ops::try_trait::FromResidual",
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            [
                                              Ty.tuple [];
                                              Ty.path "solana_program::program_error::ProgramError"
                                            ],
                                          [
                                            Ty.apply
                                              (Ty.path "core::result::Result")
                                              [
                                                Ty.path "core::convert::Infallible";
                                                Ty.path
                                                  "solana_program::program_error::ProgramError"
                                              ]
                                          ],
                                          "from_residual",
                                          []
                                        |),
                                        [ M.read (| residual |) ]
                                      |)
                                    |)
                                  |)
                                |)
                              |)));
                          fun γ =>
                            ltac:(M.monadic
                              (let γ0_0 :=
                                M.SubPointer.get_struct_tuple_field (|
                                  γ,
                                  "core::ops::control_flow::ControlFlow::Continue",
                                  0
                                |) in
                              let val := M.copy (| γ0_0 |) in
                              val))
                        ]
                      |)
                    |) in
                  let _ :=
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              [ Ty.tuple []; Ty.path "solana_program::program_error::ProgramError"
                              ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "spl_token_2022::processor::Processor",
                                "validate_owner",
                                []
                              |),
                              [
                                M.read (| program_id |);
                                M.SubPointer.get_struct_record_field (|
                                  M.SubPointer.get_struct_record_field (|
                                    account,
                                    "spl_token_2022::extension::StateWithExtensions",
                                    "base"
                                  |),
                                  "spl_token_2022::state::Account",
                                  "owner"
                                |);
                                M.read (| authority_info |);
                                M.read (| authority_info_data_len |);
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "core::slice::iter::Iter")
                                      [ Ty.path "solana_program::account_info::AccountInfo" ],
                                    "as_slice",
                                    []
                                  |),
                                  [ M.read (| account_info_iter |) ]
                                |)
                              ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Break",
                                0
                              |) in
                            let residual := M.copy (| γ0_0 |) in
                            M.alloc (|
                              M.never_to_any (|
                                M.read (|
                                  M.return_ (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::try_trait::FromResidual",
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          [
                                            Ty.tuple [];
                                            Ty.path "solana_program::program_error::ProgramError"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "solana_program::program_error::ProgramError"
                                            ]
                                        ],
                                        "from_residual",
                                        []
                                      |),
                                      [ M.read (| residual |) ]
                                    |)
                                  |)
                                |)
                              |)
                            |)));
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Continue",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |) in
                  let native_token_amount :=
                    M.alloc (|
                      M.call_closure (|
                        M.get_associated_function (|
                          Ty.path "bool",
                          "then_some",
                          [ Ty.path "u64" ]
                        |),
                        [
                          M.call_closure (|
                            M.get_associated_function (|
                              Ty.path "spl_token_2022::state::Account",
                              "is_native",
                              []
                            |),
                            [
                              M.SubPointer.get_struct_record_field (|
                                account,
                                "spl_token_2022::extension::StateWithExtensions",
                                "base"
                              |)
                            ]
                          |);
                          M.read (|
                            M.SubPointer.get_struct_record_field (|
                              M.SubPointer.get_struct_record_field (|
                                account,
                                "spl_token_2022::extension::StateWithExtensions",
                                "base"
                              |),
                              "spl_token_2022::state::Account",
                              "amount"
                            |)
                          |)
                        ]
                      |)
                    |) in
                  M.alloc (|
                    Value.Tuple
                      [
                        M.read (|
                          M.match_operator (|
                            M.alloc (|
                              M.call_closure (|
                                M.get_trait_method (|
                                  "core::ops::try_trait::Try",
                                  Ty.apply
                                    (Ty.path "core::result::Result")
                                    [
                                      Ty.apply
                                        (Ty.path "alloc::vec::Vec")
                                        [
                                          Ty.path "spl_token_2022::extension::ExtensionType";
                                          Ty.path "alloc::alloc::Global"
                                        ];
                                      Ty.path "solana_program::program_error::ProgramError"
                                    ],
                                  [],
                                  "branch",
                                  []
                                |),
                                [
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "spl_token_2022::extension::BaseStateWithExtensions",
                                      Ty.apply
                                        (Ty.path "spl_token_2022::extension::StateWithExtensions")
                                        [ Ty.path "spl_token_2022::state::Account" ],
                                      [ Ty.path "spl_token_2022::state::Account" ],
                                      "get_extension_types",
                                      []
                                    |),
                                    [ account ]
                                  |)
                                ]
                              |)
                            |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::ops::control_flow::ControlFlow::Break",
                                      0
                                    |) in
                                  let residual := M.copy (| γ0_0 |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        M.return_ (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::try_trait::FromResidual",
                                              Ty.apply
                                                (Ty.path "core::result::Result")
                                                [
                                                  Ty.tuple [];
                                                  Ty.path
                                                    "solana_program::program_error::ProgramError"
                                                ],
                                              [
                                                Ty.apply
                                                  (Ty.path "core::result::Result")
                                                  [
                                                    Ty.path "core::convert::Infallible";
                                                    Ty.path
                                                      "solana_program::program_error::ProgramError"
                                                  ]
                                              ],
                                              "from_residual",
                                              []
                                            |),
                                            [ M.read (| residual |) ]
                                          |)
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::ops::control_flow::ControlFlow::Continue",
                                      0
                                    |) in
                                  let val := M.copy (| γ0_0 |) in
                                  val))
                            ]
                          |)
                        |);
                        M.read (| native_token_amount |)
                      ]
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 := M.SubPointer.get_tuple_field (| γ, 0 |) in
                        let γ0_1 := M.SubPointer.get_tuple_field (| γ, 1 |) in
                        let current_extension_types := M.copy (| γ0_0 |) in
                        let native_token_amount := M.copy (| γ0_1 |) in
                        let _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::iter::traits::iterator::Iterator",
                                            Ty.apply
                                              (Ty.path "core::slice::iter::Iter")
                                              [ Ty.path "spl_token_2022::extension::ExtensionType"
                                              ],
                                            [],
                                            "any",
                                            [
                                              Ty.function
                                                [
                                                  Ty.tuple
                                                    [
                                                      Ty.apply
                                                        (Ty.path "&")
                                                        [
                                                          Ty.path
                                                            "spl_token_2022::extension::ExtensionType"
                                                        ]
                                                    ]
                                                ]
                                                (Ty.path "bool")
                                            ]
                                          |),
                                          [
                                            M.alloc (|
                                              M.call_closure (|
                                                M.get_associated_function (|
                                                  Ty.apply
                                                    (Ty.path "slice")
                                                    [
                                                      Ty.path
                                                        "spl_token_2022::extension::ExtensionType"
                                                    ],
                                                  "iter",
                                                  []
                                                |),
                                                [
                                                  M.call_closure (|
                                                    M.get_trait_method (|
                                                      "core::ops::deref::Deref",
                                                      Ty.apply
                                                        (Ty.path "alloc::vec::Vec")
                                                        [
                                                          Ty.path
                                                            "spl_token_2022::extension::ExtensionType";
                                                          Ty.path "alloc::alloc::Global"
                                                        ],
                                                      [],
                                                      "deref",
                                                      []
                                                    |),
                                                    [ new_extension_types ]
                                                  |)
                                                ]
                                              |)
                                            |);
                                            M.closure
                                              (fun γ =>
                                                ltac:(M.monadic
                                                  match γ with
                                                  | [ α0 ] =>
                                                    M.match_operator (|
                                                      M.alloc (| α0 |),
                                                      [
                                                        fun γ =>
                                                          ltac:(M.monadic
                                                            (let extension_type := M.copy (| γ |) in
                                                            M.call_closure (|
                                                              M.get_trait_method (|
                                                                "core::cmp::PartialEq",
                                                                Ty.path
                                                                  "spl_token_2022::extension::AccountType",
                                                                [
                                                                  Ty.path
                                                                    "spl_token_2022::extension::AccountType"
                                                                ],
                                                                "ne",
                                                                []
                                                              |),
                                                              [
                                                                M.alloc (|
                                                                  M.call_closure (|
                                                                    M.get_associated_function (|
                                                                      Ty.path
                                                                        "spl_token_2022::extension::ExtensionType",
                                                                      "get_account_type",
                                                                      []
                                                                    |),
                                                                    [ M.read (| extension_type |) ]
                                                                  |)
                                                                |);
                                                                M.alloc (|
                                                                  Value.StructTuple
                                                                    "spl_token_2022::extension::AccountType::Account"
                                                                    []
                                                                |)
                                                              ]
                                                            |)))
                                                      ]
                                                    |)
                                                  | _ => M.impossible (||)
                                                  end))
                                          ]
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        M.return_ (|
                                          Value.StructTuple
                                            "core::result::Result::Err"
                                            [
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::convert::Into",
                                                  Ty.path "spl_token_2022::error::TokenError",
                                                  [
                                                    Ty.path
                                                      "solana_program::program_error::ProgramError"
                                                  ],
                                                  "into",
                                                  []
                                                |),
                                                [
                                                  Value.StructTuple
                                                    "spl_token_2022::error::TokenError::InvalidState"
                                                    []
                                                ]
                                              |)
                                            ]
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let _ :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "alloc::vec::Vec")
                                  [
                                    Ty.path "spl_token_2022::extension::ExtensionType";
                                    Ty.path "alloc::alloc::Global"
                                  ],
                                "extend_from_slice",
                                []
                              |),
                              [
                                current_extension_types;
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::ops::deref::Deref",
                                    Ty.apply
                                      (Ty.path "alloc::vec::Vec")
                                      [
                                        Ty.path "spl_token_2022::extension::ExtensionType";
                                        Ty.path "alloc::alloc::Global"
                                      ],
                                    [],
                                    "deref",
                                    []
                                  |),
                                  [ new_extension_types ]
                                |)
                              ]
                            |)
                          |) in
                        let needed_account_len :=
                          M.copy (|
                            M.match_operator (|
                              M.alloc (|
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::ops::try_trait::Try",
                                    Ty.apply
                                      (Ty.path "core::result::Result")
                                      [
                                        Ty.path "usize";
                                        Ty.path "solana_program::program_error::ProgramError"
                                      ],
                                    [],
                                    "branch",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.path "spl_token_2022::extension::ExtensionType",
                                        "try_calculate_account_len",
                                        [ Ty.path "spl_token_2022::state::Account" ]
                                      |),
                                      [
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::ops::deref::Deref",
                                            Ty.apply
                                              (Ty.path "alloc::vec::Vec")
                                              [
                                                Ty.path "spl_token_2022::extension::ExtensionType";
                                                Ty.path "alloc::alloc::Global"
                                              ],
                                            [],
                                            "deref",
                                            []
                                          |),
                                          [ current_extension_types ]
                                        |)
                                      ]
                                    |)
                                  ]
                                |)
                              |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::ops::control_flow::ControlFlow::Break",
                                        0
                                      |) in
                                    let residual := M.copy (| γ0_0 |) in
                                    M.alloc (|
                                      M.never_to_any (|
                                        M.read (|
                                          M.return_ (|
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "core::ops::try_trait::FromResidual",
                                                Ty.apply
                                                  (Ty.path "core::result::Result")
                                                  [
                                                    Ty.tuple [];
                                                    Ty.path
                                                      "solana_program::program_error::ProgramError"
                                                  ],
                                                [
                                                  Ty.apply
                                                    (Ty.path "core::result::Result")
                                                    [
                                                      Ty.path "core::convert::Infallible";
                                                      Ty.path
                                                        "solana_program::program_error::ProgramError"
                                                    ]
                                                ],
                                                "from_residual",
                                                []
                                              |),
                                              [ M.read (| residual |) ]
                                            |)
                                          |)
                                        |)
                                      |)
                                    |)));
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::ops::control_flow::ControlFlow::Continue",
                                        0
                                      |) in
                                    let val := M.copy (| γ0_0 |) in
                                    val))
                              ]
                            |)
                          |) in
                        let _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.Pure.ge
                                          (M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.path "solana_program::account_info::AccountInfo",
                                              "data_len",
                                              []
                                            |),
                                            [ M.read (| token_account_info |) ]
                                          |))
                                          (M.read (| needed_account_len |))
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        M.return_ (|
                                          Value.StructTuple
                                            "core::result::Result::Ok"
                                            [ Value.Tuple [] ]
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let _ :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (| "solana_program::log::sol_log", [] |),
                              [
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::ops::deref::Deref",
                                    Ty.path "alloc::string::String",
                                    [],
                                    "deref",
                                    []
                                  |),
                                  [
                                    let res :=
                                      M.alloc (|
                                        M.call_closure (|
                                          M.get_function (| "alloc::fmt::format", [] |),
                                          [
                                            M.call_closure (|
                                              M.get_associated_function (|
                                                Ty.path "core::fmt::Arguments",
                                                "new_v1",
                                                []
                                              |),
                                              [
                                                (* Unsize *)
                                                M.pointer_coercion
                                                  (M.alloc (|
                                                    Value.Array
                                                      [
                                                        M.read (|
                                                          Value.String "account needs realloc, +"
                                                        |);
                                                        M.read (| Value.String " bytes" |)
                                                      ]
                                                  |));
                                                (* Unsize *)
                                                M.pointer_coercion
                                                  (M.alloc (|
                                                    Value.Array
                                                      [
                                                        M.call_closure (|
                                                          M.get_associated_function (|
                                                            Ty.path "core::fmt::rt::Argument",
                                                            "new_debug",
                                                            [ Ty.path "usize" ]
                                                          |),
                                                          [
                                                            M.alloc (|
                                                              BinOp.Panic.sub (|
                                                                Integer.Usize,
                                                                M.read (| needed_account_len |),
                                                                M.call_closure (|
                                                                  M.get_associated_function (|
                                                                    Ty.path
                                                                      "solana_program::account_info::AccountInfo",
                                                                    "data_len",
                                                                    []
                                                                  |),
                                                                  [ M.read (| token_account_info |)
                                                                  ]
                                                                |)
                                                              |)
                                                            |)
                                                          ]
                                                        |)
                                                      ]
                                                  |))
                                              ]
                                            |)
                                          ]
                                        |)
                                      |) in
                                    res
                                  ]
                                |)
                              ]
                            |)
                          |) in
                        let _ :=
                          M.match_operator (|
                            M.alloc (|
                              M.call_closure (|
                                M.get_trait_method (|
                                  "core::ops::try_trait::Try",
                                  Ty.apply
                                    (Ty.path "core::result::Result")
                                    [
                                      Ty.tuple [];
                                      Ty.path "solana_program::program_error::ProgramError"
                                    ],
                                  [],
                                  "branch",
                                  []
                                |),
                                [
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "solana_program::account_info::AccountInfo",
                                      "realloc",
                                      []
                                    |),
                                    [
                                      M.read (| token_account_info |);
                                      M.read (| needed_account_len |);
                                      Value.Bool false
                                    ]
                                  |)
                                ]
                              |)
                            |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::ops::control_flow::ControlFlow::Break",
                                      0
                                    |) in
                                  let residual := M.copy (| γ0_0 |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        M.return_ (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::try_trait::FromResidual",
                                              Ty.apply
                                                (Ty.path "core::result::Result")
                                                [
                                                  Ty.tuple [];
                                                  Ty.path
                                                    "solana_program::program_error::ProgramError"
                                                ],
                                              [
                                                Ty.apply
                                                  (Ty.path "core::result::Result")
                                                  [
                                                    Ty.path "core::convert::Infallible";
                                                    Ty.path
                                                      "solana_program::program_error::ProgramError"
                                                  ]
                                              ],
                                              "from_residual",
                                              []
                                            |),
                                            [ M.read (| residual |) ]
                                          |)
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::ops::control_flow::ControlFlow::Continue",
                                      0
                                    |) in
                                  let val := M.copy (| γ0_0 |) in
                                  val))
                            ]
                          |) in
                        let rent :=
                          M.copy (|
                            M.match_operator (|
                              M.alloc (|
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::ops::try_trait::Try",
                                    Ty.apply
                                      (Ty.path "core::result::Result")
                                      [
                                        Ty.path "solana_program::rent::Rent";
                                        Ty.path "solana_program::program_error::ProgramError"
                                      ],
                                    [],
                                    "branch",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "solana_program::sysvar::Sysvar",
                                        Ty.path "solana_program::rent::Rent",
                                        [],
                                        "get",
                                        []
                                      |),
                                      []
                                    |)
                                  ]
                                |)
                              |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::ops::control_flow::ControlFlow::Break",
                                        0
                                      |) in
                                    let residual := M.copy (| γ0_0 |) in
                                    M.alloc (|
                                      M.never_to_any (|
                                        M.read (|
                                          M.return_ (|
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "core::ops::try_trait::FromResidual",
                                                Ty.apply
                                                  (Ty.path "core::result::Result")
                                                  [
                                                    Ty.tuple [];
                                                    Ty.path
                                                      "solana_program::program_error::ProgramError"
                                                  ],
                                                [
                                                  Ty.apply
                                                    (Ty.path "core::result::Result")
                                                    [
                                                      Ty.path "core::convert::Infallible";
                                                      Ty.path
                                                        "solana_program::program_error::ProgramError"
                                                    ]
                                                ],
                                                "from_residual",
                                                []
                                              |),
                                              [ M.read (| residual |) ]
                                            |)
                                          |)
                                        |)
                                      |)
                                    |)));
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::ops::control_flow::ControlFlow::Continue",
                                        0
                                      |) in
                                    let val := M.copy (| γ0_0 |) in
                                    val))
                              ]
                            |)
                          |) in
                        let new_rent_exempt_reserve :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "solana_program::rent::Rent",
                                "minimum_balance",
                                []
                              |),
                              [ rent; M.read (| needed_account_len |) ]
                            |)
                          |) in
                        let current_lamport_reserve :=
                          M.copy (|
                            M.match_operator (|
                              M.alloc (|
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::ops::try_trait::Try",
                                    Ty.apply
                                      (Ty.path "core::result::Result")
                                      [ Ty.path "u64"; Ty.path "spl_token_2022::error::TokenError"
                                      ],
                                    [],
                                    "branch",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.apply (Ty.path "core::option::Option") [ Ty.path "u64" ],
                                        "ok_or",
                                        [ Ty.path "spl_token_2022::error::TokenError" ]
                                      |),
                                      [
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.path "u64",
                                            "checked_sub",
                                            []
                                          |),
                                          [
                                            M.call_closure (|
                                              M.get_associated_function (|
                                                Ty.path "solana_program::account_info::AccountInfo",
                                                "lamports",
                                                []
                                              |),
                                              [ M.read (| token_account_info |) ]
                                            |);
                                            M.call_closure (|
                                              M.get_associated_function (|
                                                Ty.apply
                                                  (Ty.path "core::option::Option")
                                                  [ Ty.path "u64" ],
                                                "unwrap_or",
                                                []
                                              |),
                                              [ M.read (| native_token_amount |); Value.Integer 0 ]
                                            |)
                                          ]
                                        |);
                                        Value.StructTuple
                                          "spl_token_2022::error::TokenError::Overflow"
                                          []
                                      ]
                                    |)
                                  ]
                                |)
                              |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::ops::control_flow::ControlFlow::Break",
                                        0
                                      |) in
                                    let residual := M.copy (| γ0_0 |) in
                                    M.alloc (|
                                      M.never_to_any (|
                                        M.read (|
                                          M.return_ (|
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "core::ops::try_trait::FromResidual",
                                                Ty.apply
                                                  (Ty.path "core::result::Result")
                                                  [
                                                    Ty.tuple [];
                                                    Ty.path
                                                      "solana_program::program_error::ProgramError"
                                                  ],
                                                [
                                                  Ty.apply
                                                    (Ty.path "core::result::Result")
                                                    [
                                                      Ty.path "core::convert::Infallible";
                                                      Ty.path "spl_token_2022::error::TokenError"
                                                    ]
                                                ],
                                                "from_residual",
                                                []
                                              |),
                                              [ M.read (| residual |) ]
                                            |)
                                          |)
                                        |)
                                      |)
                                    |)));
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::ops::control_flow::ControlFlow::Continue",
                                        0
                                      |) in
                                    let val := M.copy (| γ0_0 |) in
                                    val))
                              ]
                            |)
                          |) in
                        let lamports_diff :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (| Ty.path "u64", "saturating_sub", [] |),
                              [
                                M.read (| new_rent_exempt_reserve |);
                                M.read (| current_lamport_reserve |)
                              ]
                            |)
                          |) in
                        let _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.Pure.gt (M.read (| lamports_diff |)) (Value.Integer 0)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  let _ :=
                                    M.match_operator (|
                                      M.alloc (|
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::ops::try_trait::Try",
                                            Ty.apply
                                              (Ty.path "core::result::Result")
                                              [
                                                Ty.tuple [];
                                                Ty.path
                                                  "solana_program::program_error::ProgramError"
                                              ],
                                            [],
                                            "branch",
                                            []
                                          |),
                                          [
                                            M.call_closure (|
                                              M.get_function (|
                                                "solana_program::program::invoke",
                                                []
                                              |),
                                              [
                                                M.alloc (|
                                                  M.call_closure (|
                                                    M.get_function (|
                                                      "solana_program::system_instruction::transfer",
                                                      []
                                                    |),
                                                    [
                                                      M.read (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| payer_info |),
                                                          "solana_program::account_info::AccountInfo",
                                                          "key"
                                                        |)
                                                      |);
                                                      M.read (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| token_account_info |),
                                                          "solana_program::account_info::AccountInfo",
                                                          "key"
                                                        |)
                                                      |);
                                                      M.read (| lamports_diff |)
                                                    ]
                                                  |)
                                                |);
                                                (* Unsize *)
                                                M.pointer_coercion
                                                  (M.alloc (|
                                                    Value.Array
                                                      [
                                                        M.call_closure (|
                                                          M.get_trait_method (|
                                                            "core::clone::Clone",
                                                            Ty.path
                                                              "solana_program::account_info::AccountInfo",
                                                            [],
                                                            "clone",
                                                            []
                                                          |),
                                                          [ M.read (| payer_info |) ]
                                                        |);
                                                        M.call_closure (|
                                                          M.get_trait_method (|
                                                            "core::clone::Clone",
                                                            Ty.path
                                                              "solana_program::account_info::AccountInfo",
                                                            [],
                                                            "clone",
                                                            []
                                                          |),
                                                          [ M.read (| token_account_info |) ]
                                                        |);
                                                        M.call_closure (|
                                                          M.get_trait_method (|
                                                            "core::clone::Clone",
                                                            Ty.path
                                                              "solana_program::account_info::AccountInfo",
                                                            [],
                                                            "clone",
                                                            []
                                                          |),
                                                          [ M.read (| system_program_info |) ]
                                                        |)
                                                      ]
                                                  |))
                                              ]
                                            |)
                                          ]
                                        |)
                                      |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ0_0 :=
                                              M.SubPointer.get_struct_tuple_field (|
                                                γ,
                                                "core::ops::control_flow::ControlFlow::Break",
                                                0
                                              |) in
                                            let residual := M.copy (| γ0_0 |) in
                                            M.alloc (|
                                              M.never_to_any (|
                                                M.read (|
                                                  M.return_ (|
                                                    M.call_closure (|
                                                      M.get_trait_method (|
                                                        "core::ops::try_trait::FromResidual",
                                                        Ty.apply
                                                          (Ty.path "core::result::Result")
                                                          [
                                                            Ty.tuple [];
                                                            Ty.path
                                                              "solana_program::program_error::ProgramError"
                                                          ],
                                                        [
                                                          Ty.apply
                                                            (Ty.path "core::result::Result")
                                                            [
                                                              Ty.path "core::convert::Infallible";
                                                              Ty.path
                                                                "solana_program::program_error::ProgramError"
                                                            ]
                                                        ],
                                                        "from_residual",
                                                        []
                                                      |),
                                                      [ M.read (| residual |) ]
                                                    |)
                                                  |)
                                                |)
                                              |)
                                            |)));
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ0_0 :=
                                              M.SubPointer.get_struct_tuple_field (|
                                                γ,
                                                "core::ops::control_flow::ControlFlow::Continue",
                                                0
                                              |) in
                                            let val := M.copy (| γ0_0 |) in
                                            val))
                                      ]
                                    |) in
                                  M.alloc (| Value.Tuple [] |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let token_account_data :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "core::cell::RefCell")
                                  [
                                    Ty.apply
                                      (Ty.path "&mut")
                                      [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]
                                  ],
                                "borrow_mut",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::ops::deref::Deref",
                                    Ty.apply
                                      (Ty.path "alloc::rc::Rc")
                                      [
                                        Ty.apply
                                          (Ty.path "core::cell::RefCell")
                                          [
                                            Ty.apply
                                              (Ty.path "&mut")
                                              [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]
                                          ];
                                        Ty.path "alloc::alloc::Global"
                                      ],
                                    [],
                                    "deref",
                                    []
                                  |),
                                  [
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| token_account_info |),
                                      "solana_program::account_info::AccountInfo",
                                      "data"
                                    |)
                                  ]
                                |)
                              ]
                            |)
                          |) in
                        let _ :=
                          M.match_operator (|
                            M.alloc (|
                              M.call_closure (|
                                M.get_trait_method (|
                                  "core::ops::try_trait::Try",
                                  Ty.apply
                                    (Ty.path "core::result::Result")
                                    [
                                      Ty.tuple [];
                                      Ty.path "solana_program::program_error::ProgramError"
                                    ],
                                  [],
                                  "branch",
                                  []
                                |),
                                [
                                  M.call_closure (|
                                    M.get_function (|
                                      "spl_token_2022::extension::set_account_type",
                                      [ Ty.path "spl_token_2022::state::Account" ]
                                    |),
                                    [
                                      M.read (|
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::ops::deref::DerefMut",
                                            Ty.apply
                                              (Ty.path "core::cell::RefMut")
                                              [
                                                Ty.apply
                                                  (Ty.path "&mut")
                                                  [ Ty.apply (Ty.path "slice") [ Ty.path "u8" ] ]
                                              ],
                                            [],
                                            "deref_mut",
                                            []
                                          |),
                                          [ token_account_data ]
                                        |)
                                      |)
                                    ]
                                  |)
                                ]
                              |)
                            |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::ops::control_flow::ControlFlow::Break",
                                      0
                                    |) in
                                  let residual := M.copy (| γ0_0 |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        M.return_ (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::try_trait::FromResidual",
                                              Ty.apply
                                                (Ty.path "core::result::Result")
                                                [
                                                  Ty.tuple [];
                                                  Ty.path
                                                    "solana_program::program_error::ProgramError"
                                                ],
                                              [
                                                Ty.apply
                                                  (Ty.path "core::result::Result")
                                                  [
                                                    Ty.path "core::convert::Infallible";
                                                    Ty.path
                                                      "solana_program::program_error::ProgramError"
                                                  ]
                                              ],
                                              "from_residual",
                                              []
                                            |),
                                            [ M.read (| residual |) ]
                                          |)
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::ops::control_flow::ControlFlow::Continue",
                                      0
                                    |) in
                                  let val := M.copy (| γ0_0 |) in
                                  val))
                            ]
                          |) in
                        let _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ := native_token_amount in
                                  let γ0_0 :=
                                    M.SubPointer.get_struct_tuple_field (|
                                      γ,
                                      "core::option::Option::Some",
                                      0
                                    |) in
                                  let native_token_amount := M.copy (| γ0_0 |) in
                                  let token_account :=
                                    M.copy (|
                                      M.match_operator (|
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::try_trait::Try",
                                              Ty.apply
                                                (Ty.path "core::result::Result")
                                                [
                                                  Ty.apply
                                                    (Ty.path
                                                      "spl_token_2022::extension::StateWithExtensionsMut")
                                                    [ Ty.path "spl_token_2022::state::Account" ];
                                                  Ty.path
                                                    "solana_program::program_error::ProgramError"
                                                ],
                                              [],
                                              "branch",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_associated_function (|
                                                  Ty.apply
                                                    (Ty.path
                                                      "spl_token_2022::extension::StateWithExtensionsMut")
                                                    [ Ty.path "spl_token_2022::state::Account" ],
                                                  "unpack",
                                                  []
                                                |),
                                                [
                                                  M.read (|
                                                    M.call_closure (|
                                                      M.get_trait_method (|
                                                        "core::ops::deref::DerefMut",
                                                        Ty.apply
                                                          (Ty.path "core::cell::RefMut")
                                                          [
                                                            Ty.apply
                                                              (Ty.path "&mut")
                                                              [
                                                                Ty.apply
                                                                  (Ty.path "slice")
                                                                  [ Ty.path "u8" ]
                                                              ]
                                                          ],
                                                        [],
                                                        "deref_mut",
                                                        []
                                                      |),
                                                      [ token_account_data ]
                                                    |)
                                                  |)
                                                ]
                                              |)
                                            ]
                                          |)
                                        |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::ops::control_flow::ControlFlow::Break",
                                                  0
                                                |) in
                                              let residual := M.copy (| γ0_0 |) in
                                              M.alloc (|
                                                M.never_to_any (|
                                                  M.read (|
                                                    M.return_ (|
                                                      M.call_closure (|
                                                        M.get_trait_method (|
                                                          "core::ops::try_trait::FromResidual",
                                                          Ty.apply
                                                            (Ty.path "core::result::Result")
                                                            [
                                                              Ty.tuple [];
                                                              Ty.path
                                                                "solana_program::program_error::ProgramError"
                                                            ],
                                                          [
                                                            Ty.apply
                                                              (Ty.path "core::result::Result")
                                                              [
                                                                Ty.path "core::convert::Infallible";
                                                                Ty.path
                                                                  "solana_program::program_error::ProgramError"
                                                              ]
                                                          ],
                                                          "from_residual",
                                                          []
                                                        |),
                                                        [ M.read (| residual |) ]
                                                      |)
                                                    |)
                                                  |)
                                                |)
                                              |)));
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::ops::control_flow::ControlFlow::Continue",
                                                  0
                                                |) in
                                              let val := M.copy (| γ0_0 |) in
                                              val))
                                        ]
                                      |)
                                    |) in
                                  let minimum_lamports :=
                                    M.copy (|
                                      M.match_operator (|
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::try_trait::Try",
                                              Ty.apply
                                                (Ty.path "core::result::Result")
                                                [
                                                  Ty.path "u64";
                                                  Ty.path "spl_token_2022::error::TokenError"
                                                ],
                                              [],
                                              "branch",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_associated_function (|
                                                  Ty.apply
                                                    (Ty.path "core::option::Option")
                                                    [ Ty.path "u64" ],
                                                  "ok_or",
                                                  [ Ty.path "spl_token_2022::error::TokenError" ]
                                                |),
                                                [
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.path "u64",
                                                      "checked_add",
                                                      []
                                                    |),
                                                    [
                                                      M.read (| new_rent_exempt_reserve |);
                                                      M.read (| native_token_amount |)
                                                    ]
                                                  |);
                                                  Value.StructTuple
                                                    "spl_token_2022::error::TokenError::Overflow"
                                                    []
                                                ]
                                              |)
                                            ]
                                          |)
                                        |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::ops::control_flow::ControlFlow::Break",
                                                  0
                                                |) in
                                              let residual := M.copy (| γ0_0 |) in
                                              M.alloc (|
                                                M.never_to_any (|
                                                  M.read (|
                                                    M.return_ (|
                                                      M.call_closure (|
                                                        M.get_trait_method (|
                                                          "core::ops::try_trait::FromResidual",
                                                          Ty.apply
                                                            (Ty.path "core::result::Result")
                                                            [
                                                              Ty.tuple [];
                                                              Ty.path
                                                                "solana_program::program_error::ProgramError"
                                                            ],
                                                          [
                                                            Ty.apply
                                                              (Ty.path "core::result::Result")
                                                              [
                                                                Ty.path "core::convert::Infallible";
                                                                Ty.path
                                                                  "spl_token_2022::error::TokenError"
                                                              ]
                                                          ],
                                                          "from_residual",
                                                          []
                                                        |),
                                                        [ M.read (| residual |) ]
                                                      |)
                                                    |)
                                                  |)
                                                |)
                                              |)));
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::ops::control_flow::ControlFlow::Continue",
                                                  0
                                                |) in
                                              let val := M.copy (| γ0_0 |) in
                                              val))
                                        ]
                                      |)
                                    |) in
                                  let _ :=
                                    M.match_operator (|
                                      M.alloc (| Value.Tuple [] |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ :=
                                              M.use
                                                (M.alloc (|
                                                  BinOp.Pure.lt
                                                    (M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path
                                                          "solana_program::account_info::AccountInfo",
                                                        "lamports",
                                                        []
                                                      |),
                                                      [ M.read (| token_account_info |) ]
                                                    |))
                                                    (M.read (| minimum_lamports |))
                                                |)) in
                                            let _ :=
                                              M.is_constant_or_break_match (|
                                                M.read (| γ |),
                                                Value.Bool true
                                              |) in
                                            M.alloc (|
                                              M.never_to_any (|
                                                M.read (|
                                                  M.return_ (|
                                                    Value.StructTuple
                                                      "core::result::Result::Err"
                                                      [
                                                        M.call_closure (|
                                                          M.get_trait_method (|
                                                            "core::convert::Into",
                                                            Ty.path
                                                              "spl_token_2022::error::TokenError",
                                                            [
                                                              Ty.path
                                                                "solana_program::program_error::ProgramError"
                                                            ],
                                                            "into",
                                                            []
                                                          |),
                                                          [
                                                            Value.StructTuple
                                                              "spl_token_2022::error::TokenError::InvalidState"
                                                              []
                                                          ]
                                                        |)
                                                      ]
                                                  |)
                                                |)
                                              |)
                                            |)));
                                        fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                      ]
                                    |) in
                                  let _ :=
                                    M.write (|
                                      M.SubPointer.get_struct_record_field (|
                                        M.SubPointer.get_struct_record_field (|
                                          token_account,
                                          "spl_token_2022::extension::StateWithExtensionsMut",
                                          "base"
                                        |),
                                        "spl_token_2022::state::Account",
                                        "is_native"
                                      |),
                                      Value.StructTuple
                                        "solana_program::program_option::COption::Some"
                                        [ M.read (| new_rent_exempt_reserve |) ]
                                    |) in
                                  let _ :=
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.apply
                                            (Ty.path
                                              "spl_token_2022::extension::StateWithExtensionsMut")
                                            [ Ty.path "spl_token_2022::state::Account" ],
                                          "pack_base",
                                          []
                                        |),
                                        [ token_account ]
                                      |)
                                    |) in
                                  M.alloc (| Value.Tuple [] |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        M.alloc (|
                          Value.StructTuple "core::result::Result::Ok" [ Value.Tuple [] ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _ => M.impossible
      end.
  End reallocate.
End extension.
