referrerpolicy=no-referrer-when-downgrade

pallet_revive/evm/api/
type_id.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17//! Ethereum Typed Transaction types
18use super::Byte;
19use codec::{Decode, DecodeWithMemTracking, Encode};
20use paste::paste;
21use rlp::Decodable;
22use scale_info::TypeInfo;
23use serde::{Deserialize, Deserializer, Serialize, Serializer};
24
25/// A macro to generate Transaction type identifiers
26/// See <https://ethereum.org/en/developers/docs/transactions/#typed-transaction-envelope>
27macro_rules! transaction_type {
28	($name:ident, $value:literal) => {
29		#[doc = concat!("Transaction type identifier: ", $value)]
30		#[derive(Clone, Default, Debug, Eq, PartialEq, DecodeWithMemTracking)]
31		pub struct $name;
32
33		// upper case const name
34		paste! {
35			#[doc = concat!("Transaction value for type identifier: ", $value)]
36			pub const [<$name:snake:upper>]: u8 = $value;
37		}
38
39		impl $name {
40			/// Convert to u8
41			pub fn value(&self) -> u8 {
42				$value
43			}
44
45			/// Convert to Byte
46			pub fn as_byte(&self) -> Byte {
47				Byte::from($value)
48			}
49
50			/// Try to convert from Byte
51			pub fn try_from_byte(byte: Byte) -> Result<Self, Byte> {
52				if byte.0 == $value { Ok(Self {}) } else { Err(byte) }
53			}
54		}
55
56		impl Decodable for $name {
57			fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
58				let value: u8 = rlp.as_val()?;
59				if value == $value {
60					Ok(Self {})
61				} else {
62					Err(rlp::DecoderError::Custom(concat!("expected ", $value)))
63				}
64			}
65		}
66
67		impl Encode for $name {
68			fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
69				f(&[$value])
70			}
71		}
72		impl Decode for $name {
73			fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
74				if $value == input.read_byte()? {
75					Ok(Self {})
76				} else {
77					Err(codec::Error::from(concat!("expected ", $value)))
78				}
79			}
80		}
81
82		impl TypeInfo for $name {
83			type Identity = u8;
84			fn type_info() -> scale_info::Type {
85				<u8 as TypeInfo>::type_info()
86			}
87		}
88
89		impl Serialize for $name {
90			fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91			where
92				S: Serializer,
93			{
94				serializer.serialize_str(concat!("0x", $value))
95			}
96		}
97		impl<'de> Deserialize<'de> for $name {
98			fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99			where
100				D: Deserializer<'de>,
101			{
102				let s: &str = Deserialize::deserialize(deserializer)?;
103				if s == concat!("0x", $value) {
104					Ok($name {})
105				} else {
106					Err(serde::de::Error::custom(concat!("expected ", $value)))
107				}
108			}
109		}
110	};
111}
112
113transaction_type!(TypeLegacy, 0);
114transaction_type!(TypeEip2930, 1);
115transaction_type!(TypeEip1559, 2);
116transaction_type!(TypeEip4844, 3);
117transaction_type!(TypeEip7702, 4);
118
119#[test]
120fn transaction_type() {
121	assert_eq!(TYPE_EIP2930, 1u8);
122}