difftreelog
fix(evm-coder) subresult parsing
in: master
Subresult offset should be based on current subresult start, not on current item offset
1 file changed
crates/evm-coder/src/abi.rsdiffbeforeafterboth19#[derive(Clone)]19#[derive(Clone)]20pub struct AbiReader<'i> {20pub struct AbiReader<'i> {21 buf: &'i [u8],21 buf: &'i [u8],22 subresult_offset: usize,22 offset: usize,23 offset: usize,23}24}24impl<'i> AbiReader<'i> {25impl<'i> AbiReader<'i> {25 pub fn new(buf: &'i [u8]) -> Self {26 pub fn new(buf: &'i [u8]) -> Self {26 Self { buf, offset: 0 }27 Self {28 buf,29 subresult_offset: 0,30 offset: 0,31 }27 }32 }28 pub fn new_call(buf: &'i [u8]) -> Result<(u32, Self)> {33 pub fn new_call(buf: &'i [u8]) -> Result<(u32, Self)> {41 u32::from_be_bytes(method_id),42 Self {43 buf,44 subresult_offset: 4,45 offset: 4,46 },47 ))36 }48 }374938 fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {50 fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {39 if self.buf.len() - self.offset < 32 {51 if self.buf.len() - self.offset < ABI_ALIGNMENT {40 return Err(Error::Error(ExitError::OutOfOffset));52 return Err(Error::Error(ExitError::OutOfOffset));41 }53 }42 let mut block = [0; S];54 let mut block = [0; S];106118107 fn subresult(&mut self) -> Result<AbiReader<'i>> {119 fn subresult(&mut self) -> Result<AbiReader<'i>> {108 let offset = self.read_usize()?;120 let offset = self.read_usize()?;121 if offset + self.subresult_offset > self.buf.len() {122 return Err(Error::Error(ExitError::InvalidRange));123 }109 Ok(AbiReader {124 Ok(AbiReader {110 buf: self.buf,125 buf: self.buf,126 subresult_offset: offset + self.subresult_offset,111 offset: offset + self.offset,127 offset: offset + self.subresult_offset,112 })128 })113 }129 }114130199 for (static_offset, part) in self.dynamic_part {215 for (static_offset, part) in self.dynamic_part {200 let part_offset = self.static_part.len();216 let part_offset = self.static_part.len();201217202 let encoded_dynamic_offset = usize::to_be_bytes(part_offset - static_offset);218 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);203 self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()219 self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()204 ..static_offset + ABI_ALIGNMENT]220 ..static_offset + ABI_ALIGNMENT]205 .copy_from_slice(&encoded_dynamic_offset);221 .copy_from_slice(&encoded_dynamic_offset);290 }}306 }}291}307}308309#[cfg(test)]310pub mod test {311 use super::{AbiReader, AbiWriter};312 use hex_literal::hex;313314 #[test]315 fn dynamic_after_static() {316 let mut encoder = AbiWriter::new();317 encoder.bool(&true);318 encoder.string("test");319 let encoded = encoder.finish();320321 let mut encoder = AbiWriter::new();322 encoder.bool(&true);323 // Offset to subresult324 encoder.uint32(&(32 * 2));325 // Len of "test"326 encoder.uint32(&4);327 encoder.write_padright(&[b't', b'e', b's', b't']);328 let alternative_encoded = encoder.finish();329330 assert_eq!(encoded, alternative_encoded);331332 let mut decoder = AbiReader::new(&encoded);333 assert_eq!(decoder.bool().unwrap(), true);334 assert_eq!(decoder.string().unwrap(), "test");335 }336337 #[test]338 fn mint_sample() {339 let (call, mut decoder) = AbiReader::new_call(&hex!(340 "341 50bb4e7f342 000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374343 0000000000000000000000000000000000000000000000000000000000000001344 0000000000000000000000000000000000000000000000000000000000000060345 0000000000000000000000000000000000000000000000000000000000000008346 5465737420555249000000000000000000000000000000000000000000000000347 "348 ))349 .unwrap();350 assert_eq!(call, 0x50bb4e7f);351 assert_eq!(352 format!("{:?}", decoder.address().unwrap()),353 "0xad2c0954693c2b5404b7e50967d3481bea432374"354 );355 assert_eq!(decoder.uint32().unwrap(), 1);356 assert_eq!(decoder.string().unwrap(), "Test URI");357 }358}292359