difftreelog
Merge pull request #281 from UniqueNetwork/feature/contract-sponsoring-modes
in: master
Generous contract sponsoring mode
12 files changed
crates/evm-coder/src/abi.rsdiffbeforeafterboth1//! TODO: I misunterstood therminology, abi IS rlp encoded, so2//! this module should be replaced with rlp crate34#![allow(dead_code)]56#[cfg(not(feature = "std"))]7use alloc::vec::Vec;8use evm_core::ExitError;9use primitive_types::{H160, U256};1011use crate::{12 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},13 types::string,14};15use crate::execution::Result;1617const ABI_ALIGNMENT: usize = 32;1819#[derive(Clone)]20pub struct AbiReader<'i> {21 buf: &'i [u8],22 subresult_offset: usize,23 offset: usize,24}25impl<'i> AbiReader<'i> {26 pub fn new(buf: &'i [u8]) -> Self {27 Self {28 buf,29 subresult_offset: 0,30 offset: 0,31 }32 }33 pub fn new_call(buf: &'i [u8]) -> Result<(u32, Self)> {34 if buf.len() < 4 {35 return Err(Error::Error(ExitError::OutOfOffset));36 }37 let mut method_id = [0; 4];38 method_id.copy_from_slice(&buf[0..4]);3940 Ok((41 u32::from_be_bytes(method_id),42 Self {43 buf,44 subresult_offset: 4,45 offset: 4,46 },47 ))48 }4950 fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {51 if self.buf.len() - self.offset < ABI_ALIGNMENT {52 return Err(Error::Error(ExitError::OutOfOffset));53 }54 let mut block = [0; S];55 // Verify padding is empty56 if !self.buf[self.offset..self.offset + ABI_ALIGNMENT - S]57 .iter()58 .all(|&v| v == 0)59 {60 return Err(Error::Error(ExitError::InvalidRange));61 }62 block.copy_from_slice(63 &self.buf[self.offset + ABI_ALIGNMENT - S..self.offset + ABI_ALIGNMENT],64 );65 self.offset += ABI_ALIGNMENT;66 Ok(block)67 }6869 pub fn address(&mut self) -> Result<H160> {70 Ok(H160(self.read_padleft()?))71 }7273 pub fn bool(&mut self) -> Result<bool> {74 let data: [u8; 1] = self.read_padleft()?;75 match data[0] {76 0 => Ok(false),77 1 => Ok(true),78 _ => Err(Error::Error(ExitError::InvalidRange)),79 }80 }8182 pub fn bytes4(&mut self) -> Result<[u8; 4]> {83 self.read_padleft()84 }8586 pub fn bytes(&mut self) -> Result<Vec<u8>> {87 let mut subresult = self.subresult()?;88 let length = subresult.read_usize()?;89 if subresult.buf.len() <= subresult.offset + length {90 return Err(Error::Error(ExitError::OutOfOffset));91 }92 Ok(subresult.buf[subresult.offset..subresult.offset + length].into())93 }94 pub fn string(&mut self) -> Result<string> {95 string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))96 }9798 pub fn uint32(&mut self) -> Result<u32> {99 Ok(u32::from_be_bytes(self.read_padleft()?))100 }101102 pub fn uint128(&mut self) -> Result<u128> {103 Ok(u128::from_be_bytes(self.read_padleft()?))104 }105106 pub fn uint256(&mut self) -> Result<U256> {107 let buf: [u8; 32] = self.read_padleft()?;108 Ok(U256::from_big_endian(&buf))109 }110111 pub fn uint64(&mut self) -> Result<u64> {112 Ok(u64::from_be_bytes(self.read_padleft()?))113 }114115 pub fn read_usize(&mut self) -> Result<usize> {116 Ok(usize::from_be_bytes(self.read_padleft()?))117 }118119 fn subresult(&mut self) -> Result<AbiReader<'i>> {120 let offset = self.read_usize()?;121 if offset + self.subresult_offset > self.buf.len() {122 return Err(Error::Error(ExitError::InvalidRange));123 }124 Ok(AbiReader {125 buf: self.buf,126 subresult_offset: offset + self.subresult_offset,127 offset: offset + self.subresult_offset,128 })129 }130131 pub fn is_finished(&self) -> bool {132 self.buf.len() == self.offset133 }134}135136#[derive(Default)]137pub struct AbiWriter {138 static_part: Vec<u8>,139 dynamic_part: Vec<(usize, AbiWriter)>,140}141impl AbiWriter {142 pub fn new() -> Self {143 Self::default()144 }145 pub fn new_call(method_id: u32) -> Self {146 let mut val = Self::new();147 val.static_part.extend(&method_id.to_be_bytes());148 val149 }150151 fn write_padleft(&mut self, block: &[u8]) {152 assert!(block.len() <= ABI_ALIGNMENT);153 self.static_part154 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);155 self.static_part.extend(block);156 }157158 fn write_padright(&mut self, bytes: &[u8]) {159 assert!(bytes.len() <= ABI_ALIGNMENT);160 self.static_part.extend(bytes);161 self.static_part162 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);163 }164165 pub fn address(&mut self, address: &H160) {166 self.write_padleft(&address.0)167 }168169 pub fn bool(&mut self, value: &bool) {170 self.write_padleft(&[if *value { 1 } else { 0 }])171 }172173 pub fn uint8(&mut self, value: &u8) {174 self.write_padleft(&[*value])175 }176177 pub fn uint32(&mut self, value: &u32) {178 self.write_padleft(&u32::to_be_bytes(*value))179 }180181 pub fn uint128(&mut self, value: &u128) {182 self.write_padleft(&u128::to_be_bytes(*value))183 }184185 pub fn uint256(&mut self, value: &U256) {186 let mut out = [0; 32];187 value.to_big_endian(&mut out);188 self.write_padleft(&out)189 }190191 pub fn write_usize(&mut self, value: &usize) {192 self.write_padleft(&usize::to_be_bytes(*value))193 }194195 pub fn write_subresult(&mut self, result: Self) {196 self.dynamic_part.push((self.static_part.len(), result));197 // Empty block, to be filled later198 self.write_padleft(&[]);199 }200201 pub fn memory(&mut self, value: &[u8]) {202 let mut sub = Self::new();203 sub.write_usize(&value.len());204 for chunk in value.chunks(ABI_ALIGNMENT) {205 sub.write_padright(chunk);206 }207 self.write_subresult(sub);208 }209210 pub fn string(&mut self, value: &str) {211 self.memory(value.as_bytes())212 }213214 pub fn bytes(&mut self, value: &[u8]) {215 self.memory(value)216 }217218 pub fn finish(mut self) -> Vec<u8> {219 for (static_offset, part) in self.dynamic_part {220 let part_offset = self.static_part.len();221222 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);223 self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()224 ..static_offset + ABI_ALIGNMENT]225 .copy_from_slice(&encoded_dynamic_offset);226 self.static_part.extend(part.finish())227 }228 self.static_part229 }230}231232pub trait AbiRead<T> {233 fn abi_read(&mut self) -> Result<T>;234}235236macro_rules! impl_abi_readable {237 ($ty:ty, $method:ident) => {238 impl AbiRead<$ty> for AbiReader<'_> {239 fn abi_read(&mut self) -> Result<$ty> {240 self.$method()241 }242 }243 };244}245246impl_abi_readable!(u32, uint32);247impl_abi_readable!(u64, uint64);248impl_abi_readable!(u128, uint128);249impl_abi_readable!(U256, uint256);250impl_abi_readable!(H160, address);251impl_abi_readable!(Vec<u8>, bytes);252impl_abi_readable!(bool, bool);253impl_abi_readable!(string, string);254255mod sealed {256 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead257 pub trait CanBePlacedInVec {}258}259260impl sealed::CanBePlacedInVec for U256 {}261impl sealed::CanBePlacedInVec for string {}262impl sealed::CanBePlacedInVec for H160 {}263264impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>265where266 Self: AbiRead<R>,267{268 fn abi_read(&mut self) -> Result<Vec<R>> {269 let mut sub = self.subresult()?;270 let size = sub.read_usize()?;271 sub.subresult_offset = sub.offset;272 let mut out = Vec::with_capacity(size);273 for _ in 0..size {274 out.push(<Self as AbiRead<R>>::abi_read(&mut sub)?);275 }276 Ok(out)277 }278}279280macro_rules! impl_tuples {281 ($($ident:ident)+) => {282 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}283 impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>284 where285 $(Self: AbiRead<$ident>),+286 {287 fn abi_read(&mut self) -> Result<($($ident,)+)> {288 let mut subresult = self.subresult()?;289 Ok((290 $(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+291 ))292 }293 }294 };295}296297impl_tuples! {A}298impl_tuples! {A B}299impl_tuples! {A B C}300impl_tuples! {A B C D}301impl_tuples! {A B C D E}302impl_tuples! {A B C D E F}303impl_tuples! {A B C D E F G}304impl_tuples! {A B C D E F G H}305impl_tuples! {A B C D E F G H I}306impl_tuples! {A B C D E F G H I J}307308pub trait AbiWrite {309 fn abi_write(&self, writer: &mut AbiWriter);310 fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {311 let mut writer = AbiWriter::new();312 self.abi_write(&mut writer);313 Ok(writer.into())314 }315}316317impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {318 // this particular AbiWrite implementation should be split to another trait,319 // which only implements [`to_result`]320 //321 // But due to lack of specialization feature in stable Rust, we can't have322 // blanket impl of this trait `for T where T: AbiWrite`, so here we abusing323 // default trait methods for it324 fn abi_write(&self, _writer: &mut AbiWriter) {325 debug_assert!(false, "shouldn't be called, see comment")326 }327 fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {328 match self {329 Ok(v) => Ok(WithPostDispatchInfo {330 post_info: v.post_info.clone(),331 data: {332 let mut out = AbiWriter::new();333 v.data.abi_write(&mut out);334 out335 },336 }),337 Err(e) => Err(e.clone()),338 }339 }340}341342macro_rules! impl_abi_writeable {343 ($ty:ty, $method:ident) => {344 impl AbiWrite for $ty {345 fn abi_write(&self, writer: &mut AbiWriter) {346 writer.$method(&self)347 }348 }349 };350}351352impl_abi_writeable!(u8, uint8);353impl_abi_writeable!(u32, uint32);354impl_abi_writeable!(u128, uint128);355impl_abi_writeable!(U256, uint256);356impl_abi_writeable!(H160, address);357impl_abi_writeable!(bool, bool);358impl_abi_writeable!(&str, string);359impl AbiWrite for &string {360 fn abi_write(&self, writer: &mut AbiWriter) {361 writer.string(self)362 }363}364impl AbiWrite for &Vec<u8> {365 fn abi_write(&self, writer: &mut AbiWriter) {366 writer.bytes(self)367 }368}369370impl AbiWrite for () {371 fn abi_write(&self, _writer: &mut AbiWriter) {}372}373374#[macro_export]375macro_rules! abi_decode {376 ($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {377 $(378 let $name = $reader.$typ()?;379 )+380 }381}382#[macro_export]383macro_rules! abi_encode {384 ($($typ:ident($value:expr)),* $(,)?) => {{385 #[allow(unused_mut)]386 let mut writer = ::evm_coder::abi::AbiWriter::new();387 $(388 writer.$typ($value);389 )*390 writer391 }};392 (call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{393 #[allow(unused_mut)]394 let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);395 $(396 writer.$typ($value);397 )*398 writer399 }}400}401402#[cfg(test)]403pub mod test {404 use crate::{405 abi::AbiRead,406 types::{string, uint256},407 };408409 use super::{AbiReader, AbiWriter};410 use hex_literal::hex;411412 #[test]413 fn dynamic_after_static() {414 let mut encoder = AbiWriter::new();415 encoder.bool(&true);416 encoder.string("test");417 let encoded = encoder.finish();418419 let mut encoder = AbiWriter::new();420 encoder.bool(&true);421 // Offset to subresult422 encoder.uint32(&(32 * 2));423 // Len of "test"424 encoder.uint32(&4);425 encoder.write_padright(&[b't', b'e', b's', b't']);426 let alternative_encoded = encoder.finish();427428 assert_eq!(encoded, alternative_encoded);429430 let mut decoder = AbiReader::new(&encoded);431 assert_eq!(decoder.bool().unwrap(), true);432 assert_eq!(decoder.string().unwrap(), "test");433 }434435 #[test]436 fn mint_sample() {437 let (call, mut decoder) = AbiReader::new_call(&hex!(438 "439 50bb4e7f440 000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374441 0000000000000000000000000000000000000000000000000000000000000001442 0000000000000000000000000000000000000000000000000000000000000060443 0000000000000000000000000000000000000000000000000000000000000008444 5465737420555249000000000000000000000000000000000000000000000000445 "446 ))447 .unwrap();448 assert_eq!(call, 0x50bb4e7f);449 assert_eq!(450 format!("{:?}", decoder.address().unwrap()),451 "0xad2c0954693c2b5404b7e50967d3481bea432374"452 );453 assert_eq!(decoder.uint32().unwrap(), 1);454 assert_eq!(decoder.string().unwrap(), "Test URI");455 }456457 #[test]458 fn mint_bulk() {459 let (call, mut decoder) = AbiReader::new_call(&hex!(460 "461 36543006462 00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address463 0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]464 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]465466 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem467 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem468 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem469470 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60471 0000000000000000000000000000000000000000000000000000000000000040 // offset of string472 000000000000000000000000000000000000000000000000000000000000000a // size of string473 5465737420555249203000000000000000000000000000000000000000000000 // string474475 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0476 0000000000000000000000000000000000000000000000000000000000000040 // offset of string477 000000000000000000000000000000000000000000000000000000000000000a // size of string478 5465737420555249203100000000000000000000000000000000000000000000 // string479480 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160481 0000000000000000000000000000000000000000000000000000000000000040 // offset of string482 000000000000000000000000000000000000000000000000000000000000000a // size of string483 5465737420555249203200000000000000000000000000000000000000000000 // string484 "485 ))486 .unwrap();487 assert_eq!(call, 0x36543006);488 let _ = decoder.address().unwrap();489 let data =490 <AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();491 assert_eq!(492 data,493 vec![494 (1.into(), "Test URI 0".to_string()),495 (11.into(), "Test URI 1".to_string()),496 (12.into(), "Test URI 2".to_string())497 ]498 );499 }500}1//! TODO: I misunterstood therminology, abi IS rlp encoded, so2//! this module should be replaced with rlp crate34#![allow(dead_code)]56#[cfg(not(feature = "std"))]7use alloc::vec::Vec;8use evm_core::ExitError;9use primitive_types::{H160, U256};1011use crate::{12 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},13 types::string,14};15use crate::execution::Result;1617const ABI_ALIGNMENT: usize = 32;1819#[derive(Clone)]20pub struct AbiReader<'i> {21 buf: &'i [u8],22 subresult_offset: usize,23 offset: usize,24}25impl<'i> AbiReader<'i> {26 pub fn new(buf: &'i [u8]) -> Self {27 Self {28 buf,29 subresult_offset: 0,30 offset: 0,31 }32 }33 pub fn new_call(buf: &'i [u8]) -> Result<(u32, Self)> {34 if buf.len() < 4 {35 return Err(Error::Error(ExitError::OutOfOffset));36 }37 let mut method_id = [0; 4];38 method_id.copy_from_slice(&buf[0..4]);3940 Ok((41 u32::from_be_bytes(method_id),42 Self {43 buf,44 subresult_offset: 4,45 offset: 4,46 },47 ))48 }4950 fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {51 if self.buf.len() - self.offset < ABI_ALIGNMENT {52 return Err(Error::Error(ExitError::OutOfOffset));53 }54 let mut block = [0; S];55 // Verify padding is empty56 if !self.buf[self.offset..self.offset + ABI_ALIGNMENT - S]57 .iter()58 .all(|&v| v == 0)59 {60 return Err(Error::Error(ExitError::InvalidRange));61 }62 block.copy_from_slice(63 &self.buf[self.offset + ABI_ALIGNMENT - S..self.offset + ABI_ALIGNMENT],64 );65 self.offset += ABI_ALIGNMENT;66 Ok(block)67 }6869 pub fn address(&mut self) -> Result<H160> {70 Ok(H160(self.read_padleft()?))71 }7273 pub fn bool(&mut self) -> Result<bool> {74 let data: [u8; 1] = self.read_padleft()?;75 match data[0] {76 0 => Ok(false),77 1 => Ok(true),78 _ => Err(Error::Error(ExitError::InvalidRange)),79 }80 }8182 pub fn bytes4(&mut self) -> Result<[u8; 4]> {83 self.read_padleft()84 }8586 pub fn bytes(&mut self) -> Result<Vec<u8>> {87 let mut subresult = self.subresult()?;88 let length = subresult.read_usize()?;89 if subresult.buf.len() <= subresult.offset + length {90 return Err(Error::Error(ExitError::OutOfOffset));91 }92 Ok(subresult.buf[subresult.offset..subresult.offset + length].into())93 }94 pub fn string(&mut self) -> Result<string> {95 string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))96 }9798 pub fn uint8(&mut self) -> Result<u8> {99 Ok(self.read_padleft::<1>()?[0])100 }101102 pub fn uint32(&mut self) -> Result<u32> {103 Ok(u32::from_be_bytes(self.read_padleft()?))104 }105106 pub fn uint128(&mut self) -> Result<u128> {107 Ok(u128::from_be_bytes(self.read_padleft()?))108 }109110 pub fn uint256(&mut self) -> Result<U256> {111 let buf: [u8; 32] = self.read_padleft()?;112 Ok(U256::from_big_endian(&buf))113 }114115 pub fn uint64(&mut self) -> Result<u64> {116 Ok(u64::from_be_bytes(self.read_padleft()?))117 }118119 pub fn read_usize(&mut self) -> Result<usize> {120 Ok(usize::from_be_bytes(self.read_padleft()?))121 }122123 fn subresult(&mut self) -> Result<AbiReader<'i>> {124 let offset = self.read_usize()?;125 if offset + self.subresult_offset > self.buf.len() {126 return Err(Error::Error(ExitError::InvalidRange));127 }128 Ok(AbiReader {129 buf: self.buf,130 subresult_offset: offset + self.subresult_offset,131 offset: offset + self.subresult_offset,132 })133 }134135 pub fn is_finished(&self) -> bool {136 self.buf.len() == self.offset137 }138}139140#[derive(Default)]141pub struct AbiWriter {142 static_part: Vec<u8>,143 dynamic_part: Vec<(usize, AbiWriter)>,144}145impl AbiWriter {146 pub fn new() -> Self {147 Self::default()148 }149 pub fn new_call(method_id: u32) -> Self {150 let mut val = Self::new();151 val.static_part.extend(&method_id.to_be_bytes());152 val153 }154155 fn write_padleft(&mut self, block: &[u8]) {156 assert!(block.len() <= ABI_ALIGNMENT);157 self.static_part158 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);159 self.static_part.extend(block);160 }161162 fn write_padright(&mut self, bytes: &[u8]) {163 assert!(bytes.len() <= ABI_ALIGNMENT);164 self.static_part.extend(bytes);165 self.static_part166 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);167 }168169 pub fn address(&mut self, address: &H160) {170 self.write_padleft(&address.0)171 }172173 pub fn bool(&mut self, value: &bool) {174 self.write_padleft(&[if *value { 1 } else { 0 }])175 }176177 pub fn uint8(&mut self, value: &u8) {178 self.write_padleft(&[*value])179 }180181 pub fn uint32(&mut self, value: &u32) {182 self.write_padleft(&u32::to_be_bytes(*value))183 }184185 pub fn uint128(&mut self, value: &u128) {186 self.write_padleft(&u128::to_be_bytes(*value))187 }188189 pub fn uint256(&mut self, value: &U256) {190 let mut out = [0; 32];191 value.to_big_endian(&mut out);192 self.write_padleft(&out)193 }194195 pub fn write_usize(&mut self, value: &usize) {196 self.write_padleft(&usize::to_be_bytes(*value))197 }198199 pub fn write_subresult(&mut self, result: Self) {200 self.dynamic_part.push((self.static_part.len(), result));201 // Empty block, to be filled later202 self.write_padleft(&[]);203 }204205 pub fn memory(&mut self, value: &[u8]) {206 let mut sub = Self::new();207 sub.write_usize(&value.len());208 for chunk in value.chunks(ABI_ALIGNMENT) {209 sub.write_padright(chunk);210 }211 self.write_subresult(sub);212 }213214 pub fn string(&mut self, value: &str) {215 self.memory(value.as_bytes())216 }217218 pub fn bytes(&mut self, value: &[u8]) {219 self.memory(value)220 }221222 pub fn finish(mut self) -> Vec<u8> {223 for (static_offset, part) in self.dynamic_part {224 let part_offset = self.static_part.len();225226 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);227 self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()228 ..static_offset + ABI_ALIGNMENT]229 .copy_from_slice(&encoded_dynamic_offset);230 self.static_part.extend(part.finish())231 }232 self.static_part233 }234}235236pub trait AbiRead<T> {237 fn abi_read(&mut self) -> Result<T>;238}239240macro_rules! impl_abi_readable {241 ($ty:ty, $method:ident) => {242 impl AbiRead<$ty> for AbiReader<'_> {243 fn abi_read(&mut self) -> Result<$ty> {244 self.$method()245 }246 }247 };248}249250impl_abi_readable!(u8, uint8);251impl_abi_readable!(u32, uint32);252impl_abi_readable!(u64, uint64);253impl_abi_readable!(u128, uint128);254impl_abi_readable!(U256, uint256);255impl_abi_readable!(H160, address);256impl_abi_readable!(Vec<u8>, bytes);257impl_abi_readable!(bool, bool);258impl_abi_readable!(string, string);259260mod sealed {261 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead262 pub trait CanBePlacedInVec {}263}264265impl sealed::CanBePlacedInVec for U256 {}266impl sealed::CanBePlacedInVec for string {}267impl sealed::CanBePlacedInVec for H160 {}268269impl<R: sealed::CanBePlacedInVec> AbiRead<Vec<R>> for AbiReader<'_>270where271 Self: AbiRead<R>,272{273 fn abi_read(&mut self) -> Result<Vec<R>> {274 let mut sub = self.subresult()?;275 let size = sub.read_usize()?;276 sub.subresult_offset = sub.offset;277 let mut out = Vec::with_capacity(size);278 for _ in 0..size {279 out.push(<Self as AbiRead<R>>::abi_read(&mut sub)?);280 }281 Ok(out)282 }283}284285macro_rules! impl_tuples {286 ($($ident:ident)+) => {287 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}288 impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>289 where290 $(Self: AbiRead<$ident>),+291 {292 fn abi_read(&mut self) -> Result<($($ident,)+)> {293 let mut subresult = self.subresult()?;294 Ok((295 $(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+296 ))297 }298 }299 };300}301302impl_tuples! {A}303impl_tuples! {A B}304impl_tuples! {A B C}305impl_tuples! {A B C D}306impl_tuples! {A B C D E}307impl_tuples! {A B C D E F}308impl_tuples! {A B C D E F G}309impl_tuples! {A B C D E F G H}310impl_tuples! {A B C D E F G H I}311impl_tuples! {A B C D E F G H I J}312313pub trait AbiWrite {314 fn abi_write(&self, writer: &mut AbiWriter);315 fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {316 let mut writer = AbiWriter::new();317 self.abi_write(&mut writer);318 Ok(writer.into())319 }320}321322impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {323 // this particular AbiWrite implementation should be split to another trait,324 // which only implements [`to_result`]325 //326 // But due to lack of specialization feature in stable Rust, we can't have327 // blanket impl of this trait `for T where T: AbiWrite`, so here we abusing328 // default trait methods for it329 fn abi_write(&self, _writer: &mut AbiWriter) {330 debug_assert!(false, "shouldn't be called, see comment")331 }332 fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {333 match self {334 Ok(v) => Ok(WithPostDispatchInfo {335 post_info: v.post_info.clone(),336 data: {337 let mut out = AbiWriter::new();338 v.data.abi_write(&mut out);339 out340 },341 }),342 Err(e) => Err(e.clone()),343 }344 }345}346347macro_rules! impl_abi_writeable {348 ($ty:ty, $method:ident) => {349 impl AbiWrite for $ty {350 fn abi_write(&self, writer: &mut AbiWriter) {351 writer.$method(&self)352 }353 }354 };355}356357impl_abi_writeable!(u8, uint8);358impl_abi_writeable!(u32, uint32);359impl_abi_writeable!(u128, uint128);360impl_abi_writeable!(U256, uint256);361impl_abi_writeable!(H160, address);362impl_abi_writeable!(bool, bool);363impl_abi_writeable!(&str, string);364impl AbiWrite for &string {365 fn abi_write(&self, writer: &mut AbiWriter) {366 writer.string(self)367 }368}369impl AbiWrite for &Vec<u8> {370 fn abi_write(&self, writer: &mut AbiWriter) {371 writer.bytes(self)372 }373}374375impl AbiWrite for () {376 fn abi_write(&self, _writer: &mut AbiWriter) {}377}378379#[macro_export]380macro_rules! abi_decode {381 ($reader:expr, $($name:ident: $typ:ident),+ $(,)?) => {382 $(383 let $name = $reader.$typ()?;384 )+385 }386}387#[macro_export]388macro_rules! abi_encode {389 ($($typ:ident($value:expr)),* $(,)?) => {{390 #[allow(unused_mut)]391 let mut writer = ::evm_coder::abi::AbiWriter::new();392 $(393 writer.$typ($value);394 )*395 writer396 }};397 (call $val:expr; $($typ:ident($value:expr)),* $(,)?) => {{398 #[allow(unused_mut)]399 let mut writer = ::evm_coder::abi::AbiWriter::new_call($val);400 $(401 writer.$typ($value);402 )*403 writer404 }}405}406407#[cfg(test)]408pub mod test {409 use crate::{410 abi::AbiRead,411 types::{string, uint256},412 };413414 use super::{AbiReader, AbiWriter};415 use hex_literal::hex;416417 #[test]418 fn dynamic_after_static() {419 let mut encoder = AbiWriter::new();420 encoder.bool(&true);421 encoder.string("test");422 let encoded = encoder.finish();423424 let mut encoder = AbiWriter::new();425 encoder.bool(&true);426 // Offset to subresult427 encoder.uint32(&(32 * 2));428 // Len of "test"429 encoder.uint32(&4);430 encoder.write_padright(&[b't', b'e', b's', b't']);431 let alternative_encoded = encoder.finish();432433 assert_eq!(encoded, alternative_encoded);434435 let mut decoder = AbiReader::new(&encoded);436 assert_eq!(decoder.bool().unwrap(), true);437 assert_eq!(decoder.string().unwrap(), "test");438 }439440 #[test]441 fn mint_sample() {442 let (call, mut decoder) = AbiReader::new_call(&hex!(443 "444 50bb4e7f445 000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374446 0000000000000000000000000000000000000000000000000000000000000001447 0000000000000000000000000000000000000000000000000000000000000060448 0000000000000000000000000000000000000000000000000000000000000008449 5465737420555249000000000000000000000000000000000000000000000000450 "451 ))452 .unwrap();453 assert_eq!(call, 0x50bb4e7f);454 assert_eq!(455 format!("{:?}", decoder.address().unwrap()),456 "0xad2c0954693c2b5404b7e50967d3481bea432374"457 );458 assert_eq!(decoder.uint32().unwrap(), 1);459 assert_eq!(decoder.string().unwrap(), "Test URI");460 }461462 #[test]463 fn mint_bulk() {464 let (call, mut decoder) = AbiReader::new_call(&hex!(465 "466 36543006467 00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address468 0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]469 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]470471 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem472 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem473 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem474475 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60476 0000000000000000000000000000000000000000000000000000000000000040 // offset of string477 000000000000000000000000000000000000000000000000000000000000000a // size of string478 5465737420555249203000000000000000000000000000000000000000000000 // string479480 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0481 0000000000000000000000000000000000000000000000000000000000000040 // offset of string482 000000000000000000000000000000000000000000000000000000000000000a // size of string483 5465737420555249203100000000000000000000000000000000000000000000 // string484485 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160486 0000000000000000000000000000000000000000000000000000000000000040 // offset of string487 000000000000000000000000000000000000000000000000000000000000000a // size of string488 5465737420555249203200000000000000000000000000000000000000000000 // string489 "490 ))491 .unwrap();492 assert_eq!(call, 0x36543006);493 let _ = decoder.address().unwrap();494 let data =495 <AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();496 assert_eq!(497 data,498 vec![499 (1.into(), "Test URI 0".to_string()),500 (11.into(), "Test URI 1".to_string()),501 (12.into(), "Test URI 2".to_string())502 ]503 );504 }505}pallets/evm-contract-helpers/exp.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/exp.rs
+++ /dev/null
@@ -1,1474 +0,0 @@
-#![feature(prelude_import)]
-#[prelude_import]
-use std::prelude::rust_2018::*;
-#[macro_use]
-extern crate std;
-pub use pallet::*;
-pub use eth::*;
-pub mod eth {
- use core::marker::PhantomData;
- use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*};
- use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
- use pallet_evm::{ExitReason, ExitRevert, OnCreate, OnMethodCall, PrecompileOutput};
- use sp_core::H160;
- use crate::{
- AllowlistEnabled, Config, Owner, Pallet, SelfSponsoring, SponsorBasket, SponsoringRateLimit,
- };
- use frame_support::traits::Get;
- use up_sponsorship::SponsorshipHandler;
- use sp_std::{convert::TryInto, vec::Vec};
- struct ContractHelpers<T: Config>(SubstrateRecorder<T>);
- impl<T: Config> WithRecorder<T> for ContractHelpers<T> {
- fn recorder(&self) -> &SubstrateRecorder<T> {
- &self.0
- }
- fn into_recorder(self) -> SubstrateRecorder<T> {
- self.0
- }
- }
- impl<T: Config> ContractHelpers<T> {
- fn contract_owner(&self, contract_address: address) -> Result<address> {
- Ok(<Owner<T>>::get(contract_address))
- }
- fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {
- Ok(<SelfSponsoring<T>>::get(contract_address))
- }
- fn toggle_sponsoring(
- &mut self,
- caller: caller,
- contract_address: address,
- enabled: bool,
- ) -> Result<void> {
- <Pallet<T>>::ensure_owner(contract_address, caller)?;
- <Pallet<T>>::toggle_sponsoring(contract_address, enabled);
- Ok(())
- }
- fn set_sponsoring_rate_limit(
- &mut self,
- caller: caller,
- contract_address: address,
- rate_limit: uint32,
- ) -> Result<void> {
- <Pallet<T>>::ensure_owner(contract_address, caller)?;
- <Pallet<T>>::set_sponsoring_rate_limit(contract_address, rate_limit.into());
- Ok(())
- }
- fn get_sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {
- Ok(<SponsoringRateLimit<T>>::get(contract_address)
- .try_into()
- .map_err(|_| "rate limit > u32::MAX")?)
- }
- fn allowed(&self, contract_address: address, user: address) -> Result<bool> {
- Ok(<Pallet<T>>::allowed(contract_address, user, true))
- }
- fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {
- Ok(<AllowlistEnabled<T>>::get(contract_address))
- }
- fn toggle_allowlist(
- &mut self,
- caller: caller,
- contract_address: address,
- enabled: bool,
- ) -> Result<void> {
- <Pallet<T>>::ensure_owner(contract_address, caller)?;
- <Pallet<T>>::toggle_allowlist(contract_address, enabled);
- Ok(())
- }
- fn toggle_allowed(
- &mut self,
- caller: caller,
- contract_address: address,
- user: address,
- allowed: bool,
- ) -> Result<void> {
- <Pallet<T>>::ensure_owner(contract_address, caller)?;
- <Pallet<T>>::toggle_allowed(contract_address, user, allowed);
- Ok(())
- }
- }
- pub enum ContractHelpersCall<T: Config> {
- ERC165Call(::evm_coder::ERC165Call, PhantomData<(T)>),
- ContractOwner {
- contract_address: address,
- },
- SponsoringEnabled {
- contract_address: address,
- },
- ToggleSponsoring {
- contract_address: address,
- enabled: bool,
- },
- SetSponsoringRateLimit {
- contract_address: address,
- rate_limit: uint32,
- },
- GetSponsoringRateLimit {
- contract_address: address,
- },
- Allowed {
- contract_address: address,
- user: address,
- },
- AllowlistEnabled {
- contract_address: address,
- },
- ToggleAllowlist {
- contract_address: address,
- enabled: bool,
- },
- ToggleAllowed {
- contract_address: address,
- user: address,
- allowed: bool,
- },
- }
- #[automatically_derived]
- #[allow(unused_qualifications)]
- impl<T: ::core::fmt::Debug + Config> ::core::fmt::Debug for ContractHelpersCall<T> {
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- match (&*self,) {
- (&ContractHelpersCall::ERC165Call(ref __self_0, ref __self_1),) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_tuple(f, "ERC165Call");
- let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0));
- let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_1));
- ::core::fmt::DebugTuple::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::ContractOwner {
- contract_address: ref __self_0,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "ContractOwner");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::SponsoringEnabled {
- contract_address: ref __self_0,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "SponsoringEnabled");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::ToggleSponsoring {
- contract_address: ref __self_0,
- enabled: ref __self_1,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "ToggleSponsoring");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "enabled",
- &&(*__self_1),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::SetSponsoringRateLimit {
- contract_address: ref __self_0,
- rate_limit: ref __self_1,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "SetSponsoringRateLimit");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "rate_limit",
- &&(*__self_1),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::GetSponsoringRateLimit {
- contract_address: ref __self_0,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "GetSponsoringRateLimit");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::Allowed {
- contract_address: ref __self_0,
- user: ref __self_1,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "Allowed");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- let _ =
- ::core::fmt::DebugStruct::field(debug_trait_builder, "user", &&(*__self_1));
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::AllowlistEnabled {
- contract_address: ref __self_0,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "AllowlistEnabled");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::ToggleAllowlist {
- contract_address: ref __self_0,
- enabled: ref __self_1,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "ToggleAllowlist");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "enabled",
- &&(*__self_1),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- (&ContractHelpersCall::ToggleAllowed {
- contract_address: ref __self_0,
- user: ref __self_1,
- allowed: ref __self_2,
- },) => {
- let debug_trait_builder =
- &mut ::core::fmt::Formatter::debug_struct(f, "ToggleAllowed");
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "contract_address",
- &&(*__self_0),
- );
- let _ =
- ::core::fmt::DebugStruct::field(debug_trait_builder, "user", &&(*__self_1));
- let _ = ::core::fmt::DebugStruct::field(
- debug_trait_builder,
- "allowed",
- &&(*__self_2),
- );
- ::core::fmt::DebugStruct::finish(debug_trait_builder)
- }
- }
- }
- }
- impl<T: Config> ContractHelpersCall<T> {
- #[doc = "contractOwner(address)"]
- const CONTRACT_OWNER: u32 = 1364373836u32;
- #[doc = "sponsoringEnabled(address)"]
- const SPONSORING_ENABLED: u32 = 1613225057u32;
- #[doc = "toggleSponsoring(address,bool)"]
- const TOGGLE_SPONSORING: u32 = 4239158662u32;
- #[doc = "setSponsoringRateLimit(address,uint32)"]
- const SET_SPONSORING_RATE_LIMIT: u32 = 2008467720u32;
- #[doc = "getSponsoringRateLimit(address)"]
- const GET_SPONSORING_RATE_LIMIT: u32 = 1628240573u32;
- #[doc = "allowed(address,address)"]
- const ALLOWED: u32 = 1550156133u32;
- #[doc = "allowlistEnabled(address)"]
- const ALLOWLIST_ENABLED: u32 = 3346198380u32;
- #[doc = "toggleAllowlist(address,bool)"]
- const TOGGLE_ALLOWLIST: u32 = 920527093u32;
- #[doc = "toggleAllowed(address,address,bool)"]
- const TOGGLE_ALLOWED: u32 = 1191627804u32;
- pub const fn interface_id() -> u32 {
- let mut interface_id = 0;
- interface_id ^= Self::CONTRACT_OWNER;
- interface_id ^= Self::SPONSORING_ENABLED;
- interface_id ^= Self::TOGGLE_SPONSORING;
- interface_id ^= Self::SET_SPONSORING_RATE_LIMIT;
- interface_id ^= Self::GET_SPONSORING_RATE_LIMIT;
- interface_id ^= Self::ALLOWED;
- interface_id ^= Self::ALLOWLIST_ENABLED;
- interface_id ^= Self::TOGGLE_ALLOWLIST;
- interface_id ^= Self::TOGGLE_ALLOWED;
- interface_id
- }
- pub fn supports_interface(interface_id: u32) -> bool {
- interface_id != 0xffffff
- && (interface_id == ::evm_coder::ERC165Call::INTERFACE_ID
- || interface_id == Self::interface_id())
- }
- pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
- use evm_coder::solidity::*;
- use core::fmt::Write;
- let interface = SolidityInterface {
- name: "ContractHelpers",
- selector: Self::interface_id(),
- is: &["Dummy", "ERC165"],
- functions: (
- SolidityFunction {
- docs: &[],
- selector: "contractOwner(address) 5152b14c",
- name: "contractOwner",
- mutability: SolidityMutability::View,
- args: (<NamedArgument<address>>::new("contractAddress"),),
- result: <UnnamedArgument<address>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "sponsoringEnabled(address) 6027dc61",
- name: "sponsoringEnabled",
- mutability: SolidityMutability::View,
- args: (<NamedArgument<address>>::new("contractAddress"),),
- result: <UnnamedArgument<bool>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "toggleSponsoring(address,bool) fcac6d86",
- name: "toggleSponsoring",
- mutability: SolidityMutability::Mutable,
- args: (
- <NamedArgument<address>>::new("contractAddress"),
- <NamedArgument<bool>>::new("enabled"),
- ),
- result: <UnnamedArgument<void>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "setSponsoringRateLimit(address,uint32) 77b6c908",
- name: "setSponsoringRateLimit",
- mutability: SolidityMutability::Mutable,
- args: (
- <NamedArgument<address>>::new("contractAddress"),
- <NamedArgument<uint32>>::new("rateLimit"),
- ),
- result: <UnnamedArgument<void>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "getSponsoringRateLimit(address) 610cfabd",
- name: "getSponsoringRateLimit",
- mutability: SolidityMutability::View,
- args: (<NamedArgument<address>>::new("contractAddress"),),
- result: <UnnamedArgument<uint32>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "allowed(address,address) 5c658165",
- name: "allowed",
- mutability: SolidityMutability::View,
- args: (
- <NamedArgument<address>>::new("contractAddress"),
- <NamedArgument<address>>::new("user"),
- ),
- result: <UnnamedArgument<bool>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "allowlistEnabled(address) c772ef6c",
- name: "allowlistEnabled",
- mutability: SolidityMutability::View,
- args: (<NamedArgument<address>>::new("contractAddress"),),
- result: <UnnamedArgument<bool>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "toggleAllowlist(address,bool) 36de20f5",
- name: "toggleAllowlist",
- mutability: SolidityMutability::Mutable,
- args: (
- <NamedArgument<address>>::new("contractAddress"),
- <NamedArgument<bool>>::new("enabled"),
- ),
- result: <UnnamedArgument<void>>::default(),
- },
- SolidityFunction {
- docs: &[],
- selector: "toggleAllowed(address,address,bool) 4706cc1c",
- name: "toggleAllowed",
- mutability: SolidityMutability::Mutable,
- args: (
- <NamedArgument<address>>::new("contractAddress"),
- <NamedArgument<address>>::new("user"),
- <NamedArgument<bool>>::new("allowed"),
- ),
- result: <UnnamedArgument<void>>::default(),
- },
- ),
- };
- if is_impl {
- tc . collect ("// Common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n" . into ()) ;
- } else {
- tc . collect ("// Common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n" . into ()) ;
- }
- let mut out = string::new();
- if "ContractHelpers".starts_with("Inline") {
- out.push_str("// Inline\n");
- }
- let _ = interface.format(is_impl, &mut out, tc);
- tc.collect(out);
- }
- }
- impl<T: Config> ::evm_coder::Call for ContractHelpersCall<T> {
- fn parse(
- method_id: u32,
- reader: &mut ::evm_coder::abi::AbiReader,
- ) -> ::evm_coder::execution::Result<Option<Self>> {
- use ::evm_coder::abi::AbiRead;
- match method_id {
- ::evm_coder::ERC165Call::INTERFACE_ID => {
- return Ok(
- ::evm_coder::ERC165Call::parse(method_id, reader)?.map(Self::ERC165Call)
- )
- }
- Self::CONTRACT_OWNER => {
- return Ok(Some(Self::ContractOwner {
- contract_address: reader.abi_read()?,
- }))
- }
- Self::SPONSORING_ENABLED => {
- return Ok(Some(Self::SponsoringEnabled {
- contract_address: reader.abi_read()?,
- }))
- }
- Self::TOGGLE_SPONSORING => {
- return Ok(Some(Self::ToggleSponsoring {
- contract_address: reader.abi_read()?,
- enabled: reader.abi_read()?,
- }))
- }
- Self::SET_SPONSORING_RATE_LIMIT => {
- return Ok(Some(Self::SetSponsoringRateLimit {
- contract_address: reader.abi_read()?,
- rate_limit: reader.abi_read()?,
- }))
- }
- Self::GET_SPONSORING_RATE_LIMIT => {
- return Ok(Some(Self::GetSponsoringRateLimit {
- contract_address: reader.abi_read()?,
- }))
- }
- Self::ALLOWED => {
- return Ok(Some(Self::Allowed {
- contract_address: reader.abi_read()?,
- user: reader.abi_read()?,
- }))
- }
- Self::ALLOWLIST_ENABLED => {
- return Ok(Some(Self::AllowlistEnabled {
- contract_address: reader.abi_read()?,
- }))
- }
- Self::TOGGLE_ALLOWLIST => {
- return Ok(Some(Self::ToggleAllowlist {
- contract_address: reader.abi_read()?,
- enabled: reader.abi_read()?,
- }))
- }
- Self::TOGGLE_ALLOWED => {
- return Ok(Some(Self::ToggleAllowed {
- contract_address: reader.abi_read()?,
- user: reader.abi_read()?,
- allowed: reader.abi_read()?,
- }))
- }
- _ => {}
- }
- return Ok(None);
- }
- }
- impl<T: Config> ::evm_coder::Weighted for ContractHelpersCall<T> {
- fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
- type InternalCall = ContractHelpersCall;
- match self {
- InternalCall::ERC165Call(::evm_coder::ERC165Call::SupportsInterface { .. }) => {
- 100u64.into()
- }
- InternalCall::ContractOwner { .. } => ().into(),
- InternalCall::SponsoringEnabled { .. } => ().into(),
- InternalCall::ToggleSponsoring { .. } => ().into(),
- InternalCall::SetSponsoringRateLimit { .. } => ().into(),
- InternalCall::GetSponsoringRateLimit { .. } => ().into(),
- InternalCall::Allowed { .. } => ().into(),
- InternalCall::AllowlistEnabled { .. } => ().into(),
- InternalCall::ToggleAllowlist { .. } => ().into(),
- InternalCall::ToggleAllowed { .. } => ().into(),
- }
- }
- }
- impl<T: Config> ::evm_coder::Callable<ContractHelpersCall<T>> for ContractHelpers<T> {
- #[allow(unreachable_code)]
- fn call(
- &mut self,
- c: Msg<ContractHelpersCall>,
- ) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
- use ::evm_coder::abi::AbiWrite;
- type InternalCall = ContractHelpersCall;
- match c.call {
- InternalCall::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {
- interface_id,
- }) => {
- let mut writer = ::evm_coder::abi::AbiWriter::default();
- writer.bool(&InternalCall::supports_interface(interface_id));
- return Ok(writer.into());
- }
- _ => {}
- }
- let mut writer = ::evm_coder::abi::AbiWriter::default();
- match c.call {
- InternalCall::ContractOwner { contract_address } => {
- let result = self.contract_owner(contract_address)?;
- (&result).to_result()
- }
- InternalCall::SponsoringEnabled { contract_address } => {
- let result = self.sponsoring_enabled(contract_address)?;
- (&result).to_result()
- }
- InternalCall::ToggleSponsoring {
- contract_address,
- enabled,
- } => {
- let result =
- self.toggle_sponsoring(c.caller.clone(), contract_address, enabled)?;
- (&result).to_result()
- }
- InternalCall::SetSponsoringRateLimit {
- contract_address,
- rate_limit,
- } => {
- let result = self.set_sponsoring_rate_limit(
- c.caller.clone(),
- contract_address,
- rate_limit,
- )?;
- (&result).to_result()
- }
- InternalCall::GetSponsoringRateLimit { contract_address } => {
- let result = self.get_sponsoring_rate_limit(contract_address)?;
- (&result).to_result()
- }
- InternalCall::Allowed {
- contract_address,
- user,
- } => {
- let result = self.allowed(contract_address, user)?;
- (&result).to_result()
- }
- InternalCall::AllowlistEnabled { contract_address } => {
- let result = self.allowlist_enabled(contract_address)?;
- (&result).to_result()
- }
- InternalCall::ToggleAllowlist {
- contract_address,
- enabled,
- } => {
- let result =
- self.toggle_allowlist(c.caller.clone(), contract_address, enabled)?;
- (&result).to_result()
- }
- InternalCall::ToggleAllowed {
- contract_address,
- user,
- allowed,
- } => {
- let result =
- self.toggle_allowed(c.caller.clone(), contract_address, user, allowed)?;
- (&result).to_result()
- }
- _ => ::core::panicking::panic("internal error: entered unreachable code"),
- }
- }
- }
- pub struct HelpersOnMethodCall<T: Config>(PhantomData<*const T>);
- impl<T: Config> OnMethodCall<T> for HelpersOnMethodCall<T> {
- fn is_reserved(contract: &sp_core::H160) -> bool {
- contract == &T::ContractAddress::get()
- }
- fn is_used(contract: &sp_core::H160) -> bool {
- contract == &T::ContractAddress::get()
- }
- fn call(
- source: &sp_core::H160,
- target: &sp_core::H160,
- gas_left: u64,
- input: &[u8],
- value: sp_core::U256,
- ) -> Option<PrecompileOutput> {
- if !<Pallet<T>>::allowed(*target, *source, true) {
- return Some(PrecompileOutput {
- exit_status: ExitReason::Revert(ExitRevert::Reverted),
- cost: 0,
- output: {
- let mut writer = AbiWriter::new_call(147028384u32);
- writer.string("Target contract is allowlisted");
- writer.finish()
- },
- logs: ::alloc::vec::Vec::new(),
- });
- }
- if target != &T::ContractAddress::get() {
- return None;
- }
- let helpers = ContractHelpers::<T>(SubstrateRecorder::<T>::new(*target, gas_left));
- pallet_evm_coder_substrate::call(*source, helpers, value, input)
- }
- fn get_code(contract: &sp_core::H160) -> Option<Vec<u8>> {
- (contract == & T :: ContractAddress :: get ()) . then (| | b"`\xe0`@R`&`\x80\x81\x81R\x90a\x04\xf4`\xa09\x80Qa\x00&\x91`\x01\x91` \x90\x91\x01\x90a\x009V[P4\x80\x15a\x003W`\x00\x80\xfd[Pa\x01\rV[\x82\x80Ta\x00E\x90a\x00\xd2V[\x90`\x00R` `\x00 \x90`\x1f\x01` \x90\x04\x81\x01\x92\x82a\x00gW`\x00\x85Ua\x00\xadV[\x82`\x1f\x10a\x00\x80W\x80Q`\xff\x19\x16\x83\x80\x01\x17\x85Ua\x00\xadV[\x82\x80\x01`\x01\x01\x85U\x82\x15a\x00\xadW\x91\x82\x01[\x82\x81\x11\x15a\x00\xadW\x82Q\x82U\x91` \x01\x91\x90`\x01\x01\x90a\x00\x92V[Pa\x00\xb9\x92\x91Pa\x00\xbdV[P\x90V[[\x80\x82\x11\x15a\x00\xb9W`\x00\x81U`\x01\x01a\x00\xbeV[`\x01\x81\x81\x1c\x90\x82\x16\x80a\x00\xe6W`\x7f\x82\x16\x91P[` \x82\x10\x81\x14\x15a\x01\x07WcNH{q`\xe0\x1b`\x00R`\"`\x04R`$`\x00\xfd[P\x91\x90PV[a\x03\xd8\x80a\x01\x1c`\x009`\x00\xf3\xfe`\x80`@R4\x80\x15a\x00\x10W`\x00\x80\xfd[P`\x046\x10a\x00\x9eW`\x005`\xe0\x1c\x80c`\'\xdca\x11a\x00fW\x80c`\'\xdca\x14a\x01\"W\x80ca\x0c\xfa\xbd\x14a\x010W\x80cw\xb6\xc9\x08\x14a\x01SW\x80c\xc7r\xefl\x14a\x01\"W\x80c\xfc\xacm\x86\x14a\x00\xcbW`\x00\x80\xfd[\x80c\x01\xff\xc9\xa7\x14a\x00\xa3W\x80c6\xde \xf5\x14a\x00\xcbW\x80cG\x06\xcc\x1c\x14a\x00\xe0W\x80cQR\xb1L\x14a\x00\xeeW\x80c\\e\x81e\x14a\x01\x14W[`\x00\x80\xfd[a\x00\xb6a\x00\xb16`\x04a\x01\xa2V[a\x01aV[`@Q\x90\x15\x15\x81R` \x01[`@Q\x80\x91\x03\x90\xf3[a\x00\xdea\x00\xd96`\x04a\x01\xffV[a\x01\x87V[\x00[a\x00\xdea\x00\xd96`\x04a\x022V[a\x00\xfca\x00\xb16`\x04a\x02uV[`@Q`\x01`\x01`\xa0\x1b\x03\x90\x91\x16\x81R` \x01a\x00\xc2V[a\x00\xb6a\x00\xb16`\x04a\x02\x90V[a\x00\xb6a\x00\xb16`\x04a\x02uV[a\x01>a\x00\xb16`\x04a\x02uV[`@Qc\xff\xff\xff\xff\x90\x91\x16\x81R` \x01a\x00\xc2V[a\x00\xdea\x00\xd96`\x04a\x02\xbaV[`\x00`\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x01~\x91\x90a\x02\xfaV[`@Q\x80\x91\x03\x90\xfd[`\x01`@QbF\x1b\xcd`\xe5\x1b\x81R`\x04\x01a\x01~\x91\x90a\x02\xfaV[`\x00` \x82\x84\x03\x12\x15a\x01\xb4W`\x00\x80\xfd[\x815`\x01`\x01`\xe0\x1b\x03\x19\x81\x16\x81\x14a\x01\xccW`\x00\x80\xfd[\x93\x92PPPV[\x805`\x01`\x01`\xa0\x1b\x03\x81\x16\x81\x14a\x01\xeaW`\x00\x80\xfd[\x91\x90PV[\x805\x80\x15\x15\x81\x14a\x01\xeaW`\x00\x80\xfd[`\x00\x80`@\x83\x85\x03\x12\x15a\x02\x12W`\x00\x80\xfd[a\x02\x1b\x83a\x01\xd3V[\x91Pa\x02)` \x84\x01a\x01\xefV[\x90P\x92P\x92\x90PV[`\x00\x80`\x00``\x84\x86\x03\x12\x15a\x02GW`\x00\x80\xfd[a\x02P\x84a\x01\xd3V[\x92Pa\x02^` \x85\x01a\x01\xd3V[\x91Pa\x02l`@\x85\x01a\x01\xefV[\x90P\x92P\x92P\x92V[`\x00` \x82\x84\x03\x12\x15a\x02\x87W`\x00\x80\xfd[a\x01\xcc\x82a\x01\xd3V[`\x00\x80`@\x83\x85\x03\x12\x15a\x02\xa3W`\x00\x80\xfd[a\x02\xac\x83a\x01\xd3V[\x91Pa\x02)` \x84\x01a\x01\xd3V[`\x00\x80`@\x83\x85\x03\x12\x15a\x02\xcdW`\x00\x80\xfd[a\x02\xd6\x83a\x01\xd3V[\x91P` \x83\x015c\xff\xff\xff\xff\x81\x16\x81\x14a\x02\xefW`\x00\x80\xfd[\x80\x91PP\x92P\x92\x90PV[`\x00` \x80\x83R`\x00\x84T\x81`\x01\x82\x81\x1c\x91P\x80\x83\x16\x80a\x03\x1cW`\x7f\x83\x16\x92P[\x85\x83\x10\x81\x14\x15a\x03:WcNH{q`\xe0\x1b\x85R`\"`\x04R`$\x85\xfd[\x87\x86\x01\x83\x81R` \x01\x81\x80\x15a\x03WW`\x01\x81\x14a\x03hWa\x03\x93V[`\xff\x19\x86\x16\x82R\x87\x82\x01\x96Pa\x03\x93V[`\x00\x8b\x81R` \x90 `\x00[\x86\x81\x10\x15a\x03\x8dW\x81T\x84\x82\x01R\x90\x85\x01\x90\x89\x01a\x03tV[\x83\x01\x97PP[P\x94\x99\x98PPPPPPPPPV\xfe\xa2dipfsX\"\x12 \xde\xe1\xb0gnP\xa0\xbb\xa7\xaf\xbek+\xe6S6\n\xcd?\x0c+\x81\xebEq\x8c\xe3\xab\xaaC6UdsolcC\x00\x08\t\x003this contract is implemented in native" . to_vec ())
- }
- }
- pub struct HelpersOnCreate<T: Config>(PhantomData<*const T>);
- impl<T: Config> OnCreate<T> for HelpersOnCreate<T> {
- fn on_create(owner: H160, contract: H160) {
- <Owner<T>>::insert(contract, owner);
- }
- }
- pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);
- impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for HelpersContractSponsoring<T> {
- fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {
- if <SelfSponsoring<T>>::get(&call.0) && <Pallet<T>>::allowed(call.0, *who, false) {
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
- if let Some(last_tx_block) = <SponsorBasket<T>>::get(&call.0, who) {
- let rate_limit = <SponsoringRateLimit<T>>::get(&call.0);
- let limit_time = last_tx_block + rate_limit;
- if block_number > limit_time {
- <SponsorBasket<T>>::insert(&call.0, who, block_number);
- return Some(call.0);
- }
- } else {
- <SponsorBasket<T>>::insert(&call.0, who, block_number);
- return Some(call.0);
- }
- }
- None
- }
- }
-}
-#[doc = r"
- The module that hosts all the
- [FRAME](https://docs.substrate.io/v3/runtime/frame)
- types needed to add this pallet to a
- runtime.
- "]
-pub mod pallet {
- use evm_coder::execution::Result;
- use frame_support::pallet_prelude::*;
- use sp_core::H160;
- #[doc = r"
- Configuration trait of this pallet.
-
- Implement this type for a runtime in order to customize this pallet.
- "]
- pub trait Config: frame_system::Config + pallet_evm_coder_substrate::Config {
- type ContractAddress: Get<H160>;
- type DefaultSponsoringRateLimit: Get<Self::BlockNumber>;
- }
- #[scale_info(skip_type_params(T), capture_docs = "always")]
- #[doc = r"
- Custom [dispatch errors](https://docs.substrate.io/v3/runtime/events-and-errors)
- of this pallet.
- "]
- pub enum Error<T> {
- #[doc(hidden)]
- #[codec(skip)]
- __Ignore(
- frame_support::sp_std::marker::PhantomData<(T)>,
- frame_support::Never,
- ),
- #[doc = " This method is only executable by owner"]
- NoPermission,
- }
- #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
- const _: () = {
- impl<T> ::scale_info::TypeInfo for Error<T>
- where
- frame_support::sp_std::marker::PhantomData<(T)>: ::scale_info::TypeInfo + 'static,
- T: 'static,
- {
- type Identity = Self;
- fn type_info() -> ::scale_info::Type {
- :: scale_info :: Type :: builder () . path (:: scale_info :: Path :: new ("Error" , "pallet_evm_contract_helpers::pallet")) . type_params (< [_] > :: into_vec (box [:: scale_info :: TypeParameter :: new ("T" , :: core :: option :: Option :: None)])) . docs_always (& ["\n\t\t\tCustom [dispatch errors](https://docs.substrate.io/v3/runtime/events-and-errors)\n\t\t\tof this pallet.\n\t\t\t"]) . variant (:: scale_info :: build :: Variants :: new () . variant ("NoPermission" , | v | v . index (0usize as :: core :: primitive :: u8) . docs_always (& ["This method is only executable by owner"])))
- }
- };
- };
- #[doc = r"
- The [pallet](https://docs.substrate.io/v3/runtime/frame#pallets) implementing
- the on-chain logic.
- "]
- pub struct Pallet<T>(frame_support::sp_std::marker::PhantomData<(T)>);
- const _: () = {
- impl<T> core::clone::Clone for Pallet<T> {
- fn clone(&self) -> Self {
- Self(core::clone::Clone::clone(&self.0))
- }
- }
- };
- const _: () = {
- impl<T> core::cmp::Eq for Pallet<T> {}
- };
- const _: () = {
- impl<T> core::cmp::PartialEq for Pallet<T> {
- fn eq(&self, other: &Self) -> bool {
- true && self.0 == other.0
- }
- }
- };
- const _: () = {
- impl<T> core::fmt::Debug for Pallet<T> {
- fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
- fmt.debug_tuple("Pallet").field(&self.0).finish()
- }
- }
- };
- #[allow(type_alias_bounds)]
- pub(super) type Owner<T: Config> = StorageMap<
- _GeneratedPrefixForStorageOwner<T>,
- Twox128,
- H160,
- H160,
- ValueQuery,
- frame_support::traits::GetDefault,
- frame_support::traits::GetDefault,
- >;
- #[allow(type_alias_bounds)]
- pub(super) type SelfSponsoring<T: Config> = StorageMap<
- _GeneratedPrefixForStorageSelfSponsoring<T>,
- Twox128,
- H160,
- bool,
- ValueQuery,
- frame_support::traits::GetDefault,
- frame_support::traits::GetDefault,
- >;
- #[allow(type_alias_bounds)]
- pub(super) type SponsoringRateLimit<T: Config> = StorageMap<
- _GeneratedPrefixForStorageSponsoringRateLimit<T>,
- Twox128,
- H160,
- T::BlockNumber,
- ValueQuery,
- T::DefaultSponsoringRateLimit,
- frame_support::traits::GetDefault,
- >;
- #[allow(type_alias_bounds)]
- pub(super) type SponsorBasket<T: Config> = StorageDoubleMap<
- _GeneratedPrefixForStorageSponsorBasket<T>,
- Twox128,
- H160,
- Twox128,
- H160,
- T::BlockNumber,
- OptionQuery,
- frame_support::traits::GetDefault,
- frame_support::traits::GetDefault,
- >;
- #[allow(type_alias_bounds)]
- pub(super) type AllowlistEnabled<T: Config> = StorageMap<
- _GeneratedPrefixForStorageAllowlistEnabled<T>,
- Twox128,
- H160,
- bool,
- ValueQuery,
- frame_support::traits::GetDefault,
- frame_support::traits::GetDefault,
- >;
- #[allow(type_alias_bounds)]
- pub(super) type Allowlist<T: Config> = StorageDoubleMap<
- _GeneratedPrefixForStorageAllowlist<T>,
- Twox128,
- H160,
- Twox128,
- H160,
- bool,
- ValueQuery,
- frame_support::traits::GetDefault,
- frame_support::traits::GetDefault,
- >;
- impl<T: Config> Pallet<T> {
- pub fn toggle_sponsoring(contract: H160, enabled: bool) {
- <SelfSponsoring<T>>::insert(contract, enabled);
- }
- pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {
- <SponsoringRateLimit<T>>::insert(contract, rate_limit);
- }
- #[doc = " Default is returned if allowlist is disabled"]
- pub fn allowed(contract: H160, user: H160, default: bool) -> bool {
- if !<AllowlistEnabled<T>>::get(contract) {
- return default;
- }
- <Allowlist<T>>::get(&contract, &user) || <Owner<T>>::get(&contract) == user
- }
- pub fn toggle_allowlist(contract: H160, enabled: bool) {
- <AllowlistEnabled<T>>::insert(contract, enabled)
- }
- pub fn toggle_allowed(contract: H160, user: H160, allowed: bool) {
- <Allowlist<T>>::insert(contract, user, allowed);
- }
- pub fn ensure_owner(contract: H160, user: H160) -> Result<()> {
- {
- if !(<Owner<T>>::get(&contract) == user) {
- {
- return Err("no permission".into());
- };
- }
- };
- Ok(())
- }
- }
- impl<T: Config> Pallet<T> {
- #[doc(hidden)]
- pub fn pallet_constants_metadata(
- ) -> frame_support::sp_std::vec::Vec<frame_support::metadata::PalletConstantMetadata>
- {
- ::alloc::vec::Vec::new()
- }
- }
- impl<T: Config> Pallet<T> {
- pub fn error_metadata() -> Option<frame_support::metadata::PalletErrorMetadata> {
- Some(frame_support::metadata::PalletErrorMetadata {
- ty: frame_support::scale_info::meta_type::<Error<T>>(),
- })
- }
- }
- #[doc = r" Type alias to `Pallet`, to be used by `construct_runtime`."]
- #[doc = r""]
- #[doc = r" Generated by `pallet` attribute macro."]
- #[deprecated(note = "use `Pallet` instead")]
- #[allow(dead_code)]
- pub type Module<T> = Pallet<T>;
- impl<T: Config> frame_support::traits::GetStorageVersion for Pallet<T> {
- fn current_storage_version() -> frame_support::traits::StorageVersion {
- frame_support::traits::StorageVersion::default()
- }
- fn on_chain_storage_version() -> frame_support::traits::StorageVersion {
- frame_support::traits::StorageVersion::get::<Self>()
- }
- }
- impl<T: Config> frame_support::traits::OnGenesis for Pallet<T> {
- fn on_genesis() {
- let storage_version = frame_support::traits::StorageVersion::default();
- storage_version.put::<Self>();
- }
- }
- impl<T: Config> frame_support::traits::PalletInfoAccess for Pallet<T> {
- fn index() -> usize {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::index::<
- Self,
- >()
- .expect(
- "Pallet is part of the runtime because pallet `Config` trait is \
- implemented by the runtime",
- )
- }
- fn name() -> &'static str {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
- Self,
- >()
- .expect(
- "Pallet is part of the runtime because pallet `Config` trait is \
- implemented by the runtime",
- )
- }
- fn module_name() -> &'static str {
- < < T as frame_system :: Config > :: PalletInfo as frame_support :: traits :: PalletInfo > :: module_name :: < Self > () . expect ("Pallet is part of the runtime because pallet `Config` trait is \
- implemented by the runtime")
- }
- fn crate_version() -> frame_support::traits::CrateVersion {
- frame_support::traits::CrateVersion {
- major: 0u16,
- minor: 1u8,
- patch: 0u8,
- }
- }
- }
- impl<T: Config> frame_support::traits::StorageInfoTrait for Pallet<T> {
- fn storage_info() -> frame_support::sp_std::vec::Vec<frame_support::traits::StorageInfo> {
- #[allow(unused_mut)]
- let mut res = ::alloc::vec::Vec::new();
- {
- let mut storage_info = < Owner < T > as frame_support :: traits :: PartialStorageInfoTrait > :: partial_storage_info () ;
- res.append(&mut storage_info);
- }
- {
- let mut storage_info = < SelfSponsoring < T > as frame_support :: traits :: PartialStorageInfoTrait > :: partial_storage_info () ;
- res.append(&mut storage_info);
- }
- {
- let mut storage_info = < SponsoringRateLimit < T > as frame_support :: traits :: PartialStorageInfoTrait > :: partial_storage_info () ;
- res.append(&mut storage_info);
- }
- {
- let mut storage_info = < SponsorBasket < T > as frame_support :: traits :: PartialStorageInfoTrait > :: partial_storage_info () ;
- res.append(&mut storage_info);
- }
- {
- let mut storage_info = < AllowlistEnabled < T > as frame_support :: traits :: PartialStorageInfoTrait > :: partial_storage_info () ;
- res.append(&mut storage_info);
- }
- {
- let mut storage_info = < Allowlist < T > as frame_support :: traits :: PartialStorageInfoTrait > :: partial_storage_info () ;
- res.append(&mut storage_info);
- }
- res
- }
- }
- #[doc(hidden)]
- pub mod __substrate_call_check {
- #[doc(hidden)]
- pub use __is_call_part_defined_0 as is_call_part_defined;
- }
- #[doc = r"Contains one variant per dispatchable that can be called by an extrinsic."]
- #[codec(encode_bound())]
- #[codec(decode_bound())]
- #[scale_info(skip_type_params(T), capture_docs = "always")]
- #[allow(non_camel_case_types)]
- pub enum Call<T: Config> {
- #[doc(hidden)]
- #[codec(skip)]
- __Ignore(
- frame_support::sp_std::marker::PhantomData<(T,)>,
- frame_support::Never,
- ),
- }
- const _: () = {
- impl<T: Config> core::fmt::Debug for Call<T> {
- fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
- match *self {
- Self::__Ignore(ref _0, ref _1) => fmt
- .debug_tuple("Call::__Ignore")
- .field(&_0)
- .field(&_1)
- .finish(),
- }
- }
- }
- };
- const _: () = {
- impl<T: Config> core::clone::Clone for Call<T> {
- fn clone(&self) -> Self {
- match self {
- Self::__Ignore(ref _0, ref _1) => {
- Self::__Ignore(core::clone::Clone::clone(_0), core::clone::Clone::clone(_1))
- }
- }
- }
- }
- };
- const _: () = {
- impl<T: Config> core::cmp::Eq for Call<T> {}
- };
- const _: () = {
- impl<T: Config> core::cmp::PartialEq for Call<T> {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (Self::__Ignore(_0, _1), Self::__Ignore(_0_other, _1_other)) => {
- true && _0 == _0_other && _1 == _1_other
- }
- }
- }
- }
- };
- const _: () = {
- #[allow(non_camel_case_types)]
- impl<T: Config> ::codec::Encode for Call<T> {}
- impl<T: Config> ::codec::EncodeLike for Call<T> {}
- };
- const _: () = {
- #[allow(non_camel_case_types)]
- impl<T: Config> ::codec::Decode for Call<T> {
- fn decode<__CodecInputEdqy: ::codec::Input>(
- __codec_input_edqy: &mut __CodecInputEdqy,
- ) -> ::core::result::Result<Self, ::codec::Error> {
- match __codec_input_edqy
- .read_byte()
- .map_err(|e| e.chain("Could not decode `Call`, failed to read variant byte"))?
- {
- _ => ::core::result::Result::Err(<_ as ::core::convert::Into<_>>::into(
- "Could not decode `Call`, variant doesn\'t exist",
- )),
- }
- }
- }
- };
- #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
- const _: () = {
- impl<T: Config> ::scale_info::TypeInfo for Call<T>
- where
- frame_support::sp_std::marker::PhantomData<(T,)>: ::scale_info::TypeInfo + 'static,
- T: Config + 'static,
- {
- type Identity = Self;
- fn type_info() -> ::scale_info::Type {
- ::scale_info::Type::builder()
- .path(::scale_info::Path::new(
- "Call",
- "pallet_evm_contract_helpers::pallet",
- ))
- .type_params(<[_]>::into_vec(box [::scale_info::TypeParameter::new(
- "T",
- ::core::option::Option::None,
- )]))
- .docs_always(&[
- "Contains one variant per dispatchable that can be called by an extrinsic.",
- ])
- .variant(::scale_info::build::Variants::new())
- }
- };
- };
- impl<T: Config> Call<T> {}
- impl<T: Config> frame_support::dispatch::GetDispatchInfo for Call<T> {
- fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo {
- match *self {
- Self::__Ignore(_, _) => {
- ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["internal error: entered unreachable code: "],
- &match (&"__Ignore cannot be used",) {
- (arg0,) => [::core::fmt::ArgumentV1::new(
- arg0,
- ::core::fmt::Display::fmt,
- )],
- },
- ))
- }
- }
- }
- }
- impl<T: Config> frame_support::dispatch::GetCallName for Call<T> {
- fn get_call_name(&self) -> &'static str {
- match *self {
- Self::__Ignore(_, _) => {
- ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["internal error: entered unreachable code: "],
- &match (&"__PhantomItem cannot be used.",) {
- (arg0,) => [::core::fmt::ArgumentV1::new(
- arg0,
- ::core::fmt::Display::fmt,
- )],
- },
- ))
- }
- }
- }
- fn get_call_names() -> &'static [&'static str] {
- &[]
- }
- }
- impl<T: Config> frame_support::traits::UnfilteredDispatchable for Call<T> {
- type Origin = frame_system::pallet_prelude::OriginFor<T>;
- fn dispatch_bypass_filter(
- self,
- origin: Self::Origin,
- ) -> frame_support::dispatch::DispatchResultWithPostInfo {
- match self {
- Self::__Ignore(_, _) => {
- let _ = origin;
- {
- {
- ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["internal error: entered unreachable code: "],
- &match (&"__PhantomItem cannot be used.",) {
- (arg0,) => [::core::fmt::ArgumentV1::new(
- arg0,
- ::core::fmt::Display::fmt,
- )],
- },
- ))
- }
- };
- }
- }
- }
- }
- impl<T: Config> frame_support::dispatch::Callable<T> for Pallet<T> {
- type Call = Call<T>;
- }
- impl<T: Config> Pallet<T> {
- #[doc(hidden)]
- pub fn call_functions() -> frame_support::metadata::PalletCallMetadata {
- frame_support::scale_info::meta_type::<Call<T>>().into()
- }
- }
- impl<T: Config> frame_support::sp_std::fmt::Debug for Error<T> {
- fn fmt(
- &self,
- f: &mut frame_support::sp_std::fmt::Formatter<'_>,
- ) -> frame_support::sp_std::fmt::Result {
- f.write_str(self.as_str())
- }
- }
- impl<T: Config> Error<T> {
- pub fn as_u8(&self) -> u8 {
- match &self {
- Self::__Ignore(_, _) => {
- ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["internal error: entered unreachable code: "],
- &match (&"`__Ignore` can never be constructed",) {
- (arg0,) => [::core::fmt::ArgumentV1::new(
- arg0,
- ::core::fmt::Display::fmt,
- )],
- },
- ))
- }
- Self::NoPermission => 0usize as u8,
- }
- }
- pub fn as_str(&self) -> &'static str {
- match &self {
- Self::__Ignore(_, _) => {
- ::core::panicking::panic_fmt(::core::fmt::Arguments::new_v1(
- &["internal error: entered unreachable code: "],
- &match (&"`__Ignore` can never be constructed",) {
- (arg0,) => [::core::fmt::ArgumentV1::new(
- arg0,
- ::core::fmt::Display::fmt,
- )],
- },
- ))
- }
- Self::NoPermission => "NoPermission",
- }
- }
- }
- impl<T: Config> From<Error<T>> for &'static str {
- fn from(err: Error<T>) -> &'static str {
- err.as_str()
- }
- }
- impl<T: Config> From<Error<T>> for frame_support::sp_runtime::DispatchError {
- fn from(err: Error<T>) -> Self {
- let index = < < T as frame_system :: Config > :: PalletInfo as frame_support :: traits :: PalletInfo > :: index :: < Pallet < T > > () . expect ("Every active module has an index in the runtime; qed") as u8 ;
- frame_support::sp_runtime::DispatchError::Module {
- index,
- error: err.as_u8(),
- message: Some(err.as_str()),
- }
- }
- }
- #[doc(hidden)]
- pub mod __substrate_event_check {
- #[doc(hidden)]
- pub use __is_event_part_defined_1 as is_event_part_defined;
- }
- impl<T: Config> Pallet<T> {
- #[doc(hidden)]
- pub fn storage_metadata() -> frame_support::metadata::PalletStorageMetadata {
- frame_support :: metadata :: PalletStorageMetadata { prefix : < < T as frame_system :: Config > :: PalletInfo as frame_support :: traits :: PalletInfo > :: name :: < Pallet < T > > () . expect ("Every active pallet has a name in the runtime; qed") , entries : { # [allow (unused_mut)] let mut entries = :: alloc :: vec :: Vec :: new () ; { < Owner < T > as frame_support :: storage :: StorageEntryMetadataBuilder > :: build_metadata (:: alloc :: vec :: Vec :: new () , & mut entries) ; } { < SelfSponsoring < T > as frame_support :: storage :: StorageEntryMetadataBuilder > :: build_metadata (:: alloc :: vec :: Vec :: new () , & mut entries) ; } { < SponsoringRateLimit < T > as frame_support :: storage :: StorageEntryMetadataBuilder > :: build_metadata (:: alloc :: vec :: Vec :: new () , & mut entries) ; } { < SponsorBasket < T > as frame_support :: storage :: StorageEntryMetadataBuilder > :: build_metadata (:: alloc :: vec :: Vec :: new () , & mut entries) ; } { < AllowlistEnabled < T > as frame_support :: storage :: StorageEntryMetadataBuilder > :: build_metadata (:: alloc :: vec :: Vec :: new () , & mut entries) ; } { < Allowlist < T > as frame_support :: storage :: StorageEntryMetadataBuilder > :: build_metadata (:: alloc :: vec :: Vec :: new () , & mut entries) ; } entries } , }
- }
- }
- pub(super) struct _GeneratedPrefixForStorageOwner<T>(core::marker::PhantomData<(T,)>);
- impl<T: Config> frame_support::traits::StorageInstance for _GeneratedPrefixForStorageOwner<T> {
- fn pallet_prefix() -> &'static str {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
- Pallet<T>,
- >()
- .expect("Every active pallet has a name in the runtime; qed")
- }
- const STORAGE_PREFIX: &'static str = "Owner";
- }
- pub(super) struct _GeneratedPrefixForStorageSelfSponsoring<T>(core::marker::PhantomData<(T,)>);
- impl<T: Config> frame_support::traits::StorageInstance
- for _GeneratedPrefixForStorageSelfSponsoring<T>
- {
- fn pallet_prefix() -> &'static str {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
- Pallet<T>,
- >()
- .expect("Every active pallet has a name in the runtime; qed")
- }
- const STORAGE_PREFIX: &'static str = "SelfSponsoring";
- }
- pub(super) struct _GeneratedPrefixForStorageSponsoringRateLimit<T>(
- core::marker::PhantomData<(T,)>,
- );
- impl<T: Config> frame_support::traits::StorageInstance
- for _GeneratedPrefixForStorageSponsoringRateLimit<T>
- {
- fn pallet_prefix() -> &'static str {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
- Pallet<T>,
- >()
- .expect("Every active pallet has a name in the runtime; qed")
- }
- const STORAGE_PREFIX: &'static str = "SponsoringRateLimit";
- }
- pub(super) struct _GeneratedPrefixForStorageSponsorBasket<T>(core::marker::PhantomData<(T,)>);
- impl<T: Config> frame_support::traits::StorageInstance
- for _GeneratedPrefixForStorageSponsorBasket<T>
- {
- fn pallet_prefix() -> &'static str {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
- Pallet<T>,
- >()
- .expect("Every active pallet has a name in the runtime; qed")
- }
- const STORAGE_PREFIX: &'static str = "SponsorBasket";
- }
- pub(super) struct _GeneratedPrefixForStorageAllowlistEnabled<T>(
- core::marker::PhantomData<(T,)>,
- );
- impl<T: Config> frame_support::traits::StorageInstance
- for _GeneratedPrefixForStorageAllowlistEnabled<T>
- {
- fn pallet_prefix() -> &'static str {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
- Pallet<T>,
- >()
- .expect("Every active pallet has a name in the runtime; qed")
- }
- const STORAGE_PREFIX: &'static str = "AllowlistEnabled";
- }
- pub(super) struct _GeneratedPrefixForStorageAllowlist<T>(core::marker::PhantomData<(T,)>);
- impl<T: Config> frame_support::traits::StorageInstance for _GeneratedPrefixForStorageAllowlist<T> {
- fn pallet_prefix() -> &'static str {
- <<T as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::name::<
- Pallet<T>,
- >()
- .expect("Every active pallet has a name in the runtime; qed")
- }
- const STORAGE_PREFIX: &'static str = "Allowlist";
- }
- #[doc(hidden)]
- pub mod __substrate_inherent_check {
- #[doc(hidden)]
- pub use __is_inherent_part_defined_2 as is_inherent_part_defined;
- }
- #[doc = r" Hidden instance generated to be internally used when module is used without"]
- #[doc = r" instance."]
- #[doc(hidden)]
- pub type __InherentHiddenInstance = ();
- pub(super) trait Store {
- type Owner;
- type SelfSponsoring;
- type SponsoringRateLimit;
- type SponsorBasket;
- type AllowlistEnabled;
- type Allowlist;
- }
- impl<T: Config> Store for Pallet<T> {
- type Owner = Owner<T>;
- type SelfSponsoring = SelfSponsoring<T>;
- type SponsoringRateLimit = SponsoringRateLimit<T>;
- type SponsorBasket = SponsorBasket<T>;
- type AllowlistEnabled = AllowlistEnabled<T>;
- type Allowlist = Allowlist<T>;
- }
- impl<T: Config> frame_support::traits::Hooks<<T as frame_system::Config>::BlockNumber>
- for Pallet<T>
- {
- }
- impl<T: Config> frame_support::traits::OnFinalize<<T as frame_system::Config>::BlockNumber>
- for Pallet<T>
- {
- fn on_finalize(n: <T as frame_system::Config>::BlockNumber) {
- let __within_span__ = {
- use ::tracing::__macro_support::Callsite as _;
- static CALLSITE: ::tracing::__macro_support::MacroCallsite = {
- use ::tracing::__macro_support::MacroCallsite;
- static META: ::tracing::Metadata<'static> = {
- ::tracing_core::metadata::Metadata::new(
- "on_finalize",
- "pallet_evm_contract_helpers::pallet",
- ::tracing::Level::TRACE,
- Some("pallets/evm-contract-helpers/src/lib.rs"),
- Some(7u32),
- Some("pallet_evm_contract_helpers::pallet"),
- ::tracing_core::field::FieldSet::new(
- &[],
- ::tracing_core::callsite::Identifier(&CALLSITE),
- ),
- ::tracing::metadata::Kind::SPAN,
- )
- };
- MacroCallsite::new(&META)
- };
- let mut interest = ::tracing::subscriber::Interest::never();
- if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
- && ::tracing::Level::TRACE <= ::tracing::level_filters::LevelFilter::current()
- && {
- interest = CALLSITE.interest();
- !interest.is_never()
- }
- && CALLSITE.is_enabled(interest)
- {
- let meta = CALLSITE.metadata();
- ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })
- } else {
- let span = CALLSITE.disabled_span();
- {};
- span
- }
- };
- let __tracing_guard__ = __within_span__.enter();
- < Self as frame_support :: traits :: Hooks < < T as frame_system :: Config > :: BlockNumber > > :: on_finalize (n)
- }
- }
- impl<T: Config> frame_support::traits::OnIdle<<T as frame_system::Config>::BlockNumber>
- for Pallet<T>
- {
- fn on_idle(
- n: <T as frame_system::Config>::BlockNumber,
- remaining_weight: frame_support::weights::Weight,
- ) -> frame_support::weights::Weight {
- < Self as frame_support :: traits :: Hooks < < T as frame_system :: Config > :: BlockNumber > > :: on_idle (n , remaining_weight)
- }
- }
- impl<T: Config> frame_support::traits::OnInitialize<<T as frame_system::Config>::BlockNumber>
- for Pallet<T>
- {
- fn on_initialize(
- n: <T as frame_system::Config>::BlockNumber,
- ) -> frame_support::weights::Weight {
- let __within_span__ = {
- use ::tracing::__macro_support::Callsite as _;
- static CALLSITE: ::tracing::__macro_support::MacroCallsite = {
- use ::tracing::__macro_support::MacroCallsite;
- static META: ::tracing::Metadata<'static> = {
- ::tracing_core::metadata::Metadata::new(
- "on_initialize",
- "pallet_evm_contract_helpers::pallet",
- ::tracing::Level::TRACE,
- Some("pallets/evm-contract-helpers/src/lib.rs"),
- Some(7u32),
- Some("pallet_evm_contract_helpers::pallet"),
- ::tracing_core::field::FieldSet::new(
- &[],
- ::tracing_core::callsite::Identifier(&CALLSITE),
- ),
- ::tracing::metadata::Kind::SPAN,
- )
- };
- MacroCallsite::new(&META)
- };
- let mut interest = ::tracing::subscriber::Interest::never();
- if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
- && ::tracing::Level::TRACE <= ::tracing::level_filters::LevelFilter::current()
- && {
- interest = CALLSITE.interest();
- !interest.is_never()
- }
- && CALLSITE.is_enabled(interest)
- {
- let meta = CALLSITE.metadata();
- ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })
- } else {
- let span = CALLSITE.disabled_span();
- {};
- span
- }
- };
- let __tracing_guard__ = __within_span__.enter();
- < Self as frame_support :: traits :: Hooks < < T as frame_system :: Config > :: BlockNumber > > :: on_initialize (n)
- }
- }
- impl<T: Config> frame_support::traits::OnRuntimeUpgrade for Pallet<T> {
- fn on_runtime_upgrade() -> frame_support::weights::Weight {
- let __within_span__ = {
- use ::tracing::__macro_support::Callsite as _;
- static CALLSITE: ::tracing::__macro_support::MacroCallsite = {
- use ::tracing::__macro_support::MacroCallsite;
- static META: ::tracing::Metadata<'static> = {
- ::tracing_core::metadata::Metadata::new(
- "on_runtime_update",
- "pallet_evm_contract_helpers::pallet",
- ::tracing::Level::TRACE,
- Some("pallets/evm-contract-helpers/src/lib.rs"),
- Some(7u32),
- Some("pallet_evm_contract_helpers::pallet"),
- ::tracing_core::field::FieldSet::new(
- &[],
- ::tracing_core::callsite::Identifier(&CALLSITE),
- ),
- ::tracing::metadata::Kind::SPAN,
- )
- };
- MacroCallsite::new(&META)
- };
- let mut interest = ::tracing::subscriber::Interest::never();
- if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
- && ::tracing::Level::TRACE <= ::tracing::level_filters::LevelFilter::current()
- && {
- interest = CALLSITE.interest();
- !interest.is_never()
- }
- && CALLSITE.is_enabled(interest)
- {
- let meta = CALLSITE.metadata();
- ::tracing::Span::new(meta, &{ meta.fields().value_set(&[]) })
- } else {
- let span = CALLSITE.disabled_span();
- {};
- span
- }
- };
- let __tracing_guard__ = __within_span__.enter();
- let pallet_name = < < T as frame_system :: Config > :: PalletInfo as frame_support :: traits :: PalletInfo > :: name :: < Self > () . unwrap_or ("<unknown pallet name>") ;
- {
- let lvl = ::log::Level::Info;
- if lvl <= ::log::STATIC_MAX_LEVEL && lvl <= ::log::max_level() {
- ::log::__private_api_log(
- ::core::fmt::Arguments::new_v1(
- &["\u{2705} no migration for "],
- &match (&pallet_name,) {
- (arg0,) => [::core::fmt::ArgumentV1::new(
- arg0,
- ::core::fmt::Display::fmt,
- )],
- },
- ),
- lvl,
- &(
- frame_support::LOG_TARGET,
- "pallet_evm_contract_helpers::pallet",
- "pallets/evm-contract-helpers/src/lib.rs",
- 7u32,
- ),
- );
- }
- };
- < Self as frame_support :: traits :: Hooks < < T as frame_system :: Config > :: BlockNumber > > :: on_runtime_upgrade ()
- }
- }
- impl<T: Config> frame_support::traits::OffchainWorker<<T as frame_system::Config>::BlockNumber>
- for Pallet<T>
- {
- fn offchain_worker(n: <T as frame_system::Config>::BlockNumber) {
- < Self as frame_support :: traits :: Hooks < < T as frame_system :: Config > :: BlockNumber > > :: offchain_worker (n)
- }
- }
- impl<T: Config> frame_support::traits::IntegrityTest for Pallet<T> {
- fn integrity_test() {
- < Self as frame_support :: traits :: Hooks < < T as frame_system :: Config > :: BlockNumber > > :: integrity_test ()
- }
- }
- #[doc(hidden)]
- pub mod __substrate_genesis_config_check {
- #[doc(hidden)]
- pub use __is_genesis_config_defined_3 as is_genesis_config_defined;
- #[doc(hidden)]
- pub use __is_std_enabled_for_genesis_3 as is_std_enabled_for_genesis;
- }
- #[doc(hidden)]
- pub mod __substrate_origin_check {
- #[doc(hidden)]
- pub use __is_origin_part_defined_4 as is_origin_part_defined;
- }
- #[doc(hidden)]
- pub mod __substrate_validate_unsigned_check {
- #[doc(hidden)]
- pub use __is_validate_unsigned_part_defined_5 as is_validate_unsigned_part_defined;
- }
-}
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -4,7 +4,7 @@
use pallet_evm::{ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure};
use sp_core::H160;
use crate::{
- AllowlistEnabled, Config, Owner, Pallet, SelfSponsoring, SponsorBasket, SponsoringRateLimit,
+ AllowlistEnabled, Config, Owner, Pallet, SponsorBasket, SponsoringRateLimit, SponsoringModeT,
};
use frame_support::traits::Get;
use up_sponsorship::SponsorshipHandler;
@@ -28,9 +28,10 @@
}
fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {
- Ok(<SelfSponsoring<T>>::get(contract_address))
+ Ok(<Pallet<T>>::sponsoring_mode(contract_address) != SponsoringModeT::Disabled)
}
+ /// Deprecated
fn toggle_sponsoring(
&mut self,
caller: caller,
@@ -42,6 +43,22 @@
Ok(())
}
+ fn set_sponsoring_mode(
+ &mut self,
+ caller: caller,
+ contract_address: address,
+ mode: uint8,
+ ) -> Result<void> {
+ <Pallet<T>>::ensure_owner(contract_address, caller)?;
+ let mode = SponsoringModeT::from_eth(mode).ok_or("unknown mode")?;
+ <Pallet<T>>::set_sponsoring_mode(contract_address, mode);
+ Ok(())
+ }
+
+ fn sponsoring_mode(&self, contract_address: address) -> Result<uint8> {
+ Ok(<Pallet<T>>::sponsoring_mode(contract_address).to_eth())
+ }
+
fn set_sponsoring_rate_limit(
&mut self,
caller: caller,
@@ -146,10 +163,11 @@
pub struct HelpersContractSponsoring<T: Config>(PhantomData<*const T>);
impl<T: Config> SponsorshipHandler<H160, (H160, Vec<u8>)> for HelpersContractSponsoring<T> {
fn get_sponsor(who: &H160, call: &(H160, Vec<u8>)) -> Option<H160> {
- if !<SelfSponsoring<T>>::get(&call.0) {
+ let mode = <Pallet<T>>::sponsoring_mode(call.0);
+ if mode == SponsoringModeT::Disabled {
return None;
}
- if !<Pallet<T>>::allowed(call.0, *who) {
+ if mode == SponsoringModeT::Allowlisted && !<Pallet<T>>::allowed(call.0, *who) {
return None;
}
let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
pallets/evm-contract-helpers/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/lib.rs
+++ b/pallets/evm-contract-helpers/src/lib.rs
@@ -1,11 +1,14 @@
#![cfg_attr(not(feature = "std"), no_std)]
+use codec::{Decode, Encode, MaxEncodedLen};
pub use pallet::*;
pub use eth::*;
+use scale_info::TypeInfo;
pub mod eth;
#[frame_support::pallet]
pub mod pallet {
+ pub use super::*;
use evm_coder::execution::Result;
use frame_support::pallet_prelude::*;
use sp_core::H160;
@@ -31,10 +34,15 @@
StorageMap<Hasher = Twox128, Key = H160, Value = H160, QueryKind = ValueQuery>;
#[pallet::storage]
+ #[deprecated]
pub(super) type SelfSponsoring<T: Config> =
StorageMap<Hasher = Twox128, Key = H160, Value = bool, QueryKind = ValueQuery>;
#[pallet::storage]
+ pub(super) type SponsoringMode<T: Config> =
+ StorageMap<Hasher = Twox128, Key = H160, Value = SponsoringModeT, QueryKind = OptionQuery>;
+
+ #[pallet::storage]
pub(super) type SponsoringRateLimit<T: Config> = StorageMap<
Hasher = Twox128,
Key = H160,
@@ -68,8 +76,31 @@
>;
impl<T: Config> Pallet<T> {
+ pub fn sponsoring_mode(contract: H160) -> SponsoringModeT {
+ <SponsoringMode<T>>::get(contract)
+ .or_else(|| {
+ <SelfSponsoring<T>>::get(contract).then(|| SponsoringModeT::Allowlisted)
+ })
+ .unwrap_or_default()
+ }
+ pub fn set_sponsoring_mode(contract: H160, mode: SponsoringModeT) {
+ if mode == SponsoringModeT::Disabled {
+ <SponsoringMode<T>>::remove(contract);
+ } else {
+ <SponsoringMode<T>>::insert(contract, mode);
+ }
+ <SelfSponsoring<T>>::remove(contract)
+ }
+
pub fn toggle_sponsoring(contract: H160, enabled: bool) {
- <SelfSponsoring<T>>::insert(contract, enabled);
+ Self::set_sponsoring_mode(
+ contract,
+ if enabled {
+ SponsoringModeT::Allowlisted
+ } else {
+ SponsoringModeT::Disabled
+ },
+ )
}
pub fn set_sponsoring_rate_limit(contract: H160, rate_limit: T::BlockNumber) {
@@ -94,3 +125,34 @@
}
}
}
+
+#[derive(Encode, Decode, PartialEq, TypeInfo, MaxEncodedLen)]
+pub enum SponsoringModeT {
+ Disabled,
+ Allowlisted,
+ Generous,
+}
+
+impl SponsoringModeT {
+ fn from_eth(v: u8) -> Option<Self> {
+ Some(match v {
+ 0 => Self::Disabled,
+ 1 => Self::Allowlisted,
+ 2 => Self::Generous,
+ _ => return None,
+ })
+ }
+ fn to_eth(self) -> u8 {
+ match self {
+ SponsoringModeT::Disabled => 0,
+ SponsoringModeT::Allowlisted => 1,
+ SponsoringModeT::Generous => 2,
+ }
+ }
+}
+
+impl Default for SponsoringModeT {
+ fn default() -> Self {
+ Self::Disabled
+ }
+}
pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/evm-contract-helpers/src/stubs/ContractHelpers.soldiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
+++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol
@@ -21,7 +21,7 @@
}
}
-// Selector: 31acb1fe
+// Selector: 7b4866f9
contract ContractHelpers is Dummy, ERC165 {
// Selector: contractOwner(address) 5152b14c
function contractOwner(address contractAddress)
@@ -47,6 +47,8 @@
return false;
}
+ // Deprecated
+ //
// Selector: toggleSponsoring(address,bool) fcac6d86
function toggleSponsoring(address contractAddress, bool enabled) public {
require(false, stub_error);
@@ -55,6 +57,26 @@
dummy = 0;
}
+ // Selector: setSponsoringMode(address,uint8) fde8a560
+ function setSponsoringMode(address contractAddress, uint8 mode) public {
+ require(false, stub_error);
+ contractAddress;
+ mode;
+ dummy = 0;
+ }
+
+ // Selector: sponsoringMode(address) b70c7267
+ function sponsoringMode(address contractAddress)
+ public
+ view
+ returns (uint8)
+ {
+ require(false, stub_error);
+ contractAddress;
+ dummy;
+ return 0;
+ }
+
// Selector: setSponsoringRateLimit(address,uint32) 77b6c908
function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
public
tests/src/eth/api/ContractHelpers.soldiffbeforeafterboth--- a/tests/src/eth/api/ContractHelpers.sol
+++ b/tests/src/eth/api/ContractHelpers.sol
@@ -12,7 +12,7 @@
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
-// Selector: 31acb1fe
+// Selector: 7b4866f9
interface ContractHelpers is Dummy, ERC165 {
// Selector: contractOwner(address) 5152b14c
function contractOwner(address contractAddress)
@@ -26,9 +26,20 @@
view
returns (bool);
+ // Deprecated
+ //
// Selector: toggleSponsoring(address,bool) fcac6d86
function toggleSponsoring(address contractAddress, bool enabled) external;
+ // Selector: setSponsoringMode(address,uint8) fde8a560
+ function setSponsoringMode(address contractAddress, uint8 mode) external;
+
+ // Selector: sponsoringMode(address) b70c7267
+ function sponsoringMode(address contractAddress)
+ external
+ view
+ returns (uint8);
+
// Selector: setSponsoringRateLimit(address,uint32) 77b6c908
function setSponsoringRateLimit(address contractAddress, uint32 rateLimit)
external;
tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -10,7 +10,10 @@
createEthAccountWithBalance,
transferBalanceToEth,
deployFlipper,
- itWeb3} from './util/helpers';
+ itWeb3,
+ SponsoringMode,
+ createEthAccount,
+} from './util/helpers';
describe('Sponsoring EVM contracts', () => {
itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3}) => {
@@ -18,7 +21,7 @@
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
+ await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
});
@@ -28,11 +31,11 @@
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await expect(helpers.methods.toggleSponsoring(notOwner, true).send({from: notOwner})).to.rejected;
+ await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).send({from: notOwner})).to.rejected;
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
});
- itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({api, web3}) => {
+ itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3}) => {
const alice = privateKey('//Alice');
const owner = await createEthAccountWithBalance(api, web3);
@@ -41,11 +44,39 @@
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
+
+ expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
+ await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});
+ await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
+ expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
+
+ await transferBalanceToEth(api, alice, flipper.options.address);
+
+ const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);
+ expect(originalFlipperBalance).to.be.not.equal('0');
+
+ await flipper.methods.flip().send({from: caller});
+ expect(await flipper.methods.getValue().call()).to.be.true;
+
+ // Balance should be taken from flipper instead of caller
+ const balanceAfter = await web3.eth.getBalance(flipper.options.address);
+ expect(+balanceAfter).to.be.lessThan(+originalFlipperBalance);
+ });
+
+ itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({api, web3}) => {
+ const alice = privateKey('//Alice');
+
+ const owner = await createEthAccountWithBalance(api, web3);
+ const caller = createEthAccount(web3);
+
+ const flipper = await deployFlipper(web3, owner);
+
+ const helpers = contractHelpers(web3, owner);
await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});
await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
+ await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});
await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
@@ -66,14 +97,14 @@
const alice = privateKey('//Alice');
const owner = await createEthAccountWithBalance(api, web3);
- const caller = await createEthAccountWithBalance(api, web3);
+ const caller = createEthAccount(web3);
const flipper = await deployFlipper(web3, owner);
const helpers = contractHelpers(web3, owner);
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
+ await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});
await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
@@ -104,7 +135,7 @@
await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
+ await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});
await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
@@ -133,7 +164,7 @@
await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
+ await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});
await helpers.methods.setSponsoringRateLimit(flipper.options.address, 10).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
@@ -157,33 +188,4 @@
const helpers = contractHelpers(web3, owner);
expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');
});
-
- itWeb3('If allowlist mode is off and sponsorship is on, sponsorship does not work', async ({api, web3}) => {
- const alice = privateKey('//Alice');
-
- const owner = await createEthAccountWithBalance(api, web3);
- const caller = await createEthAccountWithBalance(api, web3);
-
- const flipper = await deployFlipper(web3, owner);
-
- const helpers = contractHelpers(web3, owner);
-
- expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
- await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
- expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
-
- await transferBalanceToEth(api, alice, flipper.options.address);
-
- const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);
- expect(originalFlipperBalance).to.be.not.equal('0');
-
- await flipper.methods.flip().send({from: caller});
- expect(await flipper.methods.getValue().call()).to.be.true;
-
- // Balance should be taken from flipper instead of caller
- const balanceAfter = await web3.eth.getBalance(flipper.options.address);
- expect(+balanceAfter).to.be.equals(+originalFlipperBalance);
- });
-
});
tests/src/eth/marketplace/marketplace.test.tsdiffbeforeafterboth--- a/tests/src/eth/marketplace/marketplace.test.ts
+++ b/tests/src/eth/marketplace/marketplace.test.ts
@@ -2,7 +2,7 @@
import {getBalanceSingle, transferBalanceExpectSuccess} from '../../substrate/get-balance';
import privateKey from '../../substrate/privateKey';
import {addToAllowListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, getTokenOwner, setCollectionLimitsExpectSuccess, setCollectionSponsorExpectSuccess, transferExpectSuccess, transferFromExpectSuccess} from '../../util/helpers';
-import {collectionIdToAddress, contractHelpers, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, subToEth, subToEthLowercase, transferBalanceToEth} from '../util/helpers';
+import {collectionIdToAddress, contractHelpers, createEthAccountWithBalance, executeEthTxOnSub, GAS_ARGS, itWeb3, SponsoringMode, subToEth, subToEthLowercase, transferBalanceToEth} from '../util/helpers';
import {evmToAddress} from '@polkadot/util-crypto';
import nonFungibleAbi from '../nonFungibleAbi.json';
import fungibleAbi from '../fungibleAbi.json';
@@ -20,7 +20,7 @@
});
const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments:[matcherOwner]}).send({from: matcherOwner});
const helpers = contractHelpers(web3, matcherOwner);
- await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});
+ await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});
await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});
await transferBalanceToEth(api, alice, matcher.options.address);
@@ -147,7 +147,7 @@
const matcher = await matcherContract.deploy({data: (await readFile(`${__dirname}/MarketPlace.bin`)).toString(), arguments: [matcherOwner]}).send({from: matcherOwner, gas: 10000000});
await matcher.methods.setEscrow(escrow).send({from: matcherOwner});
const helpers = contractHelpers(web3, matcherOwner);
- await helpers.methods.toggleSponsoring(matcher.options.address, true).send({from: matcherOwner});
+ await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner});
await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner});
await transferBalanceToEth(api, alice, matcher.options.address);
tests/src/eth/sponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/sponsoring.test.ts
+++ b/tests/src/eth/sponsoring.test.ts
@@ -1,6 +1,6 @@
import {expect} from 'chai';
import privateKey from '../substrate/privateKey';
-import {contractHelpers, createEthAccount, createEthAccountWithBalance, deployCollector, deployFlipper, itWeb3, transferBalanceToEth} from './util/helpers';
+import {contractHelpers, createEthAccount, createEthAccountWithBalance, deployCollector, deployFlipper, itWeb3, SponsoringMode, transferBalanceToEth} from './util/helpers';
describe('EVM sponsoring', () => {
itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3}) => {
@@ -18,7 +18,7 @@
await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(flipper.options.address, true).send({from: owner});
+ await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});
await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
@@ -49,7 +49,7 @@
await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(collector.options.address).call()).to.be.false;
- await helpers.methods.toggleSponsoring(collector.options.address, true).send({from: owner});
+ await helpers.methods.setSponsoringMode(collector.options.address, SponsoringMode.Allowlisted).send({from: owner});
await helpers.methods.setSponsoringRateLimit(collector.options.address, 0).send({from: owner});
expect(await helpers.methods.sponsoringEnabled(collector.options.address).call()).to.be.true;
tests/src/eth/util/contractHelpersAbi.jsondiffbeforeafterboth--- a/tests/src/eth/util/contractHelpersAbi.json
+++ b/tests/src/eth/util/contractHelpersAbi.json
@@ -147,6 +147,43 @@
"type": "address"
},
{
+ "internalType": "uint8",
+ "name": "mode",
+ "type": "uint8"
+ }
+ ],
+ "name": "setSponsoringMode",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ }
+ ],
+ "name": "sponsoringMode",
+ "outputs": [
+ {
+ "internalType": "uint8",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
"internalType": "uint32",
"name": "limit",
"type": "uint32"
@@ -176,4 +213,4 @@
"stateMutability": "view",
"type": "function"
}
-]
\ No newline at end of file
+]
tests/src/eth/util/helpers.tsdiffbeforeafterboth--- a/tests/src/eth/util/helpers.ts
+++ b/tests/src/eth/util/helpers.ts
@@ -21,6 +21,12 @@
export const GAS_ARGS = {gas: 2500000};
+export enum SponsoringMode {
+ Disabled = 0,
+ Allowlisted = 1,
+ Generous = 2,
+}
+
let web3Connected = false;
export async function usingWeb3<T>(cb: (web3: Web3) => Promise<T> | T): Promise<T> {
if (web3Connected) throw new Error('do not nest usingWeb3 calls');