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

Module instructions.
  Module contract.
    (*
    pub fn resize_memory(
        interpreter: &mut Interpreter,
        offset: U256,
        len: U256,
    ) -> Option<Range<usize>> {
        let len = as_usize_or_fail_ret!(interpreter, len, None);
        if len != 0 {
            let offset = as_usize_or_fail_ret!(interpreter, offset, None);
            resize_memory!(interpreter, offset, len, None);
            // range is checked in resize_memory! macro and it is bounded by usize.
            Some(offset..offset + len)
        } else {
            //unrealistic value so we are sure it is not used
            Some(usize::MAX..usize::MAX)
        }
    }
    *)
    Definition resize_memory (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ interpreter; offset; len ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let offset := M.alloc (| offset |) in
          let len := M.alloc (| len |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ len :=
                  M.copy (|
                    let~ x :=
                      M.alloc (|
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.apply
                              (Ty.path "ruint::Uint")
                              [
                                Value.Integer IntegerKind.Usize 256;
                                Value.Integer IntegerKind.Usize 4
                              ]
                              [],
                            "as_limbs",
                            []
                          |),
                          [ len ]
                        |)
                      |) in
                    let~ _ :=
                      M.match_operator (|
                        M.alloc (| Value.Tuple [] |),
                        [
                          fun γ =>
                            ltac:(M.monadic
                              (let γ :=
                                M.use
                                  (M.alloc (|
                                    LogicalOp.or (|
                                      LogicalOp.or (|
                                        BinOp.ne (|
                                          M.read (|
                                            M.SubPointer.get_array_field (|
                                              M.read (| x |),
                                              M.alloc (| Value.Integer IntegerKind.Usize 1 |)
                                            |)
                                          |),
                                          Value.Integer IntegerKind.U64 0
                                        |),
                                        ltac:(M.monadic
                                          (BinOp.ne (|
                                            M.read (|
                                              M.SubPointer.get_array_field (|
                                                M.read (| x |),
                                                M.alloc (| Value.Integer IntegerKind.Usize 2 |)
                                              |)
                                            |),
                                            Value.Integer IntegerKind.U64 0
                                          |)))
                                      |),
                                      ltac:(M.monadic
                                        (BinOp.ne (|
                                          M.read (|
                                            M.SubPointer.get_array_field (|
                                              M.read (| x |),
                                              M.alloc (| Value.Integer IntegerKind.Usize 3 |)
                                            |)
                                          |),
                                          Value.Integer IntegerKind.U64 0
                                        |)))
                                    |)
                                  |)) in
                              let _ :=
                                M.is_constant_or_break_match (|
                                  M.read (| γ |),
                                  Value.Bool true
                                |) in
                              M.alloc (|
                                M.never_to_any (|
                                  M.read (|
                                    let~ _ :=
                                      M.write (|
                                        M.SubPointer.get_struct_record_field (|
                                          M.read (| interpreter |),
                                          "revm_interpreter::interpreter::Interpreter",
                                          "instruction_result"
                                        |),
                                        Value.StructTuple
                                          "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG"
                                          []
                                      |) in
                                    M.return_ (|
                                      Value.StructTuple "core::option::Option::None" []
                                    |)
                                  |)
                                |)
                              |)));
                          fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                        ]
                      |) in
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::TryFrom",
                            Ty.path "usize",
                            [ Ty.path "u64" ],
                            "try_from",
                            []
                          |),
                          [
                            M.read (|
                              M.SubPointer.get_array_field (|
                                M.read (| x |),
                                M.alloc (| Value.Integer IntegerKind.Usize 0 |)
                              |)
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::result::Result::Ok",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |)
                  |) in
                M.match_operator (|
                  M.alloc (| Value.Tuple [] |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ :=
                          M.use
                            (M.alloc (|
                              BinOp.ne (| M.read (| len |), Value.Integer IntegerKind.Usize 0 |)
                            |)) in
                        let _ :=
                          M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                        let~ offset :=
                          M.copy (|
                            let~ x :=
                              M.alloc (|
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "ruint::Uint")
                                      [
                                        Value.Integer IntegerKind.Usize 256;
                                        Value.Integer IntegerKind.Usize 4
                                      ]
                                      [],
                                    "as_limbs",
                                    []
                                  |),
                                  [ offset ]
                                |)
                              |) in
                            let~ _ :=
                              M.match_operator (|
                                M.alloc (| Value.Tuple [] |),
                                [
                                  fun γ =>
                                    ltac:(M.monadic
                                      (let γ :=
                                        M.use
                                          (M.alloc (|
                                            LogicalOp.or (|
                                              LogicalOp.or (|
                                                BinOp.ne (|
                                                  M.read (|
                                                    M.SubPointer.get_array_field (|
                                                      M.read (| x |),
                                                      M.alloc (|
                                                        Value.Integer IntegerKind.Usize 1
                                                      |)
                                                    |)
                                                  |),
                                                  Value.Integer IntegerKind.U64 0
                                                |),
                                                ltac:(M.monadic
                                                  (BinOp.ne (|
                                                    M.read (|
                                                      M.SubPointer.get_array_field (|
                                                        M.read (| x |),
                                                        M.alloc (|
                                                          Value.Integer IntegerKind.Usize 2
                                                        |)
                                                      |)
                                                    |),
                                                    Value.Integer IntegerKind.U64 0
                                                  |)))
                                              |),
                                              ltac:(M.monadic
                                                (BinOp.ne (|
                                                  M.read (|
                                                    M.SubPointer.get_array_field (|
                                                      M.read (| x |),
                                                      M.alloc (|
                                                        Value.Integer IntegerKind.Usize 3
                                                      |)
                                                    |)
                                                  |),
                                                  Value.Integer IntegerKind.U64 0
                                                |)))
                                            |)
                                          |)) in
                                      let _ :=
                                        M.is_constant_or_break_match (|
                                          M.read (| γ |),
                                          Value.Bool true
                                        |) in
                                      M.alloc (|
                                        M.never_to_any (|
                                          M.read (|
                                            let~ _ :=
                                              M.write (|
                                                M.SubPointer.get_struct_record_field (|
                                                  M.read (| interpreter |),
                                                  "revm_interpreter::interpreter::Interpreter",
                                                  "instruction_result"
                                                |),
                                                Value.StructTuple
                                                  "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG"
                                                  []
                                              |) in
                                            M.return_ (|
                                              Value.StructTuple "core::option::Option::None" []
                                            |)
                                          |)
                                        |)
                                      |)));
                                  fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                ]
                              |) in
                            M.match_operator (|
                              M.alloc (|
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::convert::TryFrom",
                                    Ty.path "usize",
                                    [ Ty.path "u64" ],
                                    "try_from",
                                    []
                                  |),
                                  [
                                    M.read (|
                                      M.SubPointer.get_array_field (|
                                        M.read (| x |),
                                        M.alloc (| Value.Integer IntegerKind.Usize 0 |)
                                      |)
                                    |)
                                  ]
                                |)
                              |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::result::Result::Ok",
                                        0
                                      |) in
                                    let val := M.copy (| γ0_0 |) in
                                    val))
                              ]
                            |)
                          |) in
                        let~ new_size :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (| Ty.path "usize", "saturating_add", [] |),
                              [ M.read (| offset |); M.read (| len |) ]
                            |)
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.gt (|
                                          M.read (| new_size |),
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.path
                                                "revm_interpreter::interpreter::shared_memory::SharedMemory",
                                              "len",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| interpreter |),
                                                "revm_interpreter::interpreter::Interpreter",
                                                "shared_memory"
                                              |)
                                            ]
                                          |)
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.match_operator (|
                                    M.alloc (| Value.Tuple [] |),
                                    [
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let γ :=
                                            M.use
                                              (M.alloc (|
                                                UnOp.not (|
                                                  M.call_closure (|
                                                    M.get_function (|
                                                      "revm_interpreter::interpreter::resize_memory",
                                                      []
                                                    |),
                                                    [
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.read (| interpreter |),
                                                        "revm_interpreter::interpreter::Interpreter",
                                                        "shared_memory"
                                                      |);
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.read (| interpreter |),
                                                        "revm_interpreter::interpreter::Interpreter",
                                                        "gas"
                                                      |);
                                                      M.read (| new_size |)
                                                    ]
                                                  |)
                                                |)
                                              |)) in
                                          let _ :=
                                            M.is_constant_or_break_match (|
                                              M.read (| γ |),
                                              Value.Bool true
                                            |) in
                                          M.alloc (|
                                            M.never_to_any (|
                                              M.read (|
                                                let~ _ :=
                                                  M.write (|
                                                    M.SubPointer.get_struct_record_field (|
                                                      M.read (| interpreter |),
                                                      "revm_interpreter::interpreter::Interpreter",
                                                      "instruction_result"
                                                    |),
                                                    Value.StructTuple
                                                      "revm_interpreter::instruction_result::InstructionResult::MemoryOOG"
                                                      []
                                                  |) in
                                                M.return_ (|
                                                  Value.StructTuple "core::option::Option::None" []
                                                |)
                                              |)
                                            |)
                                          |)));
                                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                    ]
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        M.alloc (|
                          Value.StructTuple
                            "core::option::Option::Some"
                            [
                              Value.StructRecord
                                "core::ops::range::Range"
                                [
                                  ("start", M.read (| offset |));
                                  ("end_",
                                    BinOp.Wrap.add (| M.read (| offset |), M.read (| len |) |))
                                ]
                            ]
                        |)));
                    fun γ =>
                      ltac:(M.monadic
                        (M.alloc (|
                          Value.StructTuple
                            "core::option::Option::Some"
                            [
                              Value.StructRecord
                                "core::ops::range::Range"
                                [
                                  ("start", M.read (| M.get_constant (| "core::num::MAX" |) |));
                                  ("end_", M.read (| M.get_constant (| "core::num::MAX" |) |))
                                ]
                            ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_resize_memory :
      M.IsFunction "revm_interpreter::instructions::contract::resize_memory" resize_memory.
    
    (*
    pub fn eofcreate<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
        require_eof!(interpreter);
        gas!(interpreter, EOF_CREATE_GAS);
        let initcontainer_index = unsafe { *interpreter.instruction_pointer };
        pop!(interpreter, value, salt, data_offset, data_size);
    
        let sub_container = interpreter
            .eof()
            .expect("EOF is set")
            .body
            .container_section
            .get(initcontainer_index as usize)
            .cloned()
            .expect("EOF is checked");
    
        // resize memory and get return range.
        let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else {
            return;
        };
    
        let eof = Eof::decode(sub_container.clone()).expect("Subcontainer is verified");
    
        if !eof.body.is_data_filled {
            // should be always false as it is verified by eof verification.
            panic!("Panic if data section is not full");
        }
    
        // deduct gas for hash that is needed to calculate address.
        gas_or_fail!(
            interpreter,
            cost_per_word(sub_container.len() as u64, KECCAK256WORD)
        );
    
        let created_address = interpreter
            .contract
            .caller
            .create2(salt.to_be_bytes(), keccak256(sub_container));
    
        // Send container for execution container is preverified.
        interpreter.next_action = InterpreterAction::EOFCreate {
            inputs: Box::new(EOFCreateInput::new(
                interpreter.contract.target_address,
                created_address,
                value,
                eof,
                interpreter.gas().remaining(),
                return_range,
            )),
        };
    
        interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) };
    }
    *)
    Definition eofcreate (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H ], [ interpreter; _host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let _host := M.alloc (| _host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.read (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "is_eof"
                                    |)
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::gas::Gas",
                                      "record_cost",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "gas"
                                      |);
                                      M.read (|
                                        M.get_constant (|
                                          "revm_interpreter::gas::constants::EOF_CREATE_GAS"
                                        |)
                                      |)
                                    ]
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ initcontainer_index :=
                  M.copy (|
                    M.read (|
                      M.SubPointer.get_struct_record_field (|
                        M.read (| interpreter |),
                        "revm_interpreter::interpreter::Interpreter",
                        "instruction_pointer"
                      |)
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 4
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop4_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |),
                  [
                    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 γ0_2 := M.SubPointer.get_tuple_field (| γ, 2 |) in
                        let γ0_3 := M.SubPointer.get_tuple_field (| γ, 3 |) in
                        let value := M.copy (| γ0_0 |) in
                        let salt := M.copy (| γ0_1 |) in
                        let data_offset := M.copy (| γ0_2 |) in
                        let data_size := M.copy (| γ0_3 |) in
                        let~ sub_container :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "core::option::Option")
                                  []
                                  [ Ty.path "alloy_primitives::bytes_::Bytes" ],
                                "expect",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "core::option::Option")
                                      []
                                      [
                                        Ty.apply
                                          (Ty.path "&")
                                          []
                                          [ Ty.path "alloy_primitives::bytes_::Bytes" ]
                                      ],
                                    "cloned",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.apply
                                          (Ty.path "slice")
                                          []
                                          [ Ty.path "alloy_primitives::bytes_::Bytes" ],
                                        "get",
                                        [ Ty.path "usize" ]
                                      |),
                                      [
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::ops::deref::Deref",
                                            Ty.apply
                                              (Ty.path "alloc::vec::Vec")
                                              []
                                              [
                                                Ty.path "alloy_primitives::bytes_::Bytes";
                                                Ty.path "alloc::alloc::Global"
                                              ],
                                            [],
                                            "deref",
                                            []
                                          |),
                                          [
                                            M.SubPointer.get_struct_record_field (|
                                              M.SubPointer.get_struct_record_field (|
                                                M.call_closure (|
                                                  M.get_associated_function (|
                                                    Ty.apply
                                                      (Ty.path "core::option::Option")
                                                      []
                                                      [
                                                        Ty.apply
                                                          (Ty.path "&")
                                                          []
                                                          [
                                                            Ty.path
                                                              "revm_primitives::bytecode::eof::Eof"
                                                          ]
                                                      ],
                                                    "expect",
                                                    []
                                                  |),
                                                  [
                                                    M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path
                                                          "revm_interpreter::interpreter::Interpreter",
                                                        "eof",
                                                        []
                                                      |),
                                                      [ M.read (| interpreter |) ]
                                                    |);
                                                    M.read (| Value.String "EOF is set" |)
                                                  ]
                                                |),
                                                "revm_primitives::bytecode::eof::Eof",
                                                "body"
                                              |),
                                              "revm_primitives::bytecode::eof::body::EofBody",
                                              "container_section"
                                            |)
                                          ]
                                        |);
                                        M.rust_cast (M.read (| initcontainer_index |))
                                      ]
                                    |)
                                  ]
                                |);
                                M.read (| Value.String "EOF is checked" |)
                              ]
                            |)
                          |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (|
                                "revm_interpreter::instructions::contract::resize_memory",
                                []
                              |),
                              [
                                M.read (| interpreter |);
                                M.read (| data_offset |);
                                M.read (| data_size |)
                              ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let return_range := M.copy (| γ0_0 |) in
                                let~ eof :=
                                  M.alloc (|
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          []
                                          [
                                            Ty.path "revm_primitives::bytecode::eof::Eof";
                                            Ty.path "revm_primitives::bytecode::eof::EofDecodeError"
                                          ],
                                        "expect",
                                        []
                                      |),
                                      [
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.path "revm_primitives::bytecode::eof::Eof",
                                            "decode",
                                            []
                                          |),
                                          [
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "core::clone::Clone",
                                                Ty.path "alloy_primitives::bytes_::Bytes",
                                                [],
                                                "clone",
                                                []
                                              |),
                                              [ sub_container ]
                                            |)
                                          ]
                                        |);
                                        M.read (| Value.String "Subcontainer is verified" |)
                                      ]
                                    |)
                                  |) in
                                let~ _ :=
                                  M.match_operator (|
                                    M.alloc (| Value.Tuple [] |),
                                    [
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let γ :=
                                            M.use
                                              (M.alloc (|
                                                UnOp.not (|
                                                  M.read (|
                                                    M.SubPointer.get_struct_record_field (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        eof,
                                                        "revm_primitives::bytecode::eof::Eof",
                                                        "body"
                                                      |),
                                                      "revm_primitives::bytecode::eof::body::EofBody",
                                                      "is_data_filled"
                                                    |)
                                                  |)
                                                |)
                                              |)) in
                                          let _ :=
                                            M.is_constant_or_break_match (|
                                              M.read (| γ |),
                                              Value.Bool true
                                            |) in
                                          M.alloc (|
                                            M.never_to_any (|
                                              M.call_closure (|
                                                M.get_function (|
                                                  "core::panicking::panic_fmt",
                                                  []
                                                |),
                                                [
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.path "core::fmt::Arguments",
                                                      "new_const",
                                                      []
                                                    |),
                                                    [
                                                      M.alloc (|
                                                        Value.Array
                                                          [
                                                            M.read (|
                                                              Value.String
                                                                "Panic if data section is not full"
                                                            |)
                                                          ]
                                                      |)
                                                    ]
                                                  |)
                                                ]
                                              |)
                                            |)
                                          |)));
                                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                    ]
                                  |) in
                                let~ _ :=
                                  M.match_operator (|
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_function (|
                                          "revm_interpreter::gas::calc::cost_per_word",
                                          []
                                        |),
                                        [
                                          M.rust_cast
                                            (M.call_closure (|
                                              M.get_associated_function (|
                                                Ty.path "bytes::bytes::Bytes",
                                                "len",
                                                []
                                              |),
                                              [
                                                M.call_closure (|
                                                  M.get_trait_method (|
                                                    "core::ops::deref::Deref",
                                                    Ty.path "alloy_primitives::bytes_::Bytes",
                                                    [],
                                                    "deref",
                                                    []
                                                  |),
                                                  [ sub_container ]
                                                |)
                                              ]
                                            |));
                                          M.read (|
                                            M.get_constant (|
                                              "revm_interpreter::gas::constants::KECCAK256WORD"
                                            |)
                                          |)
                                        ]
                                      |)
                                    |),
                                    [
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let γ0_0 :=
                                            M.SubPointer.get_struct_tuple_field (|
                                              γ,
                                              "core::option::Option::Some",
                                              0
                                            |) in
                                          let gas_used := M.copy (| γ0_0 |) in
                                          M.match_operator (|
                                            M.alloc (| Value.Tuple [] |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ :=
                                                    M.use
                                                      (M.alloc (|
                                                        UnOp.not (|
                                                          M.call_closure (|
                                                            M.get_associated_function (|
                                                              Ty.path "revm_interpreter::gas::Gas",
                                                              "record_cost",
                                                              []
                                                            |),
                                                            [
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "gas"
                                                              |);
                                                              M.read (| gas_used |)
                                                            ]
                                                          |)
                                                        |)
                                                      |)) in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |)));
                                      fun γ =>
                                        ltac:(M.monadic
                                          (let _ :=
                                            M.is_struct_tuple (|
                                              γ,
                                              "core::option::Option::None"
                                            |) in
                                          M.alloc (|
                                            M.never_to_any (|
                                              M.read (|
                                                let~ _ :=
                                                  M.write (|
                                                    M.SubPointer.get_struct_record_field (|
                                                      M.read (| interpreter |),
                                                      "revm_interpreter::interpreter::Interpreter",
                                                      "instruction_result"
                                                    |),
                                                    Value.StructTuple
                                                      "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                      []
                                                  |) in
                                                M.return_ (| Value.Tuple [] |)
                                              |)
                                            |)
                                          |)))
                                    ]
                                  |) in
                                let~ created_address :=
                                  M.alloc (|
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.path "alloy_primitives::bits::address::Address",
                                        "create2",
                                        [
                                          Ty.apply
                                            (Ty.path "array")
                                            [ Value.Integer IntegerKind.Usize 32 ]
                                            [ Ty.path "u8" ];
                                          Ty.apply
                                            (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                            [ Value.Integer IntegerKind.Usize 32 ]
                                            []
                                        ]
                                      |),
                                      [
                                        M.SubPointer.get_struct_record_field (|
                                          M.SubPointer.get_struct_record_field (|
                                            M.read (| interpreter |),
                                            "revm_interpreter::interpreter::Interpreter",
                                            "contract"
                                          |),
                                          "revm_interpreter::interpreter::contract::Contract",
                                          "caller"
                                        |);
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.apply
                                              (Ty.path "ruint::Uint")
                                              [
                                                Value.Integer IntegerKind.Usize 256;
                                                Value.Integer IntegerKind.Usize 4
                                              ]
                                              [],
                                            "to_be_bytes",
                                            []
                                          |),
                                          [ salt ]
                                        |);
                                        M.call_closure (|
                                          M.get_function (|
                                            "alloy_primitives::utils::keccak256",
                                            [ Ty.path "alloy_primitives::bytes_::Bytes" ]
                                          |),
                                          [ M.read (| sub_container |) ]
                                        |)
                                      ]
                                    |)
                                  |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "next_action"
                                    |),
                                    Value.StructRecord
                                      "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate"
                                      [
                                        ("inputs",
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "alloc::boxed::Box")
                                                []
                                                [
                                                  Ty.path
                                                    "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput";
                                                  Ty.path "alloc::alloc::Global"
                                                ],
                                              "new",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_associated_function (|
                                                  Ty.path
                                                    "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput",
                                                  "new",
                                                  []
                                                |),
                                                [
                                                  M.read (|
                                                    M.SubPointer.get_struct_record_field (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.read (| interpreter |),
                                                        "revm_interpreter::interpreter::Interpreter",
                                                        "contract"
                                                      |),
                                                      "revm_interpreter::interpreter::contract::Contract",
                                                      "target_address"
                                                    |)
                                                  |);
                                                  M.read (| created_address |);
                                                  M.read (| value |);
                                                  M.read (| eof |);
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.path "revm_interpreter::gas::Gas",
                                                      "remaining",
                                                      []
                                                    |),
                                                    [
                                                      M.call_closure (|
                                                        M.get_associated_function (|
                                                          Ty.path
                                                            "revm_interpreter::interpreter::Interpreter",
                                                          "gas",
                                                          []
                                                        |),
                                                        [ M.read (| interpreter |) ]
                                                      |)
                                                    ]
                                                  |);
                                                  M.read (| return_range |)
                                                ]
                                              |)
                                            ]
                                          |))
                                      ]
                                  |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_pointer"
                                    |),
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.apply (Ty.path "*const") [] [ Ty.path "u8" ],
                                        "offset",
                                        []
                                      |),
                                      [
                                        M.read (|
                                          M.SubPointer.get_struct_record_field (|
                                            M.read (| interpreter |),
                                            "revm_interpreter::interpreter::Interpreter",
                                            "instruction_pointer"
                                          |)
                                        |);
                                        Value.Integer IntegerKind.Isize 1
                                      ]
                                    |)
                                  |) in
                                M.alloc (| Value.Tuple [] |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_eofcreate :
      M.IsFunction "revm_interpreter::instructions::contract::eofcreate" eofcreate.
    
    (*
    pub fn txcreate<H: Host + ?Sized>(interpreter: &mut Interpreter, host: &mut H) {
        require_eof!(interpreter);
        gas!(interpreter, EOF_CREATE_GAS);
        pop!(
            interpreter,
            tx_initcode_hash,
            value,
            salt,
            data_offset,
            data_size
        );
        let tx_initcode_hash = B256::from(tx_initcode_hash);
    
        // resize memory and get return range.
        let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else {
            return;
        };
    
        // fetch initcode, if not found push ZERO.
        let Some(initcode) = host
            .env()
            .tx
            .eof_initcodes_hashed
            .get(&tx_initcode_hash)
            .cloned()
        else {
            push!(interpreter, U256::ZERO);
            return;
        };
    
        // deduct gas for validation
        gas_or_fail!(interpreter, cost_per_word(initcode.len() as u64, BASE));
    
        // deduct gas for hash. TODO check order of actions.
        gas_or_fail!(
            interpreter,
            cost_per_word(initcode.len() as u64, KECCAK256WORD)
        );
    
        let Ok(eof) = Eof::decode(initcode.clone()) else {
            push!(interpreter, U256::ZERO);
            return;
        };
    
        // Data section should be full, push zero to stack and return if not.
        if !eof.body.is_data_filled {
            push!(interpreter, U256::ZERO);
            return;
        }
    
        // Validate initcode
        if validate_eof(&eof).is_err() {
            push!(interpreter, U256::ZERO);
            return;
        }
    
        // Create new address. Gas for it is already deducted.
        let created_address = interpreter
            .contract
            .caller
            .create2(salt.to_be_bytes(), tx_initcode_hash);
    
        let gas_limit = interpreter.gas().remaining();
        // spend all gas. It will be reimbursed after frame returns.
        gas!(interpreter, gas_limit);
    
        interpreter.next_action = InterpreterAction::EOFCreate {
            inputs: Box::new(EOFCreateInput::new(
                interpreter.contract.target_address,
                created_address,
                value,
                eof,
                gas_limit,
                return_range,
            )),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition txcreate (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.read (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "is_eof"
                                    |)
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::gas::Gas",
                                      "record_cost",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "gas"
                                      |);
                                      M.read (|
                                        M.get_constant (|
                                          "revm_interpreter::gas::constants::EOF_CREATE_GAS"
                                        |)
                                      |)
                                    ]
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 4
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop5_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |),
                  [
                    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 γ0_2 := M.SubPointer.get_tuple_field (| γ, 2 |) in
                        let γ0_3 := M.SubPointer.get_tuple_field (| γ, 3 |) in
                        let γ0_4 := M.SubPointer.get_tuple_field (| γ, 4 |) in
                        let tx_initcode_hash := M.copy (| γ0_0 |) in
                        let value := M.copy (| γ0_1 |) in
                        let salt := M.copy (| γ0_2 |) in
                        let data_offset := M.copy (| γ0_3 |) in
                        let data_size := M.copy (| γ0_4 |) in
                        let~ tx_initcode_hash :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "core::convert::From",
                                Ty.apply
                                  (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                  [ Value.Integer IntegerKind.Usize 32 ]
                                  [],
                                [
                                  Ty.apply
                                    (Ty.path "ruint::Uint")
                                    [
                                      Value.Integer IntegerKind.Usize 256;
                                      Value.Integer IntegerKind.Usize 4
                                    ]
                                    []
                                ],
                                "from",
                                []
                              |),
                              [ M.read (| tx_initcode_hash |) ]
                            |)
                          |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (|
                                "revm_interpreter::instructions::contract::resize_memory",
                                []
                              |),
                              [
                                M.read (| interpreter |);
                                M.read (| data_offset |);
                                M.read (| data_size |)
                              ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let return_range := M.copy (| γ0_0 |) in
                                M.match_operator (|
                                  M.alloc (|
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.apply
                                          (Ty.path "core::option::Option")
                                          []
                                          [
                                            Ty.apply
                                              (Ty.path "&")
                                              []
                                              [ Ty.path "alloy_primitives::bytes_::Bytes" ]
                                          ],
                                        "cloned",
                                        []
                                      |),
                                      [
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.apply
                                              (Ty.path "std::collections::hash::map::HashMap")
                                              []
                                              [
                                                Ty.apply
                                                  (Ty.path
                                                    "alloy_primitives::bits::fixed::FixedBytes")
                                                  [ Value.Integer IntegerKind.Usize 32 ]
                                                  [];
                                                Ty.path "alloy_primitives::bytes_::Bytes";
                                                Ty.path "std::hash::random::RandomState"
                                              ],
                                            "get",
                                            [
                                              Ty.apply
                                                (Ty.path
                                                  "alloy_primitives::bits::fixed::FixedBytes")
                                                [ Value.Integer IntegerKind.Usize 32 ]
                                                []
                                            ]
                                          |),
                                          [
                                            M.SubPointer.get_struct_record_field (|
                                              M.SubPointer.get_struct_record_field (|
                                                M.call_closure (|
                                                  M.get_trait_method (|
                                                    "revm_interpreter::host::Host",
                                                    H,
                                                    [],
                                                    "env",
                                                    []
                                                  |),
                                                  [ M.read (| host |) ]
                                                |),
                                                "revm_primitives::env::Env",
                                                "tx"
                                              |),
                                              "revm_primitives::env::TxEnv",
                                              "eof_initcodes_hashed"
                                            |);
                                            tx_initcode_hash
                                          ]
                                        |)
                                      ]
                                    |)
                                  |),
                                  [
                                    fun γ =>
                                      ltac:(M.monadic
                                        (let γ0_0 :=
                                          M.SubPointer.get_struct_tuple_field (|
                                            γ,
                                            "core::option::Option::Some",
                                            0
                                          |) in
                                        let initcode := M.copy (| γ0_0 |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (|
                                              M.call_closure (|
                                                M.get_function (|
                                                  "revm_interpreter::gas::calc::cost_per_word",
                                                  []
                                                |),
                                                [
                                                  M.rust_cast
                                                    (M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path "bytes::bytes::Bytes",
                                                        "len",
                                                        []
                                                      |),
                                                      [
                                                        M.call_closure (|
                                                          M.get_trait_method (|
                                                            "core::ops::deref::Deref",
                                                            Ty.path
                                                              "alloy_primitives::bytes_::Bytes",
                                                            [],
                                                            "deref",
                                                            []
                                                          |),
                                                          [ initcode ]
                                                        |)
                                                      ]
                                                    |));
                                                  M.read (|
                                                    M.get_constant (|
                                                      "revm_interpreter::gas::constants::BASE"
                                                    |)
                                                  |)
                                                ]
                                              |)
                                            |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ0_0 :=
                                                    M.SubPointer.get_struct_tuple_field (|
                                                      γ,
                                                      "core::option::Option::Some",
                                                      0
                                                    |) in
                                                  let gas_used := M.copy (| γ0_0 |) in
                                                  M.match_operator (|
                                                    M.alloc (| Value.Tuple [] |),
                                                    [
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (let γ :=
                                                            M.use
                                                              (M.alloc (|
                                                                UnOp.not (|
                                                                  M.call_closure (|
                                                                    M.get_associated_function (|
                                                                      Ty.path
                                                                        "revm_interpreter::gas::Gas",
                                                                      "record_cost",
                                                                      []
                                                                    |),
                                                                    [
                                                                      M.SubPointer.get_struct_record_field (|
                                                                        M.read (| interpreter |),
                                                                        "revm_interpreter::interpreter::Interpreter",
                                                                        "gas"
                                                                      |);
                                                                      M.read (| gas_used |)
                                                                    ]
                                                                  |)
                                                                |)
                                                              |)) in
                                                          let _ :=
                                                            M.is_constant_or_break_match (|
                                                              M.read (| γ |),
                                                              Value.Bool true
                                                            |) in
                                                          M.alloc (|
                                                            M.never_to_any (|
                                                              M.read (|
                                                                let~ _ :=
                                                                  M.write (|
                                                                    M.SubPointer.get_struct_record_field (|
                                                                      M.read (| interpreter |),
                                                                      "revm_interpreter::interpreter::Interpreter",
                                                                      "instruction_result"
                                                                    |),
                                                                    Value.StructTuple
                                                                      "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                                      []
                                                                  |) in
                                                                M.return_ (| Value.Tuple [] |)
                                                              |)
                                                            |)
                                                          |)));
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (M.alloc (| Value.Tuple [] |)))
                                                    ]
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let _ :=
                                                    M.is_struct_tuple (|
                                                      γ,
                                                      "core::option::Option::None"
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)))
                                            ]
                                          |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (|
                                              M.call_closure (|
                                                M.get_function (|
                                                  "revm_interpreter::gas::calc::cost_per_word",
                                                  []
                                                |),
                                                [
                                                  M.rust_cast
                                                    (M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path "bytes::bytes::Bytes",
                                                        "len",
                                                        []
                                                      |),
                                                      [
                                                        M.call_closure (|
                                                          M.get_trait_method (|
                                                            "core::ops::deref::Deref",
                                                            Ty.path
                                                              "alloy_primitives::bytes_::Bytes",
                                                            [],
                                                            "deref",
                                                            []
                                                          |),
                                                          [ initcode ]
                                                        |)
                                                      ]
                                                    |));
                                                  M.read (|
                                                    M.get_constant (|
                                                      "revm_interpreter::gas::constants::KECCAK256WORD"
                                                    |)
                                                  |)
                                                ]
                                              |)
                                            |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ0_0 :=
                                                    M.SubPointer.get_struct_tuple_field (|
                                                      γ,
                                                      "core::option::Option::Some",
                                                      0
                                                    |) in
                                                  let gas_used := M.copy (| γ0_0 |) in
                                                  M.match_operator (|
                                                    M.alloc (| Value.Tuple [] |),
                                                    [
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (let γ :=
                                                            M.use
                                                              (M.alloc (|
                                                                UnOp.not (|
                                                                  M.call_closure (|
                                                                    M.get_associated_function (|
                                                                      Ty.path
                                                                        "revm_interpreter::gas::Gas",
                                                                      "record_cost",
                                                                      []
                                                                    |),
                                                                    [
                                                                      M.SubPointer.get_struct_record_field (|
                                                                        M.read (| interpreter |),
                                                                        "revm_interpreter::interpreter::Interpreter",
                                                                        "gas"
                                                                      |);
                                                                      M.read (| gas_used |)
                                                                    ]
                                                                  |)
                                                                |)
                                                              |)) in
                                                          let _ :=
                                                            M.is_constant_or_break_match (|
                                                              M.read (| γ |),
                                                              Value.Bool true
                                                            |) in
                                                          M.alloc (|
                                                            M.never_to_any (|
                                                              M.read (|
                                                                let~ _ :=
                                                                  M.write (|
                                                                    M.SubPointer.get_struct_record_field (|
                                                                      M.read (| interpreter |),
                                                                      "revm_interpreter::interpreter::Interpreter",
                                                                      "instruction_result"
                                                                    |),
                                                                    Value.StructTuple
                                                                      "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                                      []
                                                                  |) in
                                                                M.return_ (| Value.Tuple [] |)
                                                              |)
                                                            |)
                                                          |)));
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (M.alloc (| Value.Tuple [] |)))
                                                    ]
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let _ :=
                                                    M.is_struct_tuple (|
                                                      γ,
                                                      "core::option::Option::None"
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)))
                                            ]
                                          |) in
                                        M.match_operator (|
                                          M.alloc (|
                                            M.call_closure (|
                                              M.get_associated_function (|
                                                Ty.path "revm_primitives::bytecode::eof::Eof",
                                                "decode",
                                                []
                                              |),
                                              [
                                                M.call_closure (|
                                                  M.get_trait_method (|
                                                    "core::clone::Clone",
                                                    Ty.path "alloy_primitives::bytes_::Bytes",
                                                    [],
                                                    "clone",
                                                    []
                                                  |),
                                                  [ initcode ]
                                                |)
                                              ]
                                            |)
                                          |),
                                          [
                                            fun γ =>
                                              ltac:(M.monadic
                                                (let γ0_0 :=
                                                  M.SubPointer.get_struct_tuple_field (|
                                                    γ,
                                                    "core::result::Result::Ok",
                                                    0
                                                  |) in
                                                let eof := M.copy (| γ0_0 |) in
                                                let~ _ :=
                                                  M.match_operator (|
                                                    M.alloc (| Value.Tuple [] |),
                                                    [
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (let γ :=
                                                            M.use
                                                              (M.alloc (|
                                                                UnOp.not (|
                                                                  M.read (|
                                                                    M.SubPointer.get_struct_record_field (|
                                                                      M.SubPointer.get_struct_record_field (|
                                                                        eof,
                                                                        "revm_primitives::bytecode::eof::Eof",
                                                                        "body"
                                                                      |),
                                                                      "revm_primitives::bytecode::eof::body::EofBody",
                                                                      "is_data_filled"
                                                                    |)
                                                                  |)
                                                                |)
                                                              |)) in
                                                          let _ :=
                                                            M.is_constant_or_break_match (|
                                                              M.read (| γ |),
                                                              Value.Bool true
                                                            |) in
                                                          M.alloc (|
                                                            M.never_to_any (|
                                                              M.read (|
                                                                let~ _ :=
                                                                  M.match_operator (|
                                                                    M.alloc (|
                                                                      M.call_closure (|
                                                                        M.get_associated_function (|
                                                                          Ty.path
                                                                            "revm_interpreter::interpreter::stack::Stack",
                                                                          "push",
                                                                          []
                                                                        |),
                                                                        [
                                                                          M.SubPointer.get_struct_record_field (|
                                                                            M.read (|
                                                                              interpreter
                                                                            |),
                                                                            "revm_interpreter::interpreter::Interpreter",
                                                                            "stack"
                                                                          |);
                                                                          M.read (|
                                                                            M.get_constant (|
                                                                              "ruint::ZERO"
                                                                            |)
                                                                          |)
                                                                        ]
                                                                      |)
                                                                    |),
                                                                    [
                                                                      fun γ =>
                                                                        ltac:(M.monadic
                                                                          (let γ0_0 :=
                                                                            M.SubPointer.get_struct_tuple_field (|
                                                                              γ,
                                                                              "core::result::Result::Ok",
                                                                              0
                                                                            |) in
                                                                          M.alloc (|
                                                                            Value.Tuple []
                                                                          |)));
                                                                      fun γ =>
                                                                        ltac:(M.monadic
                                                                          (let γ0_0 :=
                                                                            M.SubPointer.get_struct_tuple_field (|
                                                                              γ,
                                                                              "core::result::Result::Err",
                                                                              0
                                                                            |) in
                                                                          let e :=
                                                                            M.copy (| γ0_0 |) in
                                                                          M.alloc (|
                                                                            M.never_to_any (|
                                                                              M.read (|
                                                                                let~ _ :=
                                                                                  M.write (|
                                                                                    M.SubPointer.get_struct_record_field (|
                                                                                      M.read (|
                                                                                        interpreter
                                                                                      |),
                                                                                      "revm_interpreter::interpreter::Interpreter",
                                                                                      "instruction_result"
                                                                                    |),
                                                                                    M.read (| e |)
                                                                                  |) in
                                                                                M.return_ (|
                                                                                  Value.Tuple []
                                                                                |)
                                                                              |)
                                                                            |)
                                                                          |)))
                                                                    ]
                                                                  |) in
                                                                M.return_ (| Value.Tuple [] |)
                                                              |)
                                                            |)
                                                          |)));
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (M.alloc (| Value.Tuple [] |)))
                                                    ]
                                                  |) in
                                                let~ _ :=
                                                  M.match_operator (|
                                                    M.alloc (| Value.Tuple [] |),
                                                    [
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (let γ :=
                                                            M.use
                                                              (M.alloc (|
                                                                M.call_closure (|
                                                                  M.get_associated_function (|
                                                                    Ty.apply
                                                                      (Ty.path
                                                                        "core::result::Result")
                                                                      []
                                                                      [
                                                                        Ty.tuple [];
                                                                        Ty.path
                                                                          "revm_interpreter::interpreter::analysis::EofError"
                                                                      ],
                                                                    "is_err",
                                                                    []
                                                                  |),
                                                                  [
                                                                    M.alloc (|
                                                                      M.call_closure (|
                                                                        M.get_function (|
                                                                          "revm_interpreter::interpreter::analysis::validate_eof",
                                                                          []
                                                                        |),
                                                                        [ eof ]
                                                                      |)
                                                                    |)
                                                                  ]
                                                                |)
                                                              |)) in
                                                          let _ :=
                                                            M.is_constant_or_break_match (|
                                                              M.read (| γ |),
                                                              Value.Bool true
                                                            |) in
                                                          M.alloc (|
                                                            M.never_to_any (|
                                                              M.read (|
                                                                let~ _ :=
                                                                  M.match_operator (|
                                                                    M.alloc (|
                                                                      M.call_closure (|
                                                                        M.get_associated_function (|
                                                                          Ty.path
                                                                            "revm_interpreter::interpreter::stack::Stack",
                                                                          "push",
                                                                          []
                                                                        |),
                                                                        [
                                                                          M.SubPointer.get_struct_record_field (|
                                                                            M.read (|
                                                                              interpreter
                                                                            |),
                                                                            "revm_interpreter::interpreter::Interpreter",
                                                                            "stack"
                                                                          |);
                                                                          M.read (|
                                                                            M.get_constant (|
                                                                              "ruint::ZERO"
                                                                            |)
                                                                          |)
                                                                        ]
                                                                      |)
                                                                    |),
                                                                    [
                                                                      fun γ =>
                                                                        ltac:(M.monadic
                                                                          (let γ0_0 :=
                                                                            M.SubPointer.get_struct_tuple_field (|
                                                                              γ,
                                                                              "core::result::Result::Ok",
                                                                              0
                                                                            |) in
                                                                          M.alloc (|
                                                                            Value.Tuple []
                                                                          |)));
                                                                      fun γ =>
                                                                        ltac:(M.monadic
                                                                          (let γ0_0 :=
                                                                            M.SubPointer.get_struct_tuple_field (|
                                                                              γ,
                                                                              "core::result::Result::Err",
                                                                              0
                                                                            |) in
                                                                          let e :=
                                                                            M.copy (| γ0_0 |) in
                                                                          M.alloc (|
                                                                            M.never_to_any (|
                                                                              M.read (|
                                                                                let~ _ :=
                                                                                  M.write (|
                                                                                    M.SubPointer.get_struct_record_field (|
                                                                                      M.read (|
                                                                                        interpreter
                                                                                      |),
                                                                                      "revm_interpreter::interpreter::Interpreter",
                                                                                      "instruction_result"
                                                                                    |),
                                                                                    M.read (| e |)
                                                                                  |) in
                                                                                M.return_ (|
                                                                                  Value.Tuple []
                                                                                |)
                                                                              |)
                                                                            |)
                                                                          |)))
                                                                    ]
                                                                  |) in
                                                                M.return_ (| Value.Tuple [] |)
                                                              |)
                                                            |)
                                                          |)));
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (M.alloc (| Value.Tuple [] |)))
                                                    ]
                                                  |) in
                                                let~ created_address :=
                                                  M.alloc (|
                                                    M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path
                                                          "alloy_primitives::bits::address::Address",
                                                        "create2",
                                                        [
                                                          Ty.apply
                                                            (Ty.path "array")
                                                            [ Value.Integer IntegerKind.Usize 32 ]
                                                            [ Ty.path "u8" ];
                                                          Ty.apply
                                                            (Ty.path
                                                              "alloy_primitives::bits::fixed::FixedBytes")
                                                            [ Value.Integer IntegerKind.Usize 32 ]
                                                            []
                                                        ]
                                                      |),
                                                      [
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.SubPointer.get_struct_record_field (|
                                                            M.read (| interpreter |),
                                                            "revm_interpreter::interpreter::Interpreter",
                                                            "contract"
                                                          |),
                                                          "revm_interpreter::interpreter::contract::Contract",
                                                          "caller"
                                                        |);
                                                        M.call_closure (|
                                                          M.get_associated_function (|
                                                            Ty.apply
                                                              (Ty.path "ruint::Uint")
                                                              [
                                                                Value.Integer IntegerKind.Usize 256;
                                                                Value.Integer IntegerKind.Usize 4
                                                              ]
                                                              [],
                                                            "to_be_bytes",
                                                            []
                                                          |),
                                                          [ salt ]
                                                        |);
                                                        M.read (| tx_initcode_hash |)
                                                      ]
                                                    |)
                                                  |) in
                                                let~ gas_limit :=
                                                  M.alloc (|
                                                    M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path "revm_interpreter::gas::Gas",
                                                        "remaining",
                                                        []
                                                      |),
                                                      [
                                                        M.call_closure (|
                                                          M.get_associated_function (|
                                                            Ty.path
                                                              "revm_interpreter::interpreter::Interpreter",
                                                            "gas",
                                                            []
                                                          |),
                                                          [ M.read (| interpreter |) ]
                                                        |)
                                                      ]
                                                    |)
                                                  |) in
                                                let~ _ :=
                                                  M.match_operator (|
                                                    M.alloc (| Value.Tuple [] |),
                                                    [
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (let γ :=
                                                            M.use
                                                              (M.alloc (|
                                                                UnOp.not (|
                                                                  M.call_closure (|
                                                                    M.get_associated_function (|
                                                                      Ty.path
                                                                        "revm_interpreter::gas::Gas",
                                                                      "record_cost",
                                                                      []
                                                                    |),
                                                                    [
                                                                      M.SubPointer.get_struct_record_field (|
                                                                        M.read (| interpreter |),
                                                                        "revm_interpreter::interpreter::Interpreter",
                                                                        "gas"
                                                                      |);
                                                                      M.read (| gas_limit |)
                                                                    ]
                                                                  |)
                                                                |)
                                                              |)) in
                                                          let _ :=
                                                            M.is_constant_or_break_match (|
                                                              M.read (| γ |),
                                                              Value.Bool true
                                                            |) in
                                                          M.alloc (|
                                                            M.never_to_any (|
                                                              M.read (|
                                                                let~ _ :=
                                                                  M.write (|
                                                                    M.SubPointer.get_struct_record_field (|
                                                                      M.read (| interpreter |),
                                                                      "revm_interpreter::interpreter::Interpreter",
                                                                      "instruction_result"
                                                                    |),
                                                                    Value.StructTuple
                                                                      "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                                      []
                                                                  |) in
                                                                M.return_ (| Value.Tuple [] |)
                                                              |)
                                                            |)
                                                          |)));
                                                      fun γ =>
                                                        ltac:(M.monadic
                                                          (M.alloc (| Value.Tuple [] |)))
                                                    ]
                                                  |) in
                                                let~ _ :=
                                                  M.write (|
                                                    M.SubPointer.get_struct_record_field (|
                                                      M.read (| interpreter |),
                                                      "revm_interpreter::interpreter::Interpreter",
                                                      "next_action"
                                                    |),
                                                    Value.StructRecord
                                                      "revm_interpreter::interpreter_action::InterpreterAction::EOFCreate"
                                                      [
                                                        ("inputs",
                                                          M.call_closure (|
                                                            M.get_associated_function (|
                                                              Ty.apply
                                                                (Ty.path "alloc::boxed::Box")
                                                                []
                                                                [
                                                                  Ty.path
                                                                    "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput";
                                                                  Ty.path "alloc::alloc::Global"
                                                                ],
                                                              "new",
                                                              []
                                                            |),
                                                            [
                                                              M.call_closure (|
                                                                M.get_associated_function (|
                                                                  Ty.path
                                                                    "revm_interpreter::interpreter_action::eof_create_inputs::EOFCreateInput",
                                                                  "new",
                                                                  []
                                                                |),
                                                                [
                                                                  M.read (|
                                                                    M.SubPointer.get_struct_record_field (|
                                                                      M.SubPointer.get_struct_record_field (|
                                                                        M.read (| interpreter |),
                                                                        "revm_interpreter::interpreter::Interpreter",
                                                                        "contract"
                                                                      |),
                                                                      "revm_interpreter::interpreter::contract::Contract",
                                                                      "target_address"
                                                                    |)
                                                                  |);
                                                                  M.read (| created_address |);
                                                                  M.read (| value |);
                                                                  M.read (| eof |);
                                                                  M.read (| gas_limit |);
                                                                  M.read (| return_range |)
                                                                ]
                                                              |)
                                                            ]
                                                          |))
                                                      ]
                                                  |) in
                                                let~ _ :=
                                                  M.write (|
                                                    M.SubPointer.get_struct_record_field (|
                                                      M.read (| interpreter |),
                                                      "revm_interpreter::interpreter::Interpreter",
                                                      "instruction_result"
                                                    |),
                                                    Value.StructTuple
                                                      "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                                      []
                                                  |) in
                                                M.alloc (| Value.Tuple [] |)))
                                          ]
                                        |)))
                                  ]
                                |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_txcreate :
      M.IsFunction "revm_interpreter::instructions::contract::txcreate" txcreate.
    
    (*
    pub fn return_contract<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
        require_init_eof!(interpreter);
        let deploy_container_index = unsafe { read_u16(interpreter.instruction_pointer) };
        pop!(interpreter, aux_data_offset, aux_data_size);
        let aux_data_size = as_usize_or_fail!(interpreter, aux_data_size);
        // important: offset must be ignored if len is zeros
        let container = interpreter
            .eof()
            .expect("EOF is set")
            .body
            .container_section
            .get(deploy_container_index as usize)
            .expect("EOF is checked");
    
        // convert to EOF so we can check data section size.
        let new_eof = Eof::decode(container.clone()).expect("Container is verified");
    
        let aux_slice = if aux_data_size != 0 {
            let aux_data_offset = as_usize_or_fail!(interpreter, aux_data_offset);
            resize_memory!(interpreter, aux_data_offset, aux_data_size);
    
            interpreter
                .shared_memory
                .slice(aux_data_offset, aux_data_size)
        } else {
            &[]
        };
    
        let new_data_size = new_eof.body.data_section.len() + aux_slice.len();
        if new_data_size > 0xFFFF {
            // aux data is too big
            interpreter.instruction_result = InstructionResult::FatalExternalError;
            return;
        }
        if new_data_size < new_eof.header.data_size as usize {
            // aux data is too small
            interpreter.instruction_result = InstructionResult::FatalExternalError;
            return;
        }
    
        // append data bytes
        let output = [new_eof.raw(), aux_slice].concat().into();
    
        let result = InstructionResult::ReturnContract;
        interpreter.instruction_result = result;
        interpreter.next_action = crate::InterpreterAction::Return {
            result: InterpreterResult {
                output,
                gas: interpreter.gas,
                result,
            },
        };
    }
    *)
    Definition return_contract (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H ], [ interpreter; _host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let _host := M.alloc (| _host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.read (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "is_eof_init"
                                    |)
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::ReturnContractInNotInitEOF"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ deploy_container_index :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (| "revm_interpreter::instructions::utility::read_u16", [] |),
                      [
                        M.read (|
                          M.SubPointer.get_struct_record_field (|
                            M.read (| interpreter |),
                            "revm_interpreter::interpreter::Interpreter",
                            "instruction_pointer"
                          |)
                        |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 2
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop2_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |),
                  [
                    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 aux_data_offset := M.copy (| γ0_0 |) in
                        let aux_data_size := M.copy (| γ0_1 |) in
                        let~ aux_data_size :=
                          M.copy (|
                            let~ x :=
                              M.alloc (|
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "ruint::Uint")
                                      [
                                        Value.Integer IntegerKind.Usize 256;
                                        Value.Integer IntegerKind.Usize 4
                                      ]
                                      [],
                                    "as_limbs",
                                    []
                                  |),
                                  [ aux_data_size ]
                                |)
                              |) in
                            let~ _ :=
                              M.match_operator (|
                                M.alloc (| Value.Tuple [] |),
                                [
                                  fun γ =>
                                    ltac:(M.monadic
                                      (let γ :=
                                        M.use
                                          (M.alloc (|
                                            LogicalOp.or (|
                                              LogicalOp.or (|
                                                BinOp.ne (|
                                                  M.read (|
                                                    M.SubPointer.get_array_field (|
                                                      M.read (| x |),
                                                      M.alloc (|
                                                        Value.Integer IntegerKind.Usize 1
                                                      |)
                                                    |)
                                                  |),
                                                  Value.Integer IntegerKind.U64 0
                                                |),
                                                ltac:(M.monadic
                                                  (BinOp.ne (|
                                                    M.read (|
                                                      M.SubPointer.get_array_field (|
                                                        M.read (| x |),
                                                        M.alloc (|
                                                          Value.Integer IntegerKind.Usize 2
                                                        |)
                                                      |)
                                                    |),
                                                    Value.Integer IntegerKind.U64 0
                                                  |)))
                                              |),
                                              ltac:(M.monadic
                                                (BinOp.ne (|
                                                  M.read (|
                                                    M.SubPointer.get_array_field (|
                                                      M.read (| x |),
                                                      M.alloc (|
                                                        Value.Integer IntegerKind.Usize 3
                                                      |)
                                                    |)
                                                  |),
                                                  Value.Integer IntegerKind.U64 0
                                                |)))
                                            |)
                                          |)) in
                                      let _ :=
                                        M.is_constant_or_break_match (|
                                          M.read (| γ |),
                                          Value.Bool true
                                        |) in
                                      M.alloc (|
                                        M.never_to_any (|
                                          M.read (|
                                            let~ _ :=
                                              M.write (|
                                                M.SubPointer.get_struct_record_field (|
                                                  M.read (| interpreter |),
                                                  "revm_interpreter::interpreter::Interpreter",
                                                  "instruction_result"
                                                |),
                                                Value.StructTuple
                                                  "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG"
                                                  []
                                              |) in
                                            M.return_ (| Value.Tuple [] |)
                                          |)
                                        |)
                                      |)));
                                  fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                ]
                              |) in
                            M.match_operator (|
                              M.alloc (|
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::convert::TryFrom",
                                    Ty.path "usize",
                                    [ Ty.path "u64" ],
                                    "try_from",
                                    []
                                  |),
                                  [
                                    M.read (|
                                      M.SubPointer.get_array_field (|
                                        M.read (| x |),
                                        M.alloc (| Value.Integer IntegerKind.Usize 0 |)
                                      |)
                                    |)
                                  ]
                                |)
                              |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::result::Result::Ok",
                                        0
                                      |) in
                                    let val := M.copy (| γ0_0 |) in
                                    val))
                              ]
                            |)
                          |) in
                        let~ container :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "core::option::Option")
                                  []
                                  [
                                    Ty.apply
                                      (Ty.path "&")
                                      []
                                      [ Ty.path "alloy_primitives::bytes_::Bytes" ]
                                  ],
                                "expect",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "slice")
                                      []
                                      [ Ty.path "alloy_primitives::bytes_::Bytes" ],
                                    "get",
                                    [ Ty.path "usize" ]
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::deref::Deref",
                                        Ty.apply
                                          (Ty.path "alloc::vec::Vec")
                                          []
                                          [
                                            Ty.path "alloy_primitives::bytes_::Bytes";
                                            Ty.path "alloc::alloc::Global"
                                          ],
                                        [],
                                        "deref",
                                        []
                                      |),
                                      [
                                        M.SubPointer.get_struct_record_field (|
                                          M.SubPointer.get_struct_record_field (|
                                            M.call_closure (|
                                              M.get_associated_function (|
                                                Ty.apply
                                                  (Ty.path "core::option::Option")
                                                  []
                                                  [
                                                    Ty.apply
                                                      (Ty.path "&")
                                                      []
                                                      [
                                                        Ty.path
                                                          "revm_primitives::bytecode::eof::Eof"
                                                      ]
                                                  ],
                                                "expect",
                                                []
                                              |),
                                              [
                                                M.call_closure (|
                                                  M.get_associated_function (|
                                                    Ty.path
                                                      "revm_interpreter::interpreter::Interpreter",
                                                    "eof",
                                                    []
                                                  |),
                                                  [ M.read (| interpreter |) ]
                                                |);
                                                M.read (| Value.String "EOF is set" |)
                                              ]
                                            |),
                                            "revm_primitives::bytecode::eof::Eof",
                                            "body"
                                          |),
                                          "revm_primitives::bytecode::eof::body::EofBody",
                                          "container_section"
                                        |)
                                      ]
                                    |);
                                    M.rust_cast (M.read (| deploy_container_index |))
                                  ]
                                |);
                                M.read (| Value.String "EOF is checked" |)
                              ]
                            |)
                          |) in
                        let~ new_eof :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "core::result::Result")
                                  []
                                  [
                                    Ty.path "revm_primitives::bytecode::eof::Eof";
                                    Ty.path "revm_primitives::bytecode::eof::EofDecodeError"
                                  ],
                                "expect",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.path "revm_primitives::bytecode::eof::Eof",
                                    "decode",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::clone::Clone",
                                        Ty.path "alloy_primitives::bytes_::Bytes",
                                        [],
                                        "clone",
                                        []
                                      |),
                                      [ M.read (| container |) ]
                                    |)
                                  ]
                                |);
                                M.read (| Value.String "Container is verified" |)
                              ]
                            |)
                          |) in
                        let~ aux_slice :=
                          M.copy (|
                            M.match_operator (|
                              M.alloc (| Value.Tuple [] |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ :=
                                      M.use
                                        (M.alloc (|
                                          BinOp.ne (|
                                            M.read (| aux_data_size |),
                                            Value.Integer IntegerKind.Usize 0
                                          |)
                                        |)) in
                                    let _ :=
                                      M.is_constant_or_break_match (|
                                        M.read (| γ |),
                                        Value.Bool true
                                      |) in
                                    let~ aux_data_offset :=
                                      M.copy (|
                                        let~ x :=
                                          M.alloc (|
                                            M.call_closure (|
                                              M.get_associated_function (|
                                                Ty.apply
                                                  (Ty.path "ruint::Uint")
                                                  [
                                                    Value.Integer IntegerKind.Usize 256;
                                                    Value.Integer IntegerKind.Usize 4
                                                  ]
                                                  [],
                                                "as_limbs",
                                                []
                                              |),
                                              [ aux_data_offset ]
                                            |)
                                          |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (| Value.Tuple [] |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ :=
                                                    M.use
                                                      (M.alloc (|
                                                        LogicalOp.or (|
                                                          LogicalOp.or (|
                                                            BinOp.ne (|
                                                              M.read (|
                                                                M.SubPointer.get_array_field (|
                                                                  M.read (| x |),
                                                                  M.alloc (|
                                                                    Value.Integer
                                                                      IntegerKind.Usize
                                                                      1
                                                                  |)
                                                                |)
                                                              |),
                                                              Value.Integer IntegerKind.U64 0
                                                            |),
                                                            ltac:(M.monadic
                                                              (BinOp.ne (|
                                                                M.read (|
                                                                  M.SubPointer.get_array_field (|
                                                                    M.read (| x |),
                                                                    M.alloc (|
                                                                      Value.Integer
                                                                        IntegerKind.Usize
                                                                        2
                                                                    |)
                                                                  |)
                                                                |),
                                                                Value.Integer IntegerKind.U64 0
                                                              |)))
                                                          |),
                                                          ltac:(M.monadic
                                                            (BinOp.ne (|
                                                              M.read (|
                                                                M.SubPointer.get_array_field (|
                                                                  M.read (| x |),
                                                                  M.alloc (|
                                                                    Value.Integer
                                                                      IntegerKind.Usize
                                                                      3
                                                                  |)
                                                                |)
                                                              |),
                                                              Value.Integer IntegerKind.U64 0
                                                            |)))
                                                        |)
                                                      |)) in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |) in
                                        M.match_operator (|
                                          M.alloc (|
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "core::convert::TryFrom",
                                                Ty.path "usize",
                                                [ Ty.path "u64" ],
                                                "try_from",
                                                []
                                              |),
                                              [
                                                M.read (|
                                                  M.SubPointer.get_array_field (|
                                                    M.read (| x |),
                                                    M.alloc (| Value.Integer IntegerKind.Usize 0 |)
                                                  |)
                                                |)
                                              ]
                                            |)
                                          |),
                                          [
                                            fun γ =>
                                              ltac:(M.monadic
                                                (let γ0_0 :=
                                                  M.SubPointer.get_struct_tuple_field (|
                                                    γ,
                                                    "core::result::Result::Ok",
                                                    0
                                                  |) in
                                                let val := M.copy (| γ0_0 |) in
                                                val))
                                          ]
                                        |)
                                      |) in
                                    let~ new_size :=
                                      M.alloc (|
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.path "usize",
                                            "saturating_add",
                                            []
                                          |),
                                          [ M.read (| aux_data_offset |); M.read (| aux_data_size |)
                                          ]
                                        |)
                                      |) in
                                    let~ _ :=
                                      M.match_operator (|
                                        M.alloc (| Value.Tuple [] |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ :=
                                                M.use
                                                  (M.alloc (|
                                                    BinOp.gt (|
                                                      M.read (| new_size |),
                                                      M.call_closure (|
                                                        M.get_associated_function (|
                                                          Ty.path
                                                            "revm_interpreter::interpreter::shared_memory::SharedMemory",
                                                          "len",
                                                          []
                                                        |),
                                                        [
                                                          M.SubPointer.get_struct_record_field (|
                                                            M.read (| interpreter |),
                                                            "revm_interpreter::interpreter::Interpreter",
                                                            "shared_memory"
                                                          |)
                                                        ]
                                                      |)
                                                    |)
                                                  |)) in
                                              let _ :=
                                                M.is_constant_or_break_match (|
                                                  M.read (| γ |),
                                                  Value.Bool true
                                                |) in
                                              M.match_operator (|
                                                M.alloc (| Value.Tuple [] |),
                                                [
                                                  fun γ =>
                                                    ltac:(M.monadic
                                                      (let γ :=
                                                        M.use
                                                          (M.alloc (|
                                                            UnOp.not (|
                                                              M.call_closure (|
                                                                M.get_function (|
                                                                  "revm_interpreter::interpreter::resize_memory",
                                                                  []
                                                                |),
                                                                [
                                                                  M.SubPointer.get_struct_record_field (|
                                                                    M.read (| interpreter |),
                                                                    "revm_interpreter::interpreter::Interpreter",
                                                                    "shared_memory"
                                                                  |);
                                                                  M.SubPointer.get_struct_record_field (|
                                                                    M.read (| interpreter |),
                                                                    "revm_interpreter::interpreter::Interpreter",
                                                                    "gas"
                                                                  |);
                                                                  M.read (| new_size |)
                                                                ]
                                                              |)
                                                            |)
                                                          |)) in
                                                      let _ :=
                                                        M.is_constant_or_break_match (|
                                                          M.read (| γ |),
                                                          Value.Bool true
                                                        |) in
                                                      M.alloc (|
                                                        M.never_to_any (|
                                                          M.read (|
                                                            let~ _ :=
                                                              M.write (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "instruction_result"
                                                                |),
                                                                Value.StructTuple
                                                                  "revm_interpreter::instruction_result::InstructionResult::MemoryOOG"
                                                                  []
                                                              |) in
                                                            M.return_ (| Value.Tuple [] |)
                                                          |)
                                                        |)
                                                      |)));
                                                  fun γ =>
                                                    ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                                ]
                                              |)));
                                          fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                        ]
                                      |) in
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.path
                                            "revm_interpreter::interpreter::shared_memory::SharedMemory",
                                          "slice",
                                          []
                                        |),
                                        [
                                          M.SubPointer.get_struct_record_field (|
                                            M.read (| interpreter |),
                                            "revm_interpreter::interpreter::Interpreter",
                                            "shared_memory"
                                          |);
                                          M.read (| aux_data_offset |);
                                          M.read (| aux_data_size |)
                                        ]
                                      |)
                                    |)));
                                fun γ =>
                                  ltac:(M.monadic (M.alloc (| M.alloc (| Value.Array [] |) |)))
                              ]
                            |)
                          |) in
                        let~ new_data_size :=
                          M.alloc (|
                            BinOp.Wrap.add (|
                              M.call_closure (|
                                M.get_associated_function (|
                                  Ty.path "bytes::bytes::Bytes",
                                  "len",
                                  []
                                |),
                                [
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "core::ops::deref::Deref",
                                      Ty.path "alloy_primitives::bytes_::Bytes",
                                      [],
                                      "deref",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.SubPointer.get_struct_record_field (|
                                          new_eof,
                                          "revm_primitives::bytecode::eof::Eof",
                                          "body"
                                        |),
                                        "revm_primitives::bytecode::eof::body::EofBody",
                                        "data_section"
                                      |)
                                    ]
                                  |)
                                ]
                              |),
                              M.call_closure (|
                                M.get_associated_function (|
                                  Ty.apply (Ty.path "slice") [] [ Ty.path "u8" ],
                                  "len",
                                  []
                                |),
                                [ M.read (| aux_slice |) ]
                              |)
                            |)
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.gt (|
                                          M.read (| new_data_size |),
                                          Value.Integer IntegerKind.Usize 65535
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::FatalExternalError"
                                              []
                                          |) in
                                        M.return_ (| Value.Tuple [] |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.lt (|
                                          M.read (| new_data_size |),
                                          M.rust_cast
                                            (M.read (|
                                              M.SubPointer.get_struct_record_field (|
                                                M.SubPointer.get_struct_record_field (|
                                                  new_eof,
                                                  "revm_primitives::bytecode::eof::Eof",
                                                  "header"
                                                |),
                                                "revm_primitives::bytecode::eof::header::EofHeader",
                                                "data_size"
                                              |)
                                            |))
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::FatalExternalError"
                                              []
                                          |) in
                                        M.return_ (| Value.Tuple [] |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ output :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "core::convert::Into",
                                Ty.apply
                                  (Ty.path "alloc::vec::Vec")
                                  []
                                  [ Ty.path "u8"; Ty.path "alloc::alloc::Global" ],
                                [ Ty.path "alloy_primitives::bytes_::Bytes" ],
                                "into",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "slice")
                                      []
                                      [
                                        Ty.apply
                                          (Ty.path "&")
                                          []
                                          [ Ty.apply (Ty.path "slice") [] [ Ty.path "u8" ] ]
                                      ],
                                    "concat",
                                    [ Ty.path "u8" ]
                                  |),
                                  [
                                    M.alloc (|
                                      Value.Array
                                        [
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::deref::Deref",
                                              Ty.path "bytes::bytes::Bytes",
                                              [],
                                              "deref",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_trait_method (|
                                                  "core::ops::deref::Deref",
                                                  Ty.path "alloy_primitives::bytes_::Bytes",
                                                  [],
                                                  "deref",
                                                  []
                                                |),
                                                [
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.path "revm_primitives::bytecode::eof::Eof",
                                                      "raw",
                                                      []
                                                    |),
                                                    [ new_eof ]
                                                  |)
                                                ]
                                              |)
                                            ]
                                          |);
                                          M.read (| aux_slice |)
                                        ]
                                    |)
                                  ]
                                |)
                              ]
                            |)
                          |) in
                        let~ result :=
                          M.alloc (|
                            Value.StructTuple
                              "revm_interpreter::instruction_result::InstructionResult::ReturnContract"
                              []
                          |) in
                        let~ _ :=
                          M.write (|
                            M.SubPointer.get_struct_record_field (|
                              M.read (| interpreter |),
                              "revm_interpreter::interpreter::Interpreter",
                              "instruction_result"
                            |),
                            M.read (| result |)
                          |) in
                        let~ _ :=
                          M.write (|
                            M.SubPointer.get_struct_record_field (|
                              M.read (| interpreter |),
                              "revm_interpreter::interpreter::Interpreter",
                              "next_action"
                            |),
                            Value.StructRecord
                              "revm_interpreter::interpreter_action::InterpreterAction::Return"
                              [
                                ("result",
                                  Value.StructRecord
                                    "revm_interpreter::interpreter::InterpreterResult"
                                    [
                                      ("output", M.read (| output |));
                                      ("gas",
                                        M.read (|
                                          M.SubPointer.get_struct_record_field (|
                                            M.read (| interpreter |),
                                            "revm_interpreter::interpreter::Interpreter",
                                            "gas"
                                          |)
                                        |));
                                      ("result", M.read (| result |))
                                    ])
                              ]
                          |) in
                        M.alloc (| Value.Tuple [] |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_return_contract :
      M.IsFunction "revm_interpreter::instructions::contract::return_contract" return_contract.
    
    (*
    pub fn extcall_input(interpreter: &mut Interpreter) -> Option<Bytes> {
        pop_ret!(interpreter, input_offset, input_size, None);
    
        let return_memory_offset =
            resize_memory_and_return_range(interpreter, input_offset, input_size)?;
    
        Some(Bytes::copy_from_slice(
            interpreter
                .shared_memory
                .slice_range(return_memory_offset.clone()),
        ))
    }
    *)
    Definition extcall_input (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ interpreter ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 2
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.StructTuple "core::option::Option::None" [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop2_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |),
                  [
                    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 input_offset := M.copy (| γ0_0 |) in
                        let input_size := M.copy (| γ0_1 |) in
                        let~ return_memory_offset :=
                          M.copy (|
                            M.match_operator (|
                              M.alloc (|
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::ops::try_trait::Try",
                                    Ty.apply
                                      (Ty.path "core::option::Option")
                                      []
                                      [
                                        Ty.apply
                                          (Ty.path "core::ops::range::Range")
                                          []
                                          [ Ty.path "usize" ]
                                      ],
                                    [],
                                    "branch",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_function (|
                                        "revm_interpreter::instructions::contract::call_helpers::resize_memory_and_return_range",
                                        []
                                      |),
                                      [
                                        M.read (| interpreter |);
                                        M.read (| input_offset |);
                                        M.read (| input_size |)
                                      ]
                                    |)
                                  ]
                                |)
                              |),
                              [
                                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::option::Option")
                                                  []
                                                  [ Ty.path "alloy_primitives::bytes_::Bytes" ],
                                                [
                                                  Ty.apply
                                                    (Ty.path "core::option::Option")
                                                    []
                                                    [ Ty.path "core::convert::Infallible" ]
                                                ],
                                                "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.StructTuple
                            "core::option::Option::Some"
                            [
                              M.call_closure (|
                                M.get_associated_function (|
                                  Ty.path "alloy_primitives::bytes_::Bytes",
                                  "copy_from_slice",
                                  []
                                |),
                                [
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path
                                        "revm_interpreter::interpreter::shared_memory::SharedMemory",
                                      "slice_range",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "shared_memory"
                                      |);
                                      M.call_closure (|
                                        M.get_trait_method (|
                                          "core::clone::Clone",
                                          Ty.apply
                                            (Ty.path "core::ops::range::Range")
                                            []
                                            [ Ty.path "usize" ],
                                          [],
                                          "clone",
                                          []
                                        |),
                                        [ return_memory_offset ]
                                      |)
                                    ]
                                  |)
                                ]
                              |)
                            ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_extcall_input :
      M.IsFunction "revm_interpreter::instructions::contract::extcall_input" extcall_input.
    
    (*
    pub fn extcall_gas_calc<H: Host + ?Sized>(
        interpreter: &mut Interpreter,
        host: &mut H,
        target: Address,
        transfers_value: bool,
    ) -> Option<u64> {
        let Some(load_result) = host.load_account(target) else {
            interpreter.instruction_result = InstructionResult::FatalExternalError;
            return None;
        };
    
        if load_result.is_cold {
            gas!(interpreter, gas::COLD_ACCOUNT_ACCESS_COST, None);
        }
    
        // TODO(EOF) is_empty should only be checked on delegatecall
        let call_cost = gas::call_cost(
            BerlinSpec::SPEC_ID,
            transfers_value,
            load_result.is_cold,
            load_result.is_empty,
        );
        gas!(interpreter, call_cost, None);
    
        // 7. Calculate the gas available to callee as caller’s
        // remaining gas reduced by max(ceil(gas/64), MIN_RETAINED_GAS) (MIN_RETAINED_GAS is 5000).
        let gas_reduce = max(interpreter.gas.remaining() / 64, 5000);
        let gas_limit = interpreter.gas().remaining().saturating_sub(gas_reduce);
    
        if gas_limit < 2300 {
            interpreter.instruction_result = InstructionResult::CallNotAllowedInsideStatic;
            // TODO(EOF) error;
            // interpreter.instruction_result = InstructionResult::CallGasTooLow;
            return None;
        }
    
        // TODO check remaining gas more then N
    
        gas!(interpreter, gas_limit, None);
        Some(gas_limit)
    }
    *)
    Definition extcall_gas_calc (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H ], [ interpreter; host; target; transfers_value ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          let target := M.alloc (| target |) in
          let transfers_value := M.alloc (| transfers_value |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "revm_interpreter::host::Host",
                        H,
                        [],
                        "load_account",
                        []
                      |),
                      [ M.read (| host |); M.read (| target |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let load_result := M.copy (| γ0_0 |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.SubPointer.get_struct_record_field (|
                                        load_result,
                                        "revm_interpreter::host::LoadAccountResult",
                                        "is_cold"
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  let~ _ :=
                                    M.match_operator (|
                                      M.alloc (| Value.Tuple [] |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ :=
                                              M.use
                                                (M.alloc (|
                                                  UnOp.not (|
                                                    M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path "revm_interpreter::gas::Gas",
                                                        "record_cost",
                                                        []
                                                      |),
                                                      [
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "gas"
                                                        |);
                                                        M.read (|
                                                          M.get_constant (|
                                                            "revm_interpreter::gas::constants::COLD_ACCOUNT_ACCESS_COST"
                                                          |)
                                                        |)
                                                      ]
                                                    |)
                                                  |)
                                                |)) in
                                            let _ :=
                                              M.is_constant_or_break_match (|
                                                M.read (| γ |),
                                                Value.Bool true
                                              |) in
                                            M.alloc (|
                                              M.never_to_any (|
                                                M.read (|
                                                  let~ _ :=
                                                    M.write (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.read (| interpreter |),
                                                        "revm_interpreter::interpreter::Interpreter",
                                                        "instruction_result"
                                                      |),
                                                      Value.StructTuple
                                                        "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                        []
                                                    |) in
                                                  M.return_ (|
                                                    Value.StructTuple
                                                      "core::option::Option::None"
                                                      []
                                                  |)
                                                |)
                                              |)
                                            |)));
                                        fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                      ]
                                    |) in
                                  M.alloc (| Value.Tuple [] |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ call_cost :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (| "revm_interpreter::gas::calc::call_cost", [] |),
                              [
                                M.read (|
                                  M.get_constant (|
                                    "revm_primitives::specification::Spec::SPEC_ID"
                                  |)
                                |);
                                M.read (| transfers_value |);
                                M.read (|
                                  M.SubPointer.get_struct_record_field (|
                                    load_result,
                                    "revm_interpreter::host::LoadAccountResult",
                                    "is_cold"
                                  |)
                                |);
                                M.read (|
                                  M.SubPointer.get_struct_record_field (|
                                    load_result,
                                    "revm_interpreter::host::LoadAccountResult",
                                    "is_empty"
                                  |)
                                |)
                              ]
                            |)
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        UnOp.not (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.path "revm_interpreter::gas::Gas",
                                              "record_cost",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| interpreter |),
                                                "revm_interpreter::interpreter::Interpreter",
                                                "gas"
                                              |);
                                              M.read (| call_cost |)
                                            ]
                                          |)
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                              []
                                          |) in
                                        M.return_ (|
                                          Value.StructTuple "core::option::Option::None" []
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ gas_reduce :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (| "core::cmp::max", [ Ty.path "u64" ] |),
                              [
                                BinOp.Wrap.div (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::gas::Gas",
                                      "remaining",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "gas"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.U64 64
                                |);
                                Value.Integer IntegerKind.U64 5000
                              ]
                            |)
                          |) in
                        let~ gas_limit :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (| Ty.path "u64", "saturating_sub", [] |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.path "revm_interpreter::gas::Gas",
                                    "remaining",
                                    []
                                  |),
                                  [
                                    M.call_closure (|
                                      M.get_associated_function (|
                                        Ty.path "revm_interpreter::interpreter::Interpreter",
                                        "gas",
                                        []
                                      |),
                                      [ M.read (| interpreter |) ]
                                    |)
                                  ]
                                |);
                                M.read (| gas_reduce |)
                              ]
                            |)
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.lt (|
                                          M.read (| gas_limit |),
                                          Value.Integer IntegerKind.U64 2300
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic"
                                              []
                                          |) in
                                        M.return_ (|
                                          Value.StructTuple "core::option::Option::None" []
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        UnOp.not (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.path "revm_interpreter::gas::Gas",
                                              "record_cost",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| interpreter |),
                                                "revm_interpreter::interpreter::Interpreter",
                                                "gas"
                                              |);
                                              M.read (| gas_limit |)
                                            ]
                                          |)
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                              []
                                          |) in
                                        M.return_ (|
                                          Value.StructTuple "core::option::Option::None" []
                                        |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        M.alloc (|
                          Value.StructTuple "core::option::Option::Some" [ M.read (| gas_limit |) ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_extcall_gas_calc :
      M.IsFunction "revm_interpreter::instructions::contract::extcall_gas_calc" extcall_gas_calc.
    
    (*
    pub fn extcall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
        require_eof!(interpreter);
        pop_address!(interpreter, target_address);
    
        // input call
        let Some(input) = extcall_input(interpreter) else {
            return;
        };
    
        pop!(interpreter, value);
        let has_transfer = value != U256::ZERO;
    
        let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, has_transfer) else {
            return;
        };
        // TODO Check if static and value 0
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Call {
            inputs: Box::new(CallInputs {
                input,
                gas_limit,
                target_address,
                caller: interpreter.contract.target_address,
                bytecode_address: target_address,
                value: CallValue::Transfer(value),
                scheme: CallScheme::Call,
                is_static: interpreter.is_static,
                is_eof: true,
                return_memory_offset: 0..0,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition extcall (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H; SPEC ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.read (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "is_eof"
                                    |)
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ target_address :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "alloy_primitives::bits::address::Address",
                        "from_word",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::From",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "from",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "revm_interpreter::instructions::contract::extcall_input",
                        []
                      |),
                      [ M.read (| interpreter |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let input := M.copy (| γ0_0 |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.lt (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.path "revm_interpreter::interpreter::stack::Stack",
                                              "len",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| interpreter |),
                                                "revm_interpreter::interpreter::Interpreter",
                                                "stack"
                                              |)
                                            ]
                                          |),
                                          Value.Integer IntegerKind.Usize 1
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                              []
                                          |) in
                                        M.return_ (| Value.Tuple [] |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ value :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          |) in
                        let~ has_transfer :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "core::cmp::PartialEq",
                                Ty.apply
                                  (Ty.path "ruint::Uint")
                                  [
                                    Value.Integer IntegerKind.Usize 256;
                                    Value.Integer IntegerKind.Usize 4
                                  ]
                                  [],
                                [
                                  Ty.apply
                                    (Ty.path "ruint::Uint")
                                    [
                                      Value.Integer IntegerKind.Usize 256;
                                      Value.Integer IntegerKind.Usize 4
                                    ]
                                    []
                                ],
                                "ne",
                                []
                              |),
                              [ value; M.get_constant (| "ruint::ZERO" |) ]
                            |)
                          |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (|
                                "revm_interpreter::instructions::contract::extcall_gas_calc",
                                [ H ]
                              |),
                              [
                                M.read (| interpreter |);
                                M.read (| host |);
                                M.read (| target_address |);
                                M.read (| has_transfer |)
                              ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let gas_limit := M.copy (| γ0_0 |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "next_action"
                                    |),
                                    Value.StructRecord
                                      "revm_interpreter::interpreter_action::InterpreterAction::Call"
                                      [
                                        ("inputs",
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "alloc::boxed::Box")
                                                []
                                                [
                                                  Ty.path
                                                    "revm_interpreter::interpreter_action::call_inputs::CallInputs";
                                                  Ty.path "alloc::alloc::Global"
                                                ],
                                              "new",
                                              []
                                            |),
                                            [
                                              Value.StructRecord
                                                "revm_interpreter::interpreter_action::call_inputs::CallInputs"
                                                [
                                                  ("input", M.read (| input |));
                                                  ("gas_limit", M.read (| gas_limit |));
                                                  ("target_address", M.read (| target_address |));
                                                  ("caller",
                                                    M.read (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "contract"
                                                        |),
                                                        "revm_interpreter::interpreter::contract::Contract",
                                                        "target_address"
                                                      |)
                                                    |));
                                                  ("bytecode_address", M.read (| target_address |));
                                                  ("value",
                                                    Value.StructTuple
                                                      "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer"
                                                      [ M.read (| value |) ]);
                                                  ("scheme",
                                                    Value.StructTuple
                                                      "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call"
                                                      []);
                                                  ("is_static",
                                                    M.read (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.read (| interpreter |),
                                                        "revm_interpreter::interpreter::Interpreter",
                                                        "is_static"
                                                      |)
                                                    |));
                                                  ("is_eof", Value.Bool true);
                                                  ("return_memory_offset",
                                                    Value.StructRecord
                                                      "core::ops::range::Range"
                                                      [
                                                        ("start",
                                                          Value.Integer IntegerKind.Usize 0);
                                                        ("end_", Value.Integer IntegerKind.Usize 0)
                                                      ])
                                                ]
                                            ]
                                          |))
                                      ]
                                  |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                      []
                                  |) in
                                M.alloc (| Value.Tuple [] |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_extcall :
      M.IsFunction "revm_interpreter::instructions::contract::extcall" extcall.
    
    (*
    pub fn extdcall<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
        require_eof!(interpreter);
        pop_address!(interpreter, target_address);
    
        // input call
        let Some(input) = extcall_input(interpreter) else {
            return;
        };
    
        let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, false) else {
            return;
        };
        // TODO Check if static and value 0
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Call {
            inputs: Box::new(CallInputs {
                input,
                gas_limit,
                target_address,
                caller: interpreter.contract.target_address,
                bytecode_address: target_address,
                value: CallValue::Apparent(interpreter.contract.call_value),
                // TODO(EOF) should be EofDelegateCall?
                scheme: CallScheme::DelegateCall,
                is_static: interpreter.is_static,
                is_eof: true,
                return_memory_offset: 0..0,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition extdcall (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H; SPEC ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.read (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "is_eof"
                                    |)
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ target_address :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "alloy_primitives::bits::address::Address",
                        "from_word",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::From",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "from",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "revm_interpreter::instructions::contract::extcall_input",
                        []
                      |),
                      [ M.read (| interpreter |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let input := M.copy (| γ0_0 |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (|
                                "revm_interpreter::instructions::contract::extcall_gas_calc",
                                [ H ]
                              |),
                              [
                                M.read (| interpreter |);
                                M.read (| host |);
                                M.read (| target_address |);
                                Value.Bool false
                              ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let gas_limit := M.copy (| γ0_0 |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "next_action"
                                    |),
                                    Value.StructRecord
                                      "revm_interpreter::interpreter_action::InterpreterAction::Call"
                                      [
                                        ("inputs",
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "alloc::boxed::Box")
                                                []
                                                [
                                                  Ty.path
                                                    "revm_interpreter::interpreter_action::call_inputs::CallInputs";
                                                  Ty.path "alloc::alloc::Global"
                                                ],
                                              "new",
                                              []
                                            |),
                                            [
                                              Value.StructRecord
                                                "revm_interpreter::interpreter_action::call_inputs::CallInputs"
                                                [
                                                  ("input", M.read (| input |));
                                                  ("gas_limit", M.read (| gas_limit |));
                                                  ("target_address", M.read (| target_address |));
                                                  ("caller",
                                                    M.read (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "contract"
                                                        |),
                                                        "revm_interpreter::interpreter::contract::Contract",
                                                        "target_address"
                                                      |)
                                                    |));
                                                  ("bytecode_address", M.read (| target_address |));
                                                  ("value",
                                                    Value.StructTuple
                                                      "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent"
                                                      [
                                                        M.read (|
                                                          M.SubPointer.get_struct_record_field (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "contract"
                                                            |),
                                                            "revm_interpreter::interpreter::contract::Contract",
                                                            "call_value"
                                                          |)
                                                        |)
                                                      ]);
                                                  ("scheme",
                                                    Value.StructTuple
                                                      "revm_interpreter::interpreter_action::call_inputs::CallScheme::DelegateCall"
                                                      []);
                                                  ("is_static",
                                                    M.read (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.read (| interpreter |),
                                                        "revm_interpreter::interpreter::Interpreter",
                                                        "is_static"
                                                      |)
                                                    |));
                                                  ("is_eof", Value.Bool true);
                                                  ("return_memory_offset",
                                                    Value.StructRecord
                                                      "core::ops::range::Range"
                                                      [
                                                        ("start",
                                                          Value.Integer IntegerKind.Usize 0);
                                                        ("end_", Value.Integer IntegerKind.Usize 0)
                                                      ])
                                                ]
                                            ]
                                          |))
                                      ]
                                  |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                      []
                                  |) in
                                M.alloc (| Value.Tuple [] |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_extdcall :
      M.IsFunction "revm_interpreter::instructions::contract::extdcall" extdcall.
    
    (*
    pub fn extscall<H: Host + ?Sized>(interpreter: &mut Interpreter, host: &mut H) {
        require_eof!(interpreter);
        pop_address!(interpreter, target_address);
    
        // input call
        let Some(input) = extcall_input(interpreter) else {
            return;
        };
    
        let Some(gas_limit) = extcall_gas_calc(interpreter, host, target_address, false) else {
            return;
        };
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Call {
            inputs: Box::new(CallInputs {
                input,
                gas_limit,
                target_address,
                caller: interpreter.contract.target_address,
                bytecode_address: target_address,
                value: CallValue::Transfer(U256::ZERO),
                scheme: CallScheme::Call,
                is_static: interpreter.is_static,
                is_eof: true,
                return_memory_offset: 0..0,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition extscall (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.read (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "is_eof"
                                    |)
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::EOFOpcodeDisabledInLegacy"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ target_address :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "alloy_primitives::bits::address::Address",
                        "from_word",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::From",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "from",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "revm_interpreter::instructions::contract::extcall_input",
                        []
                      |),
                      [ M.read (| interpreter |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let input := M.copy (| γ0_0 |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_function (|
                                "revm_interpreter::instructions::contract::extcall_gas_calc",
                                [ H ]
                              |),
                              [
                                M.read (| interpreter |);
                                M.read (| host |);
                                M.read (| target_address |);
                                Value.Bool false
                              ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let gas_limit := M.copy (| γ0_0 |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "next_action"
                                    |),
                                    Value.StructRecord
                                      "revm_interpreter::interpreter_action::InterpreterAction::Call"
                                      [
                                        ("inputs",
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "alloc::boxed::Box")
                                                []
                                                [
                                                  Ty.path
                                                    "revm_interpreter::interpreter_action::call_inputs::CallInputs";
                                                  Ty.path "alloc::alloc::Global"
                                                ],
                                              "new",
                                              []
                                            |),
                                            [
                                              Value.StructRecord
                                                "revm_interpreter::interpreter_action::call_inputs::CallInputs"
                                                [
                                                  ("input", M.read (| input |));
                                                  ("gas_limit", M.read (| gas_limit |));
                                                  ("target_address", M.read (| target_address |));
                                                  ("caller",
                                                    M.read (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "contract"
                                                        |),
                                                        "revm_interpreter::interpreter::contract::Contract",
                                                        "target_address"
                                                      |)
                                                    |));
                                                  ("bytecode_address", M.read (| target_address |));
                                                  ("value",
                                                    Value.StructTuple
                                                      "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer"
                                                      [
                                                        M.read (|
                                                          M.get_constant (| "ruint::ZERO" |)
                                                        |)
                                                      ]);
                                                  ("scheme",
                                                    Value.StructTuple
                                                      "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call"
                                                      []);
                                                  ("is_static",
                                                    M.read (|
                                                      M.SubPointer.get_struct_record_field (|
                                                        M.read (| interpreter |),
                                                        "revm_interpreter::interpreter::Interpreter",
                                                        "is_static"
                                                      |)
                                                    |));
                                                  ("is_eof", Value.Bool true);
                                                  ("return_memory_offset",
                                                    Value.StructRecord
                                                      "core::ops::range::Range"
                                                      [
                                                        ("start",
                                                          Value.Integer IntegerKind.Usize 0);
                                                        ("end_", Value.Integer IntegerKind.Usize 0)
                                                      ])
                                                ]
                                            ]
                                          |))
                                      ]
                                  |) in
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                      []
                                  |) in
                                M.alloc (| Value.Tuple [] |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_extscall :
      M.IsFunction "revm_interpreter::instructions::contract::extscall" extscall.
    
    (*
    pub fn create<const IS_CREATE2: bool, H: Host + ?Sized, SPEC: Spec>(
        interpreter: &mut Interpreter,
        host: &mut H,
    ) {
        require_non_staticcall!(interpreter);
    
        // EIP-1014: Skinny CREATE2
        if IS_CREATE2 {
            check!(interpreter, PETERSBURG);
        }
    
        pop!(interpreter, value, code_offset, len);
        let len = as_usize_or_fail!(interpreter, len);
    
        let mut code = Bytes::new();
        if len != 0 {
            // EIP-3860: Limit and meter initcode
            if SPEC::enabled(SHANGHAI) {
                // Limit is set as double of max contract bytecode size
                let max_initcode_size = host
                    .env()
                    .cfg
                    .limit_contract_code_size
                    .map(|limit| limit.saturating_mul(2))
                    .unwrap_or(MAX_INITCODE_SIZE);
                if len > max_initcode_size {
                    interpreter.instruction_result = InstructionResult::CreateInitCodeSizeLimit;
                    return;
                }
                gas!(interpreter, gas::initcode_cost(len as u64));
            }
    
            let code_offset = as_usize_or_fail!(interpreter, code_offset);
            resize_memory!(interpreter, code_offset, len);
            code = Bytes::copy_from_slice(interpreter.shared_memory.slice(code_offset, len));
        }
    
        // EIP-1014: Skinny CREATE2
        let scheme = if IS_CREATE2 {
            pop!(interpreter, salt);
            // SAFETY: len is reasonable in size as gas for it is already deducted.
            gas_or_fail!(interpreter, gas::create2_cost(len.try_into().unwrap()));
            CreateScheme::Create2 { salt }
        } else {
            gas!(interpreter, gas::CREATE);
            CreateScheme::Create
        };
    
        let mut gas_limit = interpreter.gas().remaining();
    
        // EIP-150: Gas cost changes for IO-heavy operations
        if SPEC::enabled(TANGERINE) {
            // take remaining gas and deduce l64 part of it.
            gas_limit -= gas_limit / 64
        }
        gas!(interpreter, gas_limit);
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Create {
            inputs: Box::new(CreateInputs {
                caller: interpreter.contract.target_address,
                scheme,
                value,
                init_code: code,
                gas_limit,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition create (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [ IS_CREATE2 ], [ H; SPEC ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.SubPointer.get_struct_record_field (|
                                M.read (| interpreter |),
                                "revm_interpreter::interpreter::Interpreter",
                                "is_static"
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StateChangeDuringStaticCall"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.get_constant (|
                                "revm_interpreter::instructions::contract::create::IS_CREATE2"
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          let~ _ :=
                            M.match_operator (|
                              M.alloc (| Value.Tuple [] |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ :=
                                      M.use
                                        (M.alloc (|
                                          UnOp.not (|
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "revm_primitives::specification::Spec",
                                                SPEC,
                                                [],
                                                "enabled",
                                                []
                                              |),
                                              [
                                                Value.StructTuple
                                                  "revm_primitives::specification::SpecId::PETERSBURG"
                                                  []
                                              ]
                                            |)
                                          |)
                                        |)) in
                                    let _ :=
                                      M.is_constant_or_break_match (|
                                        M.read (| γ |),
                                        Value.Bool true
                                      |) in
                                    M.alloc (|
                                      M.never_to_any (|
                                        M.read (|
                                          let~ _ :=
                                            M.write (|
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| interpreter |),
                                                "revm_interpreter::interpreter::Interpreter",
                                                "instruction_result"
                                              |),
                                              Value.StructTuple
                                                "revm_interpreter::instruction_result::InstructionResult::NotActivated"
                                                []
                                            |) in
                                          M.return_ (| Value.Tuple [] |)
                                        |)
                                      |)
                                    |)));
                                fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                              ]
                            |) in
                          M.alloc (| Value.Tuple [] |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 3
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop3_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |),
                  [
                    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 γ0_2 := M.SubPointer.get_tuple_field (| γ, 2 |) in
                        let value := M.copy (| γ0_0 |) in
                        let code_offset := M.copy (| γ0_1 |) in
                        let len := M.copy (| γ0_2 |) in
                        let~ len :=
                          M.copy (|
                            let~ x :=
                              M.alloc (|
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "ruint::Uint")
                                      [
                                        Value.Integer IntegerKind.Usize 256;
                                        Value.Integer IntegerKind.Usize 4
                                      ]
                                      [],
                                    "as_limbs",
                                    []
                                  |),
                                  [ len ]
                                |)
                              |) in
                            let~ _ :=
                              M.match_operator (|
                                M.alloc (| Value.Tuple [] |),
                                [
                                  fun γ =>
                                    ltac:(M.monadic
                                      (let γ :=
                                        M.use
                                          (M.alloc (|
                                            LogicalOp.or (|
                                              LogicalOp.or (|
                                                BinOp.ne (|
                                                  M.read (|
                                                    M.SubPointer.get_array_field (|
                                                      M.read (| x |),
                                                      M.alloc (|
                                                        Value.Integer IntegerKind.Usize 1
                                                      |)
                                                    |)
                                                  |),
                                                  Value.Integer IntegerKind.U64 0
                                                |),
                                                ltac:(M.monadic
                                                  (BinOp.ne (|
                                                    M.read (|
                                                      M.SubPointer.get_array_field (|
                                                        M.read (| x |),
                                                        M.alloc (|
                                                          Value.Integer IntegerKind.Usize 2
                                                        |)
                                                      |)
                                                    |),
                                                    Value.Integer IntegerKind.U64 0
                                                  |)))
                                              |),
                                              ltac:(M.monadic
                                                (BinOp.ne (|
                                                  M.read (|
                                                    M.SubPointer.get_array_field (|
                                                      M.read (| x |),
                                                      M.alloc (|
                                                        Value.Integer IntegerKind.Usize 3
                                                      |)
                                                    |)
                                                  |),
                                                  Value.Integer IntegerKind.U64 0
                                                |)))
                                            |)
                                          |)) in
                                      let _ :=
                                        M.is_constant_or_break_match (|
                                          M.read (| γ |),
                                          Value.Bool true
                                        |) in
                                      M.alloc (|
                                        M.never_to_any (|
                                          M.read (|
                                            let~ _ :=
                                              M.write (|
                                                M.SubPointer.get_struct_record_field (|
                                                  M.read (| interpreter |),
                                                  "revm_interpreter::interpreter::Interpreter",
                                                  "instruction_result"
                                                |),
                                                Value.StructTuple
                                                  "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG"
                                                  []
                                              |) in
                                            M.return_ (| Value.Tuple [] |)
                                          |)
                                        |)
                                      |)));
                                  fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                ]
                              |) in
                            M.match_operator (|
                              M.alloc (|
                                M.call_closure (|
                                  M.get_trait_method (|
                                    "core::convert::TryFrom",
                                    Ty.path "usize",
                                    [ Ty.path "u64" ],
                                    "try_from",
                                    []
                                  |),
                                  [
                                    M.read (|
                                      M.SubPointer.get_array_field (|
                                        M.read (| x |),
                                        M.alloc (| Value.Integer IntegerKind.Usize 0 |)
                                      |)
                                    |)
                                  ]
                                |)
                              |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ0_0 :=
                                      M.SubPointer.get_struct_tuple_field (|
                                        γ,
                                        "core::result::Result::Ok",
                                        0
                                      |) in
                                    let val := M.copy (| γ0_0 |) in
                                    val))
                              ]
                            |)
                          |) in
                        let~ code :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "alloy_primitives::bytes_::Bytes",
                                "new",
                                []
                              |),
                              []
                            |)
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        BinOp.ne (|
                                          M.read (| len |),
                                          Value.Integer IntegerKind.Usize 0
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) 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 (|
                                                      "revm_primitives::specification::Spec",
                                                      SPEC,
                                                      [],
                                                      "enabled",
                                                      []
                                                    |),
                                                    [
                                                      Value.StructTuple
                                                        "revm_primitives::specification::SpecId::SHANGHAI"
                                                        []
                                                    ]
                                                  |)
                                                |)) in
                                            let _ :=
                                              M.is_constant_or_break_match (|
                                                M.read (| γ |),
                                                Value.Bool true
                                              |) in
                                            let~ max_initcode_size :=
                                              M.alloc (|
                                                M.call_closure (|
                                                  M.get_associated_function (|
                                                    Ty.apply
                                                      (Ty.path "core::option::Option")
                                                      []
                                                      [ Ty.path "usize" ],
                                                    "unwrap_or",
                                                    []
                                                  |),
                                                  [
                                                    M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.apply
                                                          (Ty.path "core::option::Option")
                                                          []
                                                          [ Ty.path "usize" ],
                                                        "map",
                                                        [
                                                          Ty.path "usize";
                                                          Ty.function
                                                            [ Ty.tuple [ Ty.path "usize" ] ]
                                                            (Ty.path "usize")
                                                        ]
                                                      |),
                                                      [
                                                        M.read (|
                                                          M.SubPointer.get_struct_record_field (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.call_closure (|
                                                                M.get_trait_method (|
                                                                  "revm_interpreter::host::Host",
                                                                  H,
                                                                  [],
                                                                  "env",
                                                                  []
                                                                |),
                                                                [ M.read (| host |) ]
                                                              |),
                                                              "revm_primitives::env::Env",
                                                              "cfg"
                                                            |),
                                                            "revm_primitives::env::CfgEnv",
                                                            "limit_contract_code_size"
                                                          |)
                                                        |);
                                                        M.closure
                                                          (fun γ =>
                                                            ltac:(M.monadic
                                                              match γ with
                                                              | [ α0 ] =>
                                                                ltac:(M.monadic
                                                                  (M.match_operator (|
                                                                    M.alloc (| α0 |),
                                                                    [
                                                                      fun γ =>
                                                                        ltac:(M.monadic
                                                                          (let limit :=
                                                                            M.copy (| γ |) in
                                                                          M.call_closure (|
                                                                            M.get_associated_function (|
                                                                              Ty.path "usize",
                                                                              "saturating_mul",
                                                                              []
                                                                            |),
                                                                            [
                                                                              M.read (| limit |);
                                                                              Value.Integer
                                                                                IntegerKind.Usize
                                                                                2
                                                                            ]
                                                                          |)))
                                                                    ]
                                                                  |)))
                                                              | _ =>
                                                                M.impossible
                                                                  "wrong number of arguments"
                                                              end))
                                                      ]
                                                    |);
                                                    M.read (|
                                                      M.get_constant (|
                                                        "revm_primitives::constants::MAX_INITCODE_SIZE"
                                                      |)
                                                    |)
                                                  ]
                                                |)
                                              |) in
                                            let~ _ :=
                                              M.match_operator (|
                                                M.alloc (| Value.Tuple [] |),
                                                [
                                                  fun γ =>
                                                    ltac:(M.monadic
                                                      (let γ :=
                                                        M.use
                                                          (M.alloc (|
                                                            BinOp.gt (|
                                                              M.read (| len |),
                                                              M.read (| max_initcode_size |)
                                                            |)
                                                          |)) in
                                                      let _ :=
                                                        M.is_constant_or_break_match (|
                                                          M.read (| γ |),
                                                          Value.Bool true
                                                        |) in
                                                      M.alloc (|
                                                        M.never_to_any (|
                                                          M.read (|
                                                            let~ _ :=
                                                              M.write (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "instruction_result"
                                                                |),
                                                                Value.StructTuple
                                                                  "revm_interpreter::instruction_result::InstructionResult::CreateInitCodeSizeLimit"
                                                                  []
                                                              |) in
                                                            M.return_ (| Value.Tuple [] |)
                                                          |)
                                                        |)
                                                      |)));
                                                  fun γ =>
                                                    ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                                ]
                                              |) in
                                            let~ _ :=
                                              M.match_operator (|
                                                M.alloc (| Value.Tuple [] |),
                                                [
                                                  fun γ =>
                                                    ltac:(M.monadic
                                                      (let γ :=
                                                        M.use
                                                          (M.alloc (|
                                                            UnOp.not (|
                                                              M.call_closure (|
                                                                M.get_associated_function (|
                                                                  Ty.path
                                                                    "revm_interpreter::gas::Gas",
                                                                  "record_cost",
                                                                  []
                                                                |),
                                                                [
                                                                  M.SubPointer.get_struct_record_field (|
                                                                    M.read (| interpreter |),
                                                                    "revm_interpreter::interpreter::Interpreter",
                                                                    "gas"
                                                                  |);
                                                                  M.call_closure (|
                                                                    M.get_function (|
                                                                      "revm_interpreter::gas::calc::initcode_cost",
                                                                      []
                                                                    |),
                                                                    [ M.rust_cast (M.read (| len |))
                                                                    ]
                                                                  |)
                                                                ]
                                                              |)
                                                            |)
                                                          |)) in
                                                      let _ :=
                                                        M.is_constant_or_break_match (|
                                                          M.read (| γ |),
                                                          Value.Bool true
                                                        |) in
                                                      M.alloc (|
                                                        M.never_to_any (|
                                                          M.read (|
                                                            let~ _ :=
                                                              M.write (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "instruction_result"
                                                                |),
                                                                Value.StructTuple
                                                                  "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                                  []
                                                              |) in
                                                            M.return_ (| Value.Tuple [] |)
                                                          |)
                                                        |)
                                                      |)));
                                                  fun γ =>
                                                    ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                                ]
                                              |) in
                                            M.alloc (| Value.Tuple [] |)));
                                        fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                      ]
                                    |) in
                                  let~ code_offset :=
                                    M.copy (|
                                      let~ x :=
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.apply
                                                (Ty.path "ruint::Uint")
                                                [
                                                  Value.Integer IntegerKind.Usize 256;
                                                  Value.Integer IntegerKind.Usize 4
                                                ]
                                                [],
                                              "as_limbs",
                                              []
                                            |),
                                            [ code_offset ]
                                          |)
                                        |) in
                                      let~ _ :=
                                        M.match_operator (|
                                          M.alloc (| Value.Tuple [] |),
                                          [
                                            fun γ =>
                                              ltac:(M.monadic
                                                (let γ :=
                                                  M.use
                                                    (M.alloc (|
                                                      LogicalOp.or (|
                                                        LogicalOp.or (|
                                                          BinOp.ne (|
                                                            M.read (|
                                                              M.SubPointer.get_array_field (|
                                                                M.read (| x |),
                                                                M.alloc (|
                                                                  Value.Integer IntegerKind.Usize 1
                                                                |)
                                                              |)
                                                            |),
                                                            Value.Integer IntegerKind.U64 0
                                                          |),
                                                          ltac:(M.monadic
                                                            (BinOp.ne (|
                                                              M.read (|
                                                                M.SubPointer.get_array_field (|
                                                                  M.read (| x |),
                                                                  M.alloc (|
                                                                    Value.Integer
                                                                      IntegerKind.Usize
                                                                      2
                                                                  |)
                                                                |)
                                                              |),
                                                              Value.Integer IntegerKind.U64 0
                                                            |)))
                                                        |),
                                                        ltac:(M.monadic
                                                          (BinOp.ne (|
                                                            M.read (|
                                                              M.SubPointer.get_array_field (|
                                                                M.read (| x |),
                                                                M.alloc (|
                                                                  Value.Integer IntegerKind.Usize 3
                                                                |)
                                                              |)
                                                            |),
                                                            Value.Integer IntegerKind.U64 0
                                                          |)))
                                                      |)
                                                    |)) in
                                                let _ :=
                                                  M.is_constant_or_break_match (|
                                                    M.read (| γ |),
                                                    Value.Bool true
                                                  |) in
                                                M.alloc (|
                                                  M.never_to_any (|
                                                    M.read (|
                                                      let~ _ :=
                                                        M.write (|
                                                          M.SubPointer.get_struct_record_field (|
                                                            M.read (| interpreter |),
                                                            "revm_interpreter::interpreter::Interpreter",
                                                            "instruction_result"
                                                          |),
                                                          Value.StructTuple
                                                            "revm_interpreter::instruction_result::InstructionResult::InvalidOperandOOG"
                                                            []
                                                        |) in
                                                      M.return_ (| Value.Tuple [] |)
                                                    |)
                                                  |)
                                                |)));
                                            fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                          ]
                                        |) in
                                      M.match_operator (|
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::convert::TryFrom",
                                              Ty.path "usize",
                                              [ Ty.path "u64" ],
                                              "try_from",
                                              []
                                            |),
                                            [
                                              M.read (|
                                                M.SubPointer.get_array_field (|
                                                  M.read (| x |),
                                                  M.alloc (| Value.Integer IntegerKind.Usize 0 |)
                                                |)
                                              |)
                                            ]
                                          |)
                                        |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::result::Result::Ok",
                                                  0
                                                |) in
                                              let val := M.copy (| γ0_0 |) in
                                              val))
                                        ]
                                      |)
                                    |) in
                                  let~ new_size :=
                                    M.alloc (|
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.path "usize",
                                          "saturating_add",
                                          []
                                        |),
                                        [ M.read (| code_offset |); M.read (| len |) ]
                                      |)
                                    |) in
                                  let~ _ :=
                                    M.match_operator (|
                                      M.alloc (| Value.Tuple [] |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let γ :=
                                              M.use
                                                (M.alloc (|
                                                  BinOp.gt (|
                                                    M.read (| new_size |),
                                                    M.call_closure (|
                                                      M.get_associated_function (|
                                                        Ty.path
                                                          "revm_interpreter::interpreter::shared_memory::SharedMemory",
                                                        "len",
                                                        []
                                                      |),
                                                      [
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "shared_memory"
                                                        |)
                                                      ]
                                                    |)
                                                  |)
                                                |)) in
                                            let _ :=
                                              M.is_constant_or_break_match (|
                                                M.read (| γ |),
                                                Value.Bool true
                                              |) in
                                            M.match_operator (|
                                              M.alloc (| Value.Tuple [] |),
                                              [
                                                fun γ =>
                                                  ltac:(M.monadic
                                                    (let γ :=
                                                      M.use
                                                        (M.alloc (|
                                                          UnOp.not (|
                                                            M.call_closure (|
                                                              M.get_function (|
                                                                "revm_interpreter::interpreter::resize_memory",
                                                                []
                                                              |),
                                                              [
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "shared_memory"
                                                                |);
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "gas"
                                                                |);
                                                                M.read (| new_size |)
                                                              ]
                                                            |)
                                                          |)
                                                        |)) in
                                                    let _ :=
                                                      M.is_constant_or_break_match (|
                                                        M.read (| γ |),
                                                        Value.Bool true
                                                      |) in
                                                    M.alloc (|
                                                      M.never_to_any (|
                                                        M.read (|
                                                          let~ _ :=
                                                            M.write (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "instruction_result"
                                                              |),
                                                              Value.StructTuple
                                                                "revm_interpreter::instruction_result::InstructionResult::MemoryOOG"
                                                                []
                                                            |) in
                                                          M.return_ (| Value.Tuple [] |)
                                                        |)
                                                      |)
                                                    |)));
                                                fun γ =>
                                                  ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                              ]
                                            |)));
                                        fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                      ]
                                    |) in
                                  let~ _ :=
                                    M.write (|
                                      code,
                                      M.call_closure (|
                                        M.get_associated_function (|
                                          Ty.path "alloy_primitives::bytes_::Bytes",
                                          "copy_from_slice",
                                          []
                                        |),
                                        [
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.path
                                                "revm_interpreter::interpreter::shared_memory::SharedMemory",
                                              "slice",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| interpreter |),
                                                "revm_interpreter::interpreter::Interpreter",
                                                "shared_memory"
                                              |);
                                              M.read (| code_offset |);
                                              M.read (| len |)
                                            ]
                                          |)
                                        ]
                                      |)
                                    |) in
                                  M.alloc (| Value.Tuple [] |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ scheme :=
                          M.copy (|
                            M.match_operator (|
                              M.alloc (| Value.Tuple [] |),
                              [
                                fun γ =>
                                  ltac:(M.monadic
                                    (let γ :=
                                      M.use
                                        (M.get_constant (|
                                          "revm_interpreter::instructions::contract::create::IS_CREATE2"
                                        |)) in
                                    let _ :=
                                      M.is_constant_or_break_match (|
                                        M.read (| γ |),
                                        Value.Bool true
                                      |) in
                                    let~ _ :=
                                      M.match_operator (|
                                        M.alloc (| Value.Tuple [] |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ :=
                                                M.use
                                                  (M.alloc (|
                                                    BinOp.lt (|
                                                      M.call_closure (|
                                                        M.get_associated_function (|
                                                          Ty.path
                                                            "revm_interpreter::interpreter::stack::Stack",
                                                          "len",
                                                          []
                                                        |),
                                                        [
                                                          M.SubPointer.get_struct_record_field (|
                                                            M.read (| interpreter |),
                                                            "revm_interpreter::interpreter::Interpreter",
                                                            "stack"
                                                          |)
                                                        ]
                                                      |),
                                                      Value.Integer IntegerKind.Usize 1
                                                    |)
                                                  |)) in
                                              let _ :=
                                                M.is_constant_or_break_match (|
                                                  M.read (| γ |),
                                                  Value.Bool true
                                                |) in
                                              M.alloc (|
                                                M.never_to_any (|
                                                  M.read (|
                                                    let~ _ :=
                                                      M.write (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "instruction_result"
                                                        |),
                                                        Value.StructTuple
                                                          "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                                          []
                                                      |) in
                                                    M.return_ (| Value.Tuple [] |)
                                                  |)
                                                |)
                                              |)));
                                          fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                        ]
                                      |) in
                                    let~ salt :=
                                      M.alloc (|
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.path "revm_interpreter::interpreter::stack::Stack",
                                            "pop_unsafe",
                                            []
                                          |),
                                          [
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "stack"
                                            |)
                                          ]
                                        |)
                                      |) in
                                    let~ _ :=
                                      M.match_operator (|
                                        M.alloc (|
                                          M.call_closure (|
                                            M.get_function (|
                                              "revm_interpreter::gas::calc::create2_cost",
                                              []
                                            |),
                                            [
                                              M.call_closure (|
                                                M.get_associated_function (|
                                                  Ty.apply
                                                    (Ty.path "core::result::Result")
                                                    []
                                                    [
                                                      Ty.path "u64";
                                                      Ty.path "core::num::error::TryFromIntError"
                                                    ],
                                                  "unwrap",
                                                  []
                                                |),
                                                [
                                                  M.call_closure (|
                                                    M.get_trait_method (|
                                                      "core::convert::TryInto",
                                                      Ty.path "usize",
                                                      [ Ty.path "u64" ],
                                                      "try_into",
                                                      []
                                                    |),
                                                    [ M.read (| len |) ]
                                                  |)
                                                ]
                                              |)
                                            ]
                                          |)
                                        |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ0_0 :=
                                                M.SubPointer.get_struct_tuple_field (|
                                                  γ,
                                                  "core::option::Option::Some",
                                                  0
                                                |) in
                                              let gas_used := M.copy (| γ0_0 |) in
                                              M.match_operator (|
                                                M.alloc (| Value.Tuple [] |),
                                                [
                                                  fun γ =>
                                                    ltac:(M.monadic
                                                      (let γ :=
                                                        M.use
                                                          (M.alloc (|
                                                            UnOp.not (|
                                                              M.call_closure (|
                                                                M.get_associated_function (|
                                                                  Ty.path
                                                                    "revm_interpreter::gas::Gas",
                                                                  "record_cost",
                                                                  []
                                                                |),
                                                                [
                                                                  M.SubPointer.get_struct_record_field (|
                                                                    M.read (| interpreter |),
                                                                    "revm_interpreter::interpreter::Interpreter",
                                                                    "gas"
                                                                  |);
                                                                  M.read (| gas_used |)
                                                                ]
                                                              |)
                                                            |)
                                                          |)) in
                                                      let _ :=
                                                        M.is_constant_or_break_match (|
                                                          M.read (| γ |),
                                                          Value.Bool true
                                                        |) in
                                                      M.alloc (|
                                                        M.never_to_any (|
                                                          M.read (|
                                                            let~ _ :=
                                                              M.write (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "instruction_result"
                                                                |),
                                                                Value.StructTuple
                                                                  "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                                  []
                                                              |) in
                                                            M.return_ (| Value.Tuple [] |)
                                                          |)
                                                        |)
                                                      |)));
                                                  fun γ =>
                                                    ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                                ]
                                              |)));
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let _ :=
                                                M.is_struct_tuple (|
                                                  γ,
                                                  "core::option::Option::None"
                                                |) in
                                              M.alloc (|
                                                M.never_to_any (|
                                                  M.read (|
                                                    let~ _ :=
                                                      M.write (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "instruction_result"
                                                        |),
                                                        Value.StructTuple
                                                          "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                          []
                                                      |) in
                                                    M.return_ (| Value.Tuple [] |)
                                                  |)
                                                |)
                                              |)))
                                        ]
                                      |) in
                                    M.alloc (|
                                      Value.StructRecord
                                        "revm_primitives::env::CreateScheme::Create2"
                                        [ ("salt", M.read (| salt |)) ]
                                    |)));
                                fun γ =>
                                  ltac:(M.monadic
                                    (let~ _ :=
                                      M.match_operator (|
                                        M.alloc (| Value.Tuple [] |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (let γ :=
                                                M.use
                                                  (M.alloc (|
                                                    UnOp.not (|
                                                      M.call_closure (|
                                                        M.get_associated_function (|
                                                          Ty.path "revm_interpreter::gas::Gas",
                                                          "record_cost",
                                                          []
                                                        |),
                                                        [
                                                          M.SubPointer.get_struct_record_field (|
                                                            M.read (| interpreter |),
                                                            "revm_interpreter::interpreter::Interpreter",
                                                            "gas"
                                                          |);
                                                          M.read (|
                                                            M.get_constant (|
                                                              "revm_interpreter::gas::constants::CREATE"
                                                            |)
                                                          |)
                                                        ]
                                                      |)
                                                    |)
                                                  |)) in
                                              let _ :=
                                                M.is_constant_or_break_match (|
                                                  M.read (| γ |),
                                                  Value.Bool true
                                                |) in
                                              M.alloc (|
                                                M.never_to_any (|
                                                  M.read (|
                                                    let~ _ :=
                                                      M.write (|
                                                        M.SubPointer.get_struct_record_field (|
                                                          M.read (| interpreter |),
                                                          "revm_interpreter::interpreter::Interpreter",
                                                          "instruction_result"
                                                        |),
                                                        Value.StructTuple
                                                          "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                          []
                                                      |) in
                                                    M.return_ (| Value.Tuple [] |)
                                                  |)
                                                |)
                                              |)));
                                          fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                        ]
                                      |) in
                                    M.alloc (|
                                      Value.StructTuple
                                        "revm_primitives::env::CreateScheme::Create"
                                        []
                                    |)))
                              ]
                            |)
                          |) in
                        let~ gas_limit :=
                          M.alloc (|
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::gas::Gas",
                                "remaining",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.path "revm_interpreter::interpreter::Interpreter",
                                    "gas",
                                    []
                                  |),
                                  [ M.read (| interpreter |) ]
                                |)
                              ]
                            |)
                          |) 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 (|
                                            "revm_primitives::specification::Spec",
                                            SPEC,
                                            [],
                                            "enabled",
                                            []
                                          |),
                                          [
                                            Value.StructTuple
                                              "revm_primitives::specification::SpecId::TANGERINE"
                                              []
                                          ]
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  let β := gas_limit in
                                  M.write (|
                                    β,
                                    BinOp.Wrap.sub (|
                                      M.read (| β |),
                                      BinOp.Wrap.div (|
                                        M.read (| gas_limit |),
                                        Value.Integer IntegerKind.U64 64
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ _ :=
                          M.match_operator (|
                            M.alloc (| Value.Tuple [] |),
                            [
                              fun γ =>
                                ltac:(M.monadic
                                  (let γ :=
                                    M.use
                                      (M.alloc (|
                                        UnOp.not (|
                                          M.call_closure (|
                                            M.get_associated_function (|
                                              Ty.path "revm_interpreter::gas::Gas",
                                              "record_cost",
                                              []
                                            |),
                                            [
                                              M.SubPointer.get_struct_record_field (|
                                                M.read (| interpreter |),
                                                "revm_interpreter::interpreter::Interpreter",
                                                "gas"
                                              |);
                                              M.read (| gas_limit |)
                                            ]
                                          |)
                                        |)
                                      |)) in
                                  let _ :=
                                    M.is_constant_or_break_match (|
                                      M.read (| γ |),
                                      Value.Bool true
                                    |) in
                                  M.alloc (|
                                    M.never_to_any (|
                                      M.read (|
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                              []
                                          |) in
                                        M.return_ (| Value.Tuple [] |)
                                      |)
                                    |)
                                  |)));
                              fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                            ]
                          |) in
                        let~ _ :=
                          M.write (|
                            M.SubPointer.get_struct_record_field (|
                              M.read (| interpreter |),
                              "revm_interpreter::interpreter::Interpreter",
                              "next_action"
                            |),
                            Value.StructRecord
                              "revm_interpreter::interpreter_action::InterpreterAction::Create"
                              [
                                ("inputs",
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.apply
                                        (Ty.path "alloc::boxed::Box")
                                        []
                                        [
                                          Ty.path
                                            "revm_interpreter::interpreter_action::create_inputs::CreateInputs";
                                          Ty.path "alloc::alloc::Global"
                                        ],
                                      "new",
                                      []
                                    |),
                                    [
                                      Value.StructRecord
                                        "revm_interpreter::interpreter_action::create_inputs::CreateInputs"
                                        [
                                          ("caller",
                                            M.read (|
                                              M.SubPointer.get_struct_record_field (|
                                                M.SubPointer.get_struct_record_field (|
                                                  M.read (| interpreter |),
                                                  "revm_interpreter::interpreter::Interpreter",
                                                  "contract"
                                                |),
                                                "revm_interpreter::interpreter::contract::Contract",
                                                "target_address"
                                              |)
                                            |));
                                          ("scheme", M.read (| scheme |));
                                          ("value", M.read (| value |));
                                          ("init_code", M.read (| code |));
                                          ("gas_limit", M.read (| gas_limit |))
                                        ]
                                    ]
                                  |))
                              ]
                          |) in
                        let~ _ :=
                          M.write (|
                            M.SubPointer.get_struct_record_field (|
                              M.read (| interpreter |),
                              "revm_interpreter::interpreter::Interpreter",
                              "instruction_result"
                            |),
                            Value.StructTuple
                              "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                              []
                          |) in
                        M.alloc (| Value.Tuple [] |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_create : M.IsFunction "revm_interpreter::instructions::contract::create" create.
    
    (*
    pub fn call<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
        pop!(interpreter, local_gas_limit);
        pop_address!(interpreter, to);
        // max gas limit is not possible in real ethereum situation.
        let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);
    
        pop!(interpreter, value);
        let has_transfer = value != U256::ZERO;
        if interpreter.is_static && has_transfer {
            interpreter.instruction_result = InstructionResult::CallNotAllowedInsideStatic;
            return;
        }
    
        let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else {
            return;
        };
    
        let Some(LoadAccountResult { is_cold, is_empty }) = host.load_account(to) else {
            interpreter.instruction_result = InstructionResult::FatalExternalError;
            return;
        };
        let Some(mut gas_limit) = calc_call_gas::<H, SPEC>(
            interpreter,
            is_cold,
            has_transfer,
            is_empty,
            local_gas_limit,
        ) else {
            return;
        };
    
        gas!(interpreter, gas_limit);
    
        // add call stipend if there is value to be transferred.
        if has_transfer {
            gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND);
        }
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Call {
            inputs: Box::new(CallInputs {
                input,
                gas_limit,
                target_address: to,
                caller: interpreter.contract.target_address,
                bytecode_address: to,
                value: CallValue::Transfer(value),
                scheme: CallScheme::Call,
                is_static: interpreter.is_static,
                is_eof: false,
                return_memory_offset,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition call (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H; SPEC ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ to :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "alloy_primitives::bits::address::Address",
                        "from_word",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::From",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "from",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply
                          (Ty.path "core::result::Result")
                          []
                          [
                            Ty.path "u64";
                            Ty.apply (Ty.path "ruint::from::FromUintError") [] [ Ty.path "u64" ]
                          ],
                        "unwrap_or",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::TryFrom",
                            Ty.path "u64",
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "try_from",
                            []
                          |),
                          [ M.read (| local_gas_limit |) ]
                        |);
                        M.read (| M.get_constant (| "core::num::MAX" |) |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ value :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |) in
                let~ has_transfer :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_trait_method (|
                        "core::cmp::PartialEq",
                        Ty.apply
                          (Ty.path "ruint::Uint")
                          [ Value.Integer IntegerKind.Usize 256; Value.Integer IntegerKind.Usize 4 ]
                          [],
                        [
                          Ty.apply
                            (Ty.path "ruint::Uint")
                            [ Value.Integer IntegerKind.Usize 256; Value.Integer IntegerKind.Usize 4
                            ]
                            []
                        ],
                        "ne",
                        []
                      |),
                      [ value; M.get_constant (| "ruint::ZERO" |) ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                LogicalOp.and (|
                                  M.read (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "is_static"
                                    |)
                                  |),
                                  ltac:(M.monadic (M.read (| has_transfer |)))
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::CallNotAllowedInsideStatic"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges",
                        []
                      |),
                      [ M.read (| interpreter |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let γ1_0 := M.SubPointer.get_tuple_field (| γ0_0, 0 |) in
                        let γ1_1 := M.SubPointer.get_tuple_field (| γ0_0, 1 |) in
                        let input := M.copy (| γ1_0 |) in
                        let return_memory_offset := M.copy (| γ1_1 |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "revm_interpreter::host::Host",
                                H,
                                [],
                                "load_account",
                                []
                              |),
                              [ M.read (| host |); M.read (| to |) ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let γ1_0 :=
                                  M.SubPointer.get_struct_record_field (|
                                    γ0_0,
                                    "revm_interpreter::host::LoadAccountResult",
                                    "is_cold"
                                  |) in
                                let γ1_1 :=
                                  M.SubPointer.get_struct_record_field (|
                                    γ0_0,
                                    "revm_interpreter::host::LoadAccountResult",
                                    "is_empty"
                                  |) in
                                let is_cold := M.copy (| γ1_0 |) in
                                let is_empty := M.copy (| γ1_1 |) in
                                M.match_operator (|
                                  M.alloc (|
                                    M.call_closure (|
                                      M.get_function (|
                                        "revm_interpreter::instructions::contract::call_helpers::calc_call_gas",
                                        [ H; SPEC ]
                                      |),
                                      [
                                        M.read (| interpreter |);
                                        M.read (| is_cold |);
                                        M.read (| has_transfer |);
                                        M.read (| is_empty |);
                                        M.read (| local_gas_limit |)
                                      ]
                                    |)
                                  |),
                                  [
                                    fun γ =>
                                      ltac:(M.monadic
                                        (let γ0_0 :=
                                          M.SubPointer.get_struct_tuple_field (|
                                            γ,
                                            "core::option::Option::Some",
                                            0
                                          |) in
                                        let gas_limit := M.copy (| γ0_0 |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (| Value.Tuple [] |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ :=
                                                    M.use
                                                      (M.alloc (|
                                                        UnOp.not (|
                                                          M.call_closure (|
                                                            M.get_associated_function (|
                                                              Ty.path "revm_interpreter::gas::Gas",
                                                              "record_cost",
                                                              []
                                                            |),
                                                            [
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "gas"
                                                              |);
                                                              M.read (| gas_limit |)
                                                            ]
                                                          |)
                                                        |)
                                                      |)) in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (| Value.Tuple [] |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ := M.use has_transfer in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  let~ _ :=
                                                    M.write (|
                                                      gas_limit,
                                                      M.call_closure (|
                                                        M.get_associated_function (|
                                                          Ty.path "u64",
                                                          "saturating_add",
                                                          []
                                                        |),
                                                        [
                                                          M.read (| gas_limit |);
                                                          M.read (|
                                                            M.get_constant (|
                                                              "revm_interpreter::gas::constants::CALL_STIPEND"
                                                            |)
                                                          |)
                                                        ]
                                                      |)
                                                    |) in
                                                  M.alloc (| Value.Tuple [] |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "next_action"
                                            |),
                                            Value.StructRecord
                                              "revm_interpreter::interpreter_action::InterpreterAction::Call"
                                              [
                                                ("inputs",
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.apply
                                                        (Ty.path "alloc::boxed::Box")
                                                        []
                                                        [
                                                          Ty.path
                                                            "revm_interpreter::interpreter_action::call_inputs::CallInputs";
                                                          Ty.path "alloc::alloc::Global"
                                                        ],
                                                      "new",
                                                      []
                                                    |),
                                                    [
                                                      Value.StructRecord
                                                        "revm_interpreter::interpreter_action::call_inputs::CallInputs"
                                                        [
                                                          ("input", M.read (| input |));
                                                          ("gas_limit", M.read (| gas_limit |));
                                                          ("target_address", M.read (| to |));
                                                          ("caller",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "contract"
                                                                |),
                                                                "revm_interpreter::interpreter::contract::Contract",
                                                                "target_address"
                                                              |)
                                                            |));
                                                          ("bytecode_address", M.read (| to |));
                                                          ("value",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer"
                                                              [ M.read (| value |) ]);
                                                          ("scheme",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallScheme::Call"
                                                              []);
                                                          ("is_static",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "is_static"
                                                              |)
                                                            |));
                                                          ("is_eof", Value.Bool false);
                                                          ("return_memory_offset",
                                                            M.read (| return_memory_offset |))
                                                        ]
                                                    ]
                                                  |))
                                              ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                              []
                                          |) in
                                        M.alloc (| Value.Tuple [] |)))
                                  ]
                                |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_call : M.IsFunction "revm_interpreter::instructions::contract::call" call.
    
    (*
    pub fn call_code<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
        pop!(interpreter, local_gas_limit);
        pop_address!(interpreter, to);
        // max gas limit is not possible in real ethereum situation.
        let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);
    
        pop!(interpreter, value);
        let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else {
            return;
        };
    
        let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else {
            interpreter.instruction_result = InstructionResult::FatalExternalError;
            return;
        };
    
        let Some(mut gas_limit) = calc_call_gas::<H, SPEC>(
            interpreter,
            is_cold,
            value != U256::ZERO,
            false,
            local_gas_limit,
        ) else {
            return;
        };
    
        gas!(interpreter, gas_limit);
    
        // add call stipend if there is value to be transferred.
        if value != U256::ZERO {
            gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND);
        }
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Call {
            inputs: Box::new(CallInputs {
                input,
                gas_limit,
                target_address: interpreter.contract.target_address,
                caller: interpreter.contract.target_address,
                bytecode_address: to,
                value: CallValue::Transfer(value),
                scheme: CallScheme::CallCode,
                is_static: interpreter.is_static,
                is_eof: false,
                return_memory_offset,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition call_code (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H; SPEC ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ to :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "alloy_primitives::bits::address::Address",
                        "from_word",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::From",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "from",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply
                          (Ty.path "core::result::Result")
                          []
                          [
                            Ty.path "u64";
                            Ty.apply (Ty.path "ruint::from::FromUintError") [] [ Ty.path "u64" ]
                          ],
                        "unwrap_or",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::TryFrom",
                            Ty.path "u64",
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "try_from",
                            []
                          |),
                          [ M.read (| local_gas_limit |) ]
                        |);
                        M.read (| M.get_constant (| "core::num::MAX" |) |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ value :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges",
                        []
                      |),
                      [ M.read (| interpreter |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let γ1_0 := M.SubPointer.get_tuple_field (| γ0_0, 0 |) in
                        let γ1_1 := M.SubPointer.get_tuple_field (| γ0_0, 1 |) in
                        let input := M.copy (| γ1_0 |) in
                        let return_memory_offset := M.copy (| γ1_1 |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "revm_interpreter::host::Host",
                                H,
                                [],
                                "load_account",
                                []
                              |),
                              [ M.read (| host |); M.read (| to |) ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let γ1_0 :=
                                  M.SubPointer.get_struct_record_field (|
                                    γ0_0,
                                    "revm_interpreter::host::LoadAccountResult",
                                    "is_cold"
                                  |) in
                                let is_cold := M.copy (| γ1_0 |) in
                                M.match_operator (|
                                  M.alloc (|
                                    M.call_closure (|
                                      M.get_function (|
                                        "revm_interpreter::instructions::contract::call_helpers::calc_call_gas",
                                        [ H; SPEC ]
                                      |),
                                      [
                                        M.read (| interpreter |);
                                        M.read (| is_cold |);
                                        M.call_closure (|
                                          M.get_trait_method (|
                                            "core::cmp::PartialEq",
                                            Ty.apply
                                              (Ty.path "ruint::Uint")
                                              [
                                                Value.Integer IntegerKind.Usize 256;
                                                Value.Integer IntegerKind.Usize 4
                                              ]
                                              [],
                                            [
                                              Ty.apply
                                                (Ty.path "ruint::Uint")
                                                [
                                                  Value.Integer IntegerKind.Usize 256;
                                                  Value.Integer IntegerKind.Usize 4
                                                ]
                                                []
                                            ],
                                            "ne",
                                            []
                                          |),
                                          [ value; M.get_constant (| "ruint::ZERO" |) ]
                                        |);
                                        Value.Bool false;
                                        M.read (| local_gas_limit |)
                                      ]
                                    |)
                                  |),
                                  [
                                    fun γ =>
                                      ltac:(M.monadic
                                        (let γ0_0 :=
                                          M.SubPointer.get_struct_tuple_field (|
                                            γ,
                                            "core::option::Option::Some",
                                            0
                                          |) in
                                        let gas_limit := M.copy (| γ0_0 |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (| Value.Tuple [] |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ :=
                                                    M.use
                                                      (M.alloc (|
                                                        UnOp.not (|
                                                          M.call_closure (|
                                                            M.get_associated_function (|
                                                              Ty.path "revm_interpreter::gas::Gas",
                                                              "record_cost",
                                                              []
                                                            |),
                                                            [
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "gas"
                                                              |);
                                                              M.read (| gas_limit |)
                                                            ]
                                                          |)
                                                        |)
                                                      |)) in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |) 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::cmp::PartialEq",
                                                            Ty.apply
                                                              (Ty.path "ruint::Uint")
                                                              [
                                                                Value.Integer IntegerKind.Usize 256;
                                                                Value.Integer IntegerKind.Usize 4
                                                              ]
                                                              [],
                                                            [
                                                              Ty.apply
                                                                (Ty.path "ruint::Uint")
                                                                [
                                                                  Value.Integer
                                                                    IntegerKind.Usize
                                                                    256;
                                                                  Value.Integer IntegerKind.Usize 4
                                                                ]
                                                                []
                                                            ],
                                                            "ne",
                                                            []
                                                          |),
                                                          [
                                                            value;
                                                            M.get_constant (| "ruint::ZERO" |)
                                                          ]
                                                        |)
                                                      |)) in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  let~ _ :=
                                                    M.write (|
                                                      gas_limit,
                                                      M.call_closure (|
                                                        M.get_associated_function (|
                                                          Ty.path "u64",
                                                          "saturating_add",
                                                          []
                                                        |),
                                                        [
                                                          M.read (| gas_limit |);
                                                          M.read (|
                                                            M.get_constant (|
                                                              "revm_interpreter::gas::constants::CALL_STIPEND"
                                                            |)
                                                          |)
                                                        ]
                                                      |)
                                                    |) in
                                                  M.alloc (| Value.Tuple [] |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "next_action"
                                            |),
                                            Value.StructRecord
                                              "revm_interpreter::interpreter_action::InterpreterAction::Call"
                                              [
                                                ("inputs",
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.apply
                                                        (Ty.path "alloc::boxed::Box")
                                                        []
                                                        [
                                                          Ty.path
                                                            "revm_interpreter::interpreter_action::call_inputs::CallInputs";
                                                          Ty.path "alloc::alloc::Global"
                                                        ],
                                                      "new",
                                                      []
                                                    |),
                                                    [
                                                      Value.StructRecord
                                                        "revm_interpreter::interpreter_action::call_inputs::CallInputs"
                                                        [
                                                          ("input", M.read (| input |));
                                                          ("gas_limit", M.read (| gas_limit |));
                                                          ("target_address",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "contract"
                                                                |),
                                                                "revm_interpreter::interpreter::contract::Contract",
                                                                "target_address"
                                                              |)
                                                            |));
                                                          ("caller",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "contract"
                                                                |),
                                                                "revm_interpreter::interpreter::contract::Contract",
                                                                "target_address"
                                                              |)
                                                            |));
                                                          ("bytecode_address", M.read (| to |));
                                                          ("value",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer"
                                                              [ M.read (| value |) ]);
                                                          ("scheme",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallScheme::CallCode"
                                                              []);
                                                          ("is_static",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "is_static"
                                                              |)
                                                            |));
                                                          ("is_eof", Value.Bool false);
                                                          ("return_memory_offset",
                                                            M.read (| return_memory_offset |))
                                                        ]
                                                    ]
                                                  |))
                                              ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                              []
                                          |) in
                                        M.alloc (| Value.Tuple [] |)))
                                  ]
                                |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_call_code :
      M.IsFunction "revm_interpreter::instructions::contract::call_code" call_code.
    
    (*
    pub fn delegate_call<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
        check!(interpreter, HOMESTEAD);
        pop!(interpreter, local_gas_limit);
        pop_address!(interpreter, to);
        // max gas limit is not possible in real ethereum situation.
        let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);
    
        let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else {
            return;
        };
    
        let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else {
            interpreter.instruction_result = InstructionResult::FatalExternalError;
            return;
        };
        let Some(gas_limit) =
            calc_call_gas::<H, SPEC>(interpreter, is_cold, false, false, local_gas_limit)
        else {
            return;
        };
    
        gas!(interpreter, gas_limit);
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Call {
            inputs: Box::new(CallInputs {
                input,
                gas_limit,
                target_address: interpreter.contract.target_address,
                caller: interpreter.contract.caller,
                bytecode_address: to,
                value: CallValue::Apparent(interpreter.contract.call_value),
                scheme: CallScheme::DelegateCall,
                is_static: interpreter.is_static,
                is_eof: false,
                return_memory_offset,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition delegate_call (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H; SPEC ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "revm_primitives::specification::Spec",
                                      SPEC,
                                      [],
                                      "enabled",
                                      []
                                    |),
                                    [
                                      Value.StructTuple
                                        "revm_primitives::specification::SpecId::HOMESTEAD"
                                        []
                                    ]
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::NotActivated"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ to :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "alloy_primitives::bits::address::Address",
                        "from_word",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::From",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "from",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply
                          (Ty.path "core::result::Result")
                          []
                          [
                            Ty.path "u64";
                            Ty.apply (Ty.path "ruint::from::FromUintError") [] [ Ty.path "u64" ]
                          ],
                        "unwrap_or",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::TryFrom",
                            Ty.path "u64",
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "try_from",
                            []
                          |),
                          [ M.read (| local_gas_limit |) ]
                        |);
                        M.read (| M.get_constant (| "core::num::MAX" |) |)
                      ]
                    |)
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges",
                        []
                      |),
                      [ M.read (| interpreter |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let γ1_0 := M.SubPointer.get_tuple_field (| γ0_0, 0 |) in
                        let γ1_1 := M.SubPointer.get_tuple_field (| γ0_0, 1 |) in
                        let input := M.copy (| γ1_0 |) in
                        let return_memory_offset := M.copy (| γ1_1 |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "revm_interpreter::host::Host",
                                H,
                                [],
                                "load_account",
                                []
                              |),
                              [ M.read (| host |); M.read (| to |) ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let γ1_0 :=
                                  M.SubPointer.get_struct_record_field (|
                                    γ0_0,
                                    "revm_interpreter::host::LoadAccountResult",
                                    "is_cold"
                                  |) in
                                let is_cold := M.copy (| γ1_0 |) in
                                M.match_operator (|
                                  M.alloc (|
                                    M.call_closure (|
                                      M.get_function (|
                                        "revm_interpreter::instructions::contract::call_helpers::calc_call_gas",
                                        [ H; SPEC ]
                                      |),
                                      [
                                        M.read (| interpreter |);
                                        M.read (| is_cold |);
                                        Value.Bool false;
                                        Value.Bool false;
                                        M.read (| local_gas_limit |)
                                      ]
                                    |)
                                  |),
                                  [
                                    fun γ =>
                                      ltac:(M.monadic
                                        (let γ0_0 :=
                                          M.SubPointer.get_struct_tuple_field (|
                                            γ,
                                            "core::option::Option::Some",
                                            0
                                          |) in
                                        let gas_limit := M.copy (| γ0_0 |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (| Value.Tuple [] |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ :=
                                                    M.use
                                                      (M.alloc (|
                                                        UnOp.not (|
                                                          M.call_closure (|
                                                            M.get_associated_function (|
                                                              Ty.path "revm_interpreter::gas::Gas",
                                                              "record_cost",
                                                              []
                                                            |),
                                                            [
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "gas"
                                                              |);
                                                              M.read (| gas_limit |)
                                                            ]
                                                          |)
                                                        |)
                                                      |)) in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "next_action"
                                            |),
                                            Value.StructRecord
                                              "revm_interpreter::interpreter_action::InterpreterAction::Call"
                                              [
                                                ("inputs",
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.apply
                                                        (Ty.path "alloc::boxed::Box")
                                                        []
                                                        [
                                                          Ty.path
                                                            "revm_interpreter::interpreter_action::call_inputs::CallInputs";
                                                          Ty.path "alloc::alloc::Global"
                                                        ],
                                                      "new",
                                                      []
                                                    |),
                                                    [
                                                      Value.StructRecord
                                                        "revm_interpreter::interpreter_action::call_inputs::CallInputs"
                                                        [
                                                          ("input", M.read (| input |));
                                                          ("gas_limit", M.read (| gas_limit |));
                                                          ("target_address",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "contract"
                                                                |),
                                                                "revm_interpreter::interpreter::contract::Contract",
                                                                "target_address"
                                                              |)
                                                            |));
                                                          ("caller",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "contract"
                                                                |),
                                                                "revm_interpreter::interpreter::contract::Contract",
                                                                "caller"
                                                              |)
                                                            |));
                                                          ("bytecode_address", M.read (| to |));
                                                          ("value",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallValue::Apparent"
                                                              [
                                                                M.read (|
                                                                  M.SubPointer.get_struct_record_field (|
                                                                    M.SubPointer.get_struct_record_field (|
                                                                      M.read (| interpreter |),
                                                                      "revm_interpreter::interpreter::Interpreter",
                                                                      "contract"
                                                                    |),
                                                                    "revm_interpreter::interpreter::contract::Contract",
                                                                    "call_value"
                                                                  |)
                                                                |)
                                                              ]);
                                                          ("scheme",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallScheme::DelegateCall"
                                                              []);
                                                          ("is_static",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "is_static"
                                                              |)
                                                            |));
                                                          ("is_eof", Value.Bool false);
                                                          ("return_memory_offset",
                                                            M.read (| return_memory_offset |))
                                                        ]
                                                    ]
                                                  |))
                                              ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                              []
                                          |) in
                                        M.alloc (| Value.Tuple [] |)))
                                  ]
                                |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_delegate_call :
      M.IsFunction "revm_interpreter::instructions::contract::delegate_call" delegate_call.
    
    (*
    pub fn static_call<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
        check!(interpreter, BYZANTIUM);
        pop!(interpreter, local_gas_limit);
        pop_address!(interpreter, to);
        // max gas limit is not possible in real ethereum situation.
        let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX);
    
        let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(interpreter) else {
            return;
        };
    
        let Some(LoadAccountResult { is_cold, .. }) = host.load_account(to) else {
            interpreter.instruction_result = InstructionResult::FatalExternalError;
            return;
        };
    
        let Some(gas_limit) =
            calc_call_gas::<H, SPEC>(interpreter, is_cold, false, false, local_gas_limit)
        else {
            return;
        };
        gas!(interpreter, gas_limit);
    
        // Call host to interact with target contract
        interpreter.next_action = InterpreterAction::Call {
            inputs: Box::new(CallInputs {
                input,
                gas_limit,
                target_address: to,
                caller: interpreter.contract.target_address,
                bytecode_address: to,
                value: CallValue::Transfer(U256::ZERO),
                scheme: CallScheme::StaticCall,
                is_static: true,
                is_eof: false,
                return_memory_offset,
            }),
        };
        interpreter.instruction_result = InstructionResult::CallOrCreate;
    }
    *)
    Definition static_call (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [ H; SPEC ], [ interpreter; host ] =>
        ltac:(M.monadic
          (let interpreter := M.alloc (| interpreter |) in
          let host := M.alloc (| host |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                UnOp.not (|
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "revm_primitives::specification::Spec",
                                      SPEC,
                                      [],
                                      "enabled",
                                      []
                                    |),
                                    [
                                      Value.StructTuple
                                        "revm_primitives::specification::SpecId::BYZANTIUM"
                                        []
                                    ]
                                  |)
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::NotActivated"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "revm_interpreter::interpreter::stack::Stack",
                        "pop_unsafe",
                        []
                      |),
                      [
                        M.SubPointer.get_struct_record_field (|
                          M.read (| interpreter |),
                          "revm_interpreter::interpreter::Interpreter",
                          "stack"
                        |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.match_operator (|
                    M.alloc (| Value.Tuple [] |),
                    [
                      fun γ =>
                        ltac:(M.monadic
                          (let γ :=
                            M.use
                              (M.alloc (|
                                BinOp.lt (|
                                  M.call_closure (|
                                    M.get_associated_function (|
                                      Ty.path "revm_interpreter::interpreter::stack::Stack",
                                      "len",
                                      []
                                    |),
                                    [
                                      M.SubPointer.get_struct_record_field (|
                                        M.read (| interpreter |),
                                        "revm_interpreter::interpreter::Interpreter",
                                        "stack"
                                      |)
                                    ]
                                  |),
                                  Value.Integer IntegerKind.Usize 1
                                |)
                              |)) in
                          let _ :=
                            M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                          M.alloc (|
                            M.never_to_any (|
                              M.read (|
                                let~ _ :=
                                  M.write (|
                                    M.SubPointer.get_struct_record_field (|
                                      M.read (| interpreter |),
                                      "revm_interpreter::interpreter::Interpreter",
                                      "instruction_result"
                                    |),
                                    Value.StructTuple
                                      "revm_interpreter::instruction_result::InstructionResult::StackUnderflow"
                                      []
                                  |) in
                                M.return_ (| Value.Tuple [] |)
                              |)
                            |)
                          |)));
                      fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                    ]
                  |) in
                let~ to :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "alloy_primitives::bits::address::Address",
                        "from_word",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::From",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "from",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "revm_interpreter::interpreter::stack::Stack",
                                "pop_unsafe",
                                []
                              |),
                              [
                                M.SubPointer.get_struct_record_field (|
                                  M.read (| interpreter |),
                                  "revm_interpreter::interpreter::Interpreter",
                                  "stack"
                                |)
                              ]
                            |)
                          ]
                        |)
                      ]
                    |)
                  |) in
                let~ local_gas_limit :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply
                          (Ty.path "core::result::Result")
                          []
                          [
                            Ty.path "u64";
                            Ty.apply (Ty.path "ruint::from::FromUintError") [] [ Ty.path "u64" ]
                          ],
                        "unwrap_or",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::convert::TryFrom",
                            Ty.path "u64",
                            [
                              Ty.apply
                                (Ty.path "ruint::Uint")
                                [
                                  Value.Integer IntegerKind.Usize 256;
                                  Value.Integer IntegerKind.Usize 4
                                ]
                                []
                            ],
                            "try_from",
                            []
                          |),
                          [ M.read (| local_gas_limit |) ]
                        |);
                        M.read (| M.get_constant (| "core::num::MAX" |) |)
                      ]
                    |)
                  |) in
                M.match_operator (|
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "revm_interpreter::instructions::contract::call_helpers::get_memory_input_and_out_ranges",
                        []
                      |),
                      [ M.read (| interpreter |) ]
                    |)
                  |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ0_0 :=
                          M.SubPointer.get_struct_tuple_field (|
                            γ,
                            "core::option::Option::Some",
                            0
                          |) in
                        let γ1_0 := M.SubPointer.get_tuple_field (| γ0_0, 0 |) in
                        let γ1_1 := M.SubPointer.get_tuple_field (| γ0_0, 1 |) in
                        let input := M.copy (| γ1_0 |) in
                        let return_memory_offset := M.copy (| γ1_1 |) in
                        M.match_operator (|
                          M.alloc (|
                            M.call_closure (|
                              M.get_trait_method (|
                                "revm_interpreter::host::Host",
                                H,
                                [],
                                "load_account",
                                []
                              |),
                              [ M.read (| host |); M.read (| to |) ]
                            |)
                          |),
                          [
                            fun γ =>
                              ltac:(M.monadic
                                (let γ0_0 :=
                                  M.SubPointer.get_struct_tuple_field (|
                                    γ,
                                    "core::option::Option::Some",
                                    0
                                  |) in
                                let γ1_0 :=
                                  M.SubPointer.get_struct_record_field (|
                                    γ0_0,
                                    "revm_interpreter::host::LoadAccountResult",
                                    "is_cold"
                                  |) in
                                let is_cold := M.copy (| γ1_0 |) in
                                M.match_operator (|
                                  M.alloc (|
                                    M.call_closure (|
                                      M.get_function (|
                                        "revm_interpreter::instructions::contract::call_helpers::calc_call_gas",
                                        [ H; SPEC ]
                                      |),
                                      [
                                        M.read (| interpreter |);
                                        M.read (| is_cold |);
                                        Value.Bool false;
                                        Value.Bool false;
                                        M.read (| local_gas_limit |)
                                      ]
                                    |)
                                  |),
                                  [
                                    fun γ =>
                                      ltac:(M.monadic
                                        (let γ0_0 :=
                                          M.SubPointer.get_struct_tuple_field (|
                                            γ,
                                            "core::option::Option::Some",
                                            0
                                          |) in
                                        let gas_limit := M.copy (| γ0_0 |) in
                                        let~ _ :=
                                          M.match_operator (|
                                            M.alloc (| Value.Tuple [] |),
                                            [
                                              fun γ =>
                                                ltac:(M.monadic
                                                  (let γ :=
                                                    M.use
                                                      (M.alloc (|
                                                        UnOp.not (|
                                                          M.call_closure (|
                                                            M.get_associated_function (|
                                                              Ty.path "revm_interpreter::gas::Gas",
                                                              "record_cost",
                                                              []
                                                            |),
                                                            [
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.read (| interpreter |),
                                                                "revm_interpreter::interpreter::Interpreter",
                                                                "gas"
                                                              |);
                                                              M.read (| gas_limit |)
                                                            ]
                                                          |)
                                                        |)
                                                      |)) in
                                                  let _ :=
                                                    M.is_constant_or_break_match (|
                                                      M.read (| γ |),
                                                      Value.Bool true
                                                    |) in
                                                  M.alloc (|
                                                    M.never_to_any (|
                                                      M.read (|
                                                        let~ _ :=
                                                          M.write (|
                                                            M.SubPointer.get_struct_record_field (|
                                                              M.read (| interpreter |),
                                                              "revm_interpreter::interpreter::Interpreter",
                                                              "instruction_result"
                                                            |),
                                                            Value.StructTuple
                                                              "revm_interpreter::instruction_result::InstructionResult::OutOfGas"
                                                              []
                                                          |) in
                                                        M.return_ (| Value.Tuple [] |)
                                                      |)
                                                    |)
                                                  |)));
                                              fun γ =>
                                                ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                                            ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "next_action"
                                            |),
                                            Value.StructRecord
                                              "revm_interpreter::interpreter_action::InterpreterAction::Call"
                                              [
                                                ("inputs",
                                                  M.call_closure (|
                                                    M.get_associated_function (|
                                                      Ty.apply
                                                        (Ty.path "alloc::boxed::Box")
                                                        []
                                                        [
                                                          Ty.path
                                                            "revm_interpreter::interpreter_action::call_inputs::CallInputs";
                                                          Ty.path "alloc::alloc::Global"
                                                        ],
                                                      "new",
                                                      []
                                                    |),
                                                    [
                                                      Value.StructRecord
                                                        "revm_interpreter::interpreter_action::call_inputs::CallInputs"
                                                        [
                                                          ("input", M.read (| input |));
                                                          ("gas_limit", M.read (| gas_limit |));
                                                          ("target_address", M.read (| to |));
                                                          ("caller",
                                                            M.read (|
                                                              M.SubPointer.get_struct_record_field (|
                                                                M.SubPointer.get_struct_record_field (|
                                                                  M.read (| interpreter |),
                                                                  "revm_interpreter::interpreter::Interpreter",
                                                                  "contract"
                                                                |),
                                                                "revm_interpreter::interpreter::contract::Contract",
                                                                "target_address"
                                                              |)
                                                            |));
                                                          ("bytecode_address", M.read (| to |));
                                                          ("value",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallValue::Transfer"
                                                              [
                                                                M.read (|
                                                                  M.get_constant (| "ruint::ZERO" |)
                                                                |)
                                                              ]);
                                                          ("scheme",
                                                            Value.StructTuple
                                                              "revm_interpreter::interpreter_action::call_inputs::CallScheme::StaticCall"
                                                              []);
                                                          ("is_static", Value.Bool true);
                                                          ("is_eof", Value.Bool false);
                                                          ("return_memory_offset",
                                                            M.read (| return_memory_offset |))
                                                        ]
                                                    ]
                                                  |))
                                              ]
                                          |) in
                                        let~ _ :=
                                          M.write (|
                                            M.SubPointer.get_struct_record_field (|
                                              M.read (| interpreter |),
                                              "revm_interpreter::interpreter::Interpreter",
                                              "instruction_result"
                                            |),
                                            Value.StructTuple
                                              "revm_interpreter::instruction_result::InstructionResult::CallOrCreate"
                                              []
                                          |) in
                                        M.alloc (| Value.Tuple [] |)))
                                  ]
                                |)))
                          ]
                        |)))
                  ]
                |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_static_call :
      M.IsFunction "revm_interpreter::instructions::contract::static_call" static_call.
  End contract.
End instructions.
