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

Module secp256k1.
  Definition value_ECRECOVER : Value.t :=
    M.run
      ltac:(M.monadic
        (M.alloc (|
          Value.StructTuple
            "revm_precompile::PrecompileWithAddress"
            [
              M.call_closure (|
                M.get_function (| "revm_precompile::u64_to_address", [] |),
                [ Value.Integer IntegerKind.U64 1 ]
              |);
              Value.StructTuple
                "revm_primitives::precompile::Precompile::Standard"
                [
                  (* ReifyFnPointer *)
                  M.pointer_coercion
                    (M.get_function (| "revm_precompile::secp256k1::ec_recover_run", [] |))
                ]
            ]
        |))).
  
  Module secp256k1.
    (*
        pub fn ecrecover(sig: &B512, recid: u8, msg: &B256) -> Result<B256, secp256k1::Error> {
            let recid = RecoveryId::from_i32(recid as i32).expect("recovery ID is valid");
            let sig = RecoverableSignature::from_compact(sig.as_slice(), recid)?;
    
            let secp = Secp256k1::new();
            let msg = Message::from_digest(msg.0);
            let public = secp.recover_ecdsa(&msg, &sig)?;
    
            let mut hash = keccak256(&public.serialize_uncompressed()[1..]);
            hash[..12].fill(0);
            Ok(hash)
        }
    *)
    Definition ecrecover (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
      match ε, τ, α with
      | [], [], [ sig; recid; msg ] =>
        ltac:(M.monadic
          (let sig := M.alloc (| sig |) in
          let recid := M.alloc (| recid |) in
          let msg := M.alloc (| msg |) in
          M.catch_return (|
            ltac:(M.monadic
              (M.read (|
                let~ recid :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply
                          (Ty.path "core::result::Result")
                          []
                          [
                            Ty.path "secp256k1::ecdsa::recovery::RecoveryId";
                            Ty.path "secp256k1::Error"
                          ],
                        "expect",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_associated_function (|
                            Ty.path "secp256k1::ecdsa::recovery::RecoveryId",
                            "from_i32",
                            []
                          |),
                          [ M.rust_cast (M.read (| recid |)) ]
                        |);
                        M.read (| Value.String "recovery ID is valid" |)
                      ]
                    |)
                  |) in
                let~ sig :=
                  M.copy (|
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              []
                              [
                                Ty.path "secp256k1::ecdsa::recovery::RecoverableSignature";
                                Ty.path "secp256k1::Error"
                              ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.path "secp256k1::ecdsa::recovery::RecoverableSignature",
                                "from_compact",
                                []
                              |),
                              [
                                M.call_closure (|
                                  M.get_associated_function (|
                                    Ty.apply
                                      (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                      [ Value.Integer IntegerKind.Usize 64 ]
                                      [],
                                    "as_slice",
                                    []
                                  |),
                                  [ M.read (| sig |) ]
                                |);
                                M.read (| recid |)
                              ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Break",
                                0
                              |) in
                            let residual := M.copy (| γ0_0 |) in
                            M.alloc (|
                              M.never_to_any (|
                                M.read (|
                                  M.return_ (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::try_trait::FromResidual",
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          []
                                          [
                                            Ty.apply
                                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                              [ Value.Integer IntegerKind.Usize 32 ]
                                              [];
                                            Ty.path "secp256k1::Error"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            []
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "secp256k1::Error"
                                            ]
                                        ],
                                        "from_residual",
                                        []
                                      |),
                                      [ M.read (| residual |) ]
                                    |)
                                  |)
                                |)
                              |)
                            |)));
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Continue",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |)
                  |) in
                let~ secp :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply
                          (Ty.path "secp256k1::Secp256k1")
                          []
                          [ Ty.path "secp256k1::context::alloc_only::All" ],
                        "new",
                        []
                      |),
                      []
                    |)
                  |) in
                let~ msg :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.path "secp256k1::Message",
                        "from_digest",
                        []
                      |),
                      [
                        M.read (|
                          M.SubPointer.get_struct_tuple_field (|
                            M.read (| msg |),
                            "alloy_primitives::bits::fixed::FixedBytes",
                            0
                          |)
                        |)
                      ]
                    |)
                  |) in
                let~ public :=
                  M.copy (|
                    M.match_operator (|
                      M.alloc (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::try_trait::Try",
                            Ty.apply
                              (Ty.path "core::result::Result")
                              []
                              [ Ty.path "secp256k1::key::PublicKey"; Ty.path "secp256k1::Error" ],
                            [],
                            "branch",
                            []
                          |),
                          [
                            M.call_closure (|
                              M.get_associated_function (|
                                Ty.apply
                                  (Ty.path "secp256k1::Secp256k1")
                                  []
                                  [ Ty.path "secp256k1::context::alloc_only::All" ],
                                "recover_ecdsa",
                                []
                              |),
                              [ secp; msg; sig ]
                            |)
                          ]
                        |)
                      |),
                      [
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Break",
                                0
                              |) in
                            let residual := M.copy (| γ0_0 |) in
                            M.alloc (|
                              M.never_to_any (|
                                M.read (|
                                  M.return_ (|
                                    M.call_closure (|
                                      M.get_trait_method (|
                                        "core::ops::try_trait::FromResidual",
                                        Ty.apply
                                          (Ty.path "core::result::Result")
                                          []
                                          [
                                            Ty.apply
                                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                              [ Value.Integer IntegerKind.Usize 32 ]
                                              [];
                                            Ty.path "secp256k1::Error"
                                          ],
                                        [
                                          Ty.apply
                                            (Ty.path "core::result::Result")
                                            []
                                            [
                                              Ty.path "core::convert::Infallible";
                                              Ty.path "secp256k1::Error"
                                            ]
                                        ],
                                        "from_residual",
                                        []
                                      |),
                                      [ M.read (| residual |) ]
                                    |)
                                  |)
                                |)
                              |)
                            |)));
                        fun γ =>
                          ltac:(M.monadic
                            (let γ0_0 :=
                              M.SubPointer.get_struct_tuple_field (|
                                γ,
                                "core::ops::control_flow::ControlFlow::Continue",
                                0
                              |) in
                            let val := M.copy (| γ0_0 |) in
                            val))
                      ]
                    |)
                  |) in
                let~ hash :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_function (|
                        "alloy_primitives::utils::keccak256",
                        [
                          Ty.apply
                            (Ty.path "&")
                            []
                            [ Ty.apply (Ty.path "slice") [] [ Ty.path "u8" ] ]
                        ]
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::index::Index",
                            Ty.apply
                              (Ty.path "array")
                              [ Value.Integer IntegerKind.Usize 65 ]
                              [ Ty.path "u8" ],
                            [
                              Ty.apply
                                (Ty.path "core::ops::range::RangeFrom")
                                []
                                [ Ty.path "usize" ]
                            ],
                            "index",
                            []
                          |),
                          [
                            M.alloc (|
                              M.call_closure (|
                                M.get_associated_function (|
                                  Ty.path "secp256k1::key::PublicKey",
                                  "serialize_uncompressed",
                                  []
                                |),
                                [ public ]
                              |)
                            |);
                            Value.StructRecord
                              "core::ops::range::RangeFrom"
                              [ ("start", Value.Integer IntegerKind.Usize 1) ]
                          ]
                        |)
                      ]
                    |)
                  |) in
                let~ _ :=
                  M.alloc (|
                    M.call_closure (|
                      M.get_associated_function (|
                        Ty.apply (Ty.path "slice") [] [ Ty.path "u8" ],
                        "fill",
                        []
                      |),
                      [
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::index::IndexMut",
                            Ty.apply
                              (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                              [ Value.Integer IntegerKind.Usize 32 ]
                              [],
                            [ Ty.apply (Ty.path "core::ops::range::RangeTo") [] [ Ty.path "usize" ]
                            ],
                            "index_mut",
                            []
                          |),
                          [
                            hash;
                            Value.StructRecord
                              "core::ops::range::RangeTo"
                              [ ("end_", Value.Integer IntegerKind.Usize 12) ]
                          ]
                        |);
                        Value.Integer IntegerKind.U8 0
                      ]
                    |)
                  |) in
                M.alloc (| Value.StructTuple "core::result::Result::Ok" [ M.read (| hash |) ] |)
              |)))
          |)))
      | _, _, _ => M.impossible "wrong number of arguments"
      end.
    
    Axiom Function_ecrecover :
      M.IsFunction "revm_precompile::secp256k1::secp256k1::ecrecover" ecrecover.
  End secp256k1.
  
  (*
  pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult {
      const ECRECOVER_BASE: u64 = 3_000;
  
      if ECRECOVER_BASE > gas_limit {
          return Err(Error::OutOfGas);
      }
  
      let input = right_pad::<128>(input);
  
      // `v` must be a 32-byte big-endian integer equal to 27 or 28.
      if !(input[32..63].iter().all(|&b| b == 0) && matches!(input[63], 27 | 28)) {
          return Ok((ECRECOVER_BASE, Bytes::new()));
      }
  
      let msg = <&B256>::try_from(&input[0..32]).unwrap();
      let recid = input[63] - 27;
      let sig = <&B512>::try_from(&input[64..128]).unwrap();
  
      let out = secp256k1::ecrecover(sig, recid, msg)
          .map(|o| o.to_vec().into())
          .unwrap_or_default();
      Ok((ECRECOVER_BASE, out))
  }
  *)
  Definition ec_recover_run (ε : list Value.t) (τ : list Ty.t) (α : list Value.t) : M :=
    match ε, τ, α with
    | [], [], [ input; gas_limit ] =>
      ltac:(M.monadic
        (let input := M.alloc (| input |) in
        let gas_limit := M.alloc (| gas_limit |) 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.gt (|
                                M.read (|
                                  M.get_constant (|
                                    "revm_precompile::secp256k1::ec_recover_run::ECRECOVER_BASE"
                                  |)
                                |),
                                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 (|
                              M.return_ (|
                                Value.StructTuple
                                  "core::result::Result::Err"
                                  [
                                    Value.StructTuple
                                      "revm_primitives::precompile::PrecompileError::OutOfGas"
                                      []
                                  ]
                              |)
                            |)
                          |)
                        |)));
                    fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                  ]
                |) in
              let~ input :=
                M.alloc (|
                  M.call_closure (|
                    M.get_function (| "revm_precompile::utilities::right_pad", [] |),
                    [
                      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.read (| input |) ]
                          |)
                        ]
                      |)
                    ]
                  |)
                |) in
              let~ _ :=
                M.match_operator (|
                  M.alloc (| Value.Tuple [] |),
                  [
                    fun γ =>
                      ltac:(M.monadic
                        (let γ :=
                          M.use
                            (M.alloc (|
                              UnOp.not (|
                                LogicalOp.and (|
                                  M.call_closure (|
                                    M.get_trait_method (|
                                      "core::iter::traits::iterator::Iterator",
                                      Ty.apply
                                        (Ty.path "core::slice::iter::Iter")
                                        []
                                        [ Ty.path "u8" ],
                                      [],
                                      "all",
                                      [
                                        Ty.function
                                          [ Ty.tuple [ Ty.apply (Ty.path "&") [] [ Ty.path "u8" ] ]
                                          ]
                                          (Ty.path "bool")
                                      ]
                                    |),
                                    [
                                      M.alloc (|
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.apply (Ty.path "slice") [] [ Ty.path "u8" ],
                                            "iter",
                                            []
                                          |),
                                          [
                                            M.call_closure (|
                                              M.get_trait_method (|
                                                "core::ops::index::Index",
                                                Ty.apply
                                                  (Ty.path "array")
                                                  [ Value.Integer IntegerKind.Usize 128 ]
                                                  [ Ty.path "u8" ],
                                                [
                                                  Ty.apply
                                                    (Ty.path "core::ops::range::Range")
                                                    []
                                                    [ Ty.path "usize" ]
                                                ],
                                                "index",
                                                []
                                              |),
                                              [
                                                M.call_closure (|
                                                  M.get_trait_method (|
                                                    "core::ops::deref::Deref",
                                                    Ty.apply
                                                      (Ty.path "alloc::borrow::Cow")
                                                      []
                                                      [
                                                        Ty.apply
                                                          (Ty.path "array")
                                                          [ Value.Integer IntegerKind.Usize 128 ]
                                                          [ Ty.path "u8" ]
                                                      ],
                                                    [],
                                                    "deref",
                                                    []
                                                  |),
                                                  [ input ]
                                                |);
                                                Value.StructRecord
                                                  "core::ops::range::Range"
                                                  [
                                                    ("start", Value.Integer IntegerKind.Usize 32);
                                                    ("end_", Value.Integer IntegerKind.Usize 63)
                                                  ]
                                              ]
                                            |)
                                          ]
                                        |)
                                      |);
                                      M.closure
                                        (fun γ =>
                                          ltac:(M.monadic
                                            match γ with
                                            | [ α0 ] =>
                                              ltac:(M.monadic
                                                (M.match_operator (|
                                                  M.alloc (| α0 |),
                                                  [
                                                    fun γ =>
                                                      ltac:(M.monadic
                                                        (let γ := M.read (| γ |) in
                                                        let b := M.copy (| γ |) in
                                                        BinOp.eq (|
                                                          M.read (| b |),
                                                          Value.Integer IntegerKind.U8 0
                                                        |)))
                                                  ]
                                                |)))
                                            | _ => M.impossible "wrong number of arguments"
                                            end))
                                    ]
                                  |),
                                  ltac:(M.monadic
                                    (M.read (|
                                      M.match_operator (|
                                        M.SubPointer.get_array_field (|
                                          M.call_closure (|
                                            M.get_trait_method (|
                                              "core::ops::deref::Deref",
                                              Ty.apply
                                                (Ty.path "alloc::borrow::Cow")
                                                []
                                                [
                                                  Ty.apply
                                                    (Ty.path "array")
                                                    [ Value.Integer IntegerKind.Usize 128 ]
                                                    [ Ty.path "u8" ]
                                                ],
                                              [],
                                              "deref",
                                              []
                                            |),
                                            [ input ]
                                          |),
                                          M.alloc (| Value.Integer IntegerKind.Usize 63 |)
                                        |),
                                        [
                                          fun γ =>
                                            ltac:(M.monadic
                                              (M.find_or_pattern (|
                                                γ,
                                                [
                                                  fun γ =>
                                                    ltac:(M.monadic
                                                      (let _ :=
                                                        M.is_constant_or_break_match (|
                                                          M.read (| γ |),
                                                          Value.Integer IntegerKind.U8 27
                                                        |) in
                                                      Value.Tuple []));
                                                  fun γ =>
                                                    ltac:(M.monadic
                                                      (let _ :=
                                                        M.is_constant_or_break_match (|
                                                          M.read (| γ |),
                                                          Value.Integer IntegerKind.U8 28
                                                        |) in
                                                      Value.Tuple []))
                                                ],
                                                M.closure
                                                  (fun γ =>
                                                    ltac:(M.monadic
                                                      match γ with
                                                      | [] =>
                                                        ltac:(M.monadic
                                                          (M.alloc (| Value.Bool true |)))
                                                      | _ =>
                                                        M.impossible "wrong number of arguments"
                                                      end))
                                              |)));
                                          fun γ => ltac:(M.monadic (M.alloc (| Value.Bool false |)))
                                        ]
                                      |)
                                    |)))
                                |)
                              |)
                            |)) in
                        let _ :=
                          M.is_constant_or_break_match (| M.read (| γ |), Value.Bool true |) in
                        M.alloc (|
                          M.never_to_any (|
                            M.read (|
                              M.return_ (|
                                Value.StructTuple
                                  "core::result::Result::Ok"
                                  [
                                    Value.Tuple
                                      [
                                        M.read (|
                                          M.get_constant (|
                                            "revm_precompile::secp256k1::ec_recover_run::ECRECOVER_BASE"
                                          |)
                                        |);
                                        M.call_closure (|
                                          M.get_associated_function (|
                                            Ty.path "alloy_primitives::bytes_::Bytes",
                                            "new",
                                            []
                                          |),
                                          []
                                        |)
                                      ]
                                  ]
                              |)
                            |)
                          |)
                        |)));
                    fun γ => ltac:(M.monadic (M.alloc (| Value.Tuple [] |)))
                  ]
                |) in
              let~ msg :=
                M.alloc (|
                  M.call_closure (|
                    M.get_associated_function (|
                      Ty.apply
                        (Ty.path "core::result::Result")
                        []
                        [
                          Ty.apply
                            (Ty.path "&")
                            []
                            [
                              Ty.apply
                                (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                [ Value.Integer IntegerKind.Usize 32 ]
                                []
                            ];
                          Ty.path "core::array::TryFromSliceError"
                        ],
                      "unwrap",
                      []
                    |),
                    [
                      M.call_closure (|
                        M.get_trait_method (|
                          "core::convert::TryFrom",
                          Ty.apply
                            (Ty.path "&")
                            []
                            [
                              Ty.apply
                                (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                [ Value.Integer IntegerKind.Usize 32 ]
                                []
                            ],
                          [
                            Ty.apply
                              (Ty.path "&")
                              []
                              [ Ty.apply (Ty.path "slice") [] [ Ty.path "u8" ] ]
                          ],
                          "try_from",
                          []
                        |),
                        [
                          M.call_closure (|
                            M.get_trait_method (|
                              "core::ops::index::Index",
                              Ty.apply
                                (Ty.path "array")
                                [ Value.Integer IntegerKind.Usize 128 ]
                                [ Ty.path "u8" ],
                              [ Ty.apply (Ty.path "core::ops::range::Range") [] [ Ty.path "usize" ]
                              ],
                              "index",
                              []
                            |),
                            [
                              M.call_closure (|
                                M.get_trait_method (|
                                  "core::ops::deref::Deref",
                                  Ty.apply
                                    (Ty.path "alloc::borrow::Cow")
                                    []
                                    [
                                      Ty.apply
                                        (Ty.path "array")
                                        [ Value.Integer IntegerKind.Usize 128 ]
                                        [ Ty.path "u8" ]
                                    ],
                                  [],
                                  "deref",
                                  []
                                |),
                                [ input ]
                              |);
                              Value.StructRecord
                                "core::ops::range::Range"
                                [
                                  ("start", Value.Integer IntegerKind.Usize 0);
                                  ("end_", Value.Integer IntegerKind.Usize 32)
                                ]
                            ]
                          |)
                        ]
                      |)
                    ]
                  |)
                |) in
              let~ recid :=
                M.alloc (|
                  BinOp.Wrap.sub (|
                    M.read (|
                      M.SubPointer.get_array_field (|
                        M.call_closure (|
                          M.get_trait_method (|
                            "core::ops::deref::Deref",
                            Ty.apply
                              (Ty.path "alloc::borrow::Cow")
                              []
                              [
                                Ty.apply
                                  (Ty.path "array")
                                  [ Value.Integer IntegerKind.Usize 128 ]
                                  [ Ty.path "u8" ]
                              ],
                            [],
                            "deref",
                            []
                          |),
                          [ input ]
                        |),
                        M.alloc (| Value.Integer IntegerKind.Usize 63 |)
                      |)
                    |),
                    Value.Integer IntegerKind.U8 27
                  |)
                |) in
              let~ sig :=
                M.alloc (|
                  M.call_closure (|
                    M.get_associated_function (|
                      Ty.apply
                        (Ty.path "core::result::Result")
                        []
                        [
                          Ty.apply
                            (Ty.path "&")
                            []
                            [
                              Ty.apply
                                (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                [ Value.Integer IntegerKind.Usize 64 ]
                                []
                            ];
                          Ty.path "core::array::TryFromSliceError"
                        ],
                      "unwrap",
                      []
                    |),
                    [
                      M.call_closure (|
                        M.get_trait_method (|
                          "core::convert::TryFrom",
                          Ty.apply
                            (Ty.path "&")
                            []
                            [
                              Ty.apply
                                (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                [ Value.Integer IntegerKind.Usize 64 ]
                                []
                            ],
                          [
                            Ty.apply
                              (Ty.path "&")
                              []
                              [ Ty.apply (Ty.path "slice") [] [ Ty.path "u8" ] ]
                          ],
                          "try_from",
                          []
                        |),
                        [
                          M.call_closure (|
                            M.get_trait_method (|
                              "core::ops::index::Index",
                              Ty.apply
                                (Ty.path "array")
                                [ Value.Integer IntegerKind.Usize 128 ]
                                [ Ty.path "u8" ],
                              [ Ty.apply (Ty.path "core::ops::range::Range") [] [ Ty.path "usize" ]
                              ],
                              "index",
                              []
                            |),
                            [
                              M.call_closure (|
                                M.get_trait_method (|
                                  "core::ops::deref::Deref",
                                  Ty.apply
                                    (Ty.path "alloc::borrow::Cow")
                                    []
                                    [
                                      Ty.apply
                                        (Ty.path "array")
                                        [ Value.Integer IntegerKind.Usize 128 ]
                                        [ Ty.path "u8" ]
                                    ],
                                  [],
                                  "deref",
                                  []
                                |),
                                [ input ]
                              |);
                              Value.StructRecord
                                "core::ops::range::Range"
                                [
                                  ("start", Value.Integer IntegerKind.Usize 64);
                                  ("end_", Value.Integer IntegerKind.Usize 128)
                                ]
                            ]
                          |)
                        ]
                      |)
                    ]
                  |)
                |) in
              let~ out :=
                M.alloc (|
                  M.call_closure (|
                    M.get_associated_function (|
                      Ty.apply
                        (Ty.path "core::result::Result")
                        []
                        [ Ty.path "alloy_primitives::bytes_::Bytes"; Ty.path "secp256k1::Error" ],
                      "unwrap_or_default",
                      []
                    |),
                    [
                      M.call_closure (|
                        M.get_associated_function (|
                          Ty.apply
                            (Ty.path "core::result::Result")
                            []
                            [
                              Ty.apply
                                (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                [ Value.Integer IntegerKind.Usize 32 ]
                                [];
                              Ty.path "secp256k1::Error"
                            ],
                          "map",
                          [
                            Ty.path "alloy_primitives::bytes_::Bytes";
                            Ty.function
                              [
                                Ty.tuple
                                  [
                                    Ty.apply
                                      (Ty.path "alloy_primitives::bits::fixed::FixedBytes")
                                      [ Value.Integer IntegerKind.Usize 32 ]
                                      []
                                  ]
                              ]
                              (Ty.path "alloy_primitives::bytes_::Bytes")
                          ]
                        |),
                        [
                          M.call_closure (|
                            M.get_function (|
                              "revm_precompile::secp256k1::secp256k1::ecrecover",
                              []
                            |),
                            [ M.read (| sig |); M.read (| recid |); M.read (| msg |) ]
                          |);
                          M.closure
                            (fun γ =>
                              ltac:(M.monadic
                                match γ with
                                | [ α0 ] =>
                                  ltac:(M.monadic
                                    (M.match_operator (|
                                      M.alloc (| α0 |),
                                      [
                                        fun γ =>
                                          ltac:(M.monadic
                                            (let o := M.copy (| γ |) in
                                            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.path "u8" ],
                                                    "to_vec",
                                                    []
                                                  |),
                                                  [
                                                    M.call_closure (|
                                                      M.get_trait_method (|
                                                        "core::ops::deref::Deref",
                                                        Ty.apply
                                                          (Ty.path
                                                            "alloy_primitives::bits::fixed::FixedBytes")
                                                          [ Value.Integer IntegerKind.Usize 32 ]
                                                          [],
                                                        [],
                                                        "deref",
                                                        []
                                                      |),
                                                      [ o ]
                                                    |)
                                                  ]
                                                |)
                                              ]
                                            |)))
                                      ]
                                    |)))
                                | _ => M.impossible "wrong number of arguments"
                                end))
                        ]
                      |)
                    ]
                  |)
                |) in
              M.alloc (|
                Value.StructTuple
                  "core::result::Result::Ok"
                  [
                    Value.Tuple
                      [
                        M.read (|
                          M.get_constant (|
                            "revm_precompile::secp256k1::ec_recover_run::ECRECOVER_BASE"
                          |)
                        |);
                        M.read (| out |)
                      ]
                  ]
              |)
            |)))
        |)))
    | _, _, _ => M.impossible "wrong number of arguments"
    end.
  
  Axiom Function_ec_recover_run :
    M.IsFunction "revm_precompile::secp256k1::ec_recover_run" ec_recover_run.
  
  Module ec_recover_run.
    Definition value_ECRECOVER_BASE : Value.t :=
      M.run ltac:(M.monadic (M.alloc (| Value.Integer IntegerKind.U64 3000 |))).
  End ec_recover_run.
End secp256k1.
