diff --git a/substreams/Cargo.lock b/substreams/Cargo.lock index d529a96..03514a5 100644 --- a/substreams/Cargo.lock +++ b/substreams/Cargo.lock @@ -229,7 +229,7 @@ dependencies = [ [[package]] name = "ethereum-curve" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "bytes", @@ -1097,10 +1097,12 @@ dependencies = [ [[package]] name = "tycho-substreams" -version = "0.1.0" +version = "0.2.0" dependencies = [ + "ethabi 18.0.0", "hex", "itertools 0.12.1", + "num-bigint", "prost 0.11.9", "substreams", "substreams-ethereum", diff --git a/substreams/crates/tycho-substreams/Cargo.toml b/substreams/crates/tycho-substreams/Cargo.toml index 3908f81..a62469d 100644 --- a/substreams/crates/tycho-substreams/Cargo.toml +++ b/substreams/crates/tycho-substreams/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tycho-substreams" -version = "0.1.0" +version = "0.2.0" edition = "2021" [dependencies] @@ -8,4 +8,6 @@ substreams-ethereum.workspace = true substreams.workspace = true prost.workspace = true hex.workspace = true -itertools = "0.12.0" \ No newline at end of file +itertools = "0.12.0" +ethabi.workspace = true +num-bigint = "0.4.4" diff --git a/substreams/crates/tycho-substreams/src/abi/erc20.rs b/substreams/crates/tycho-substreams/src/abi/erc20.rs new file mode 100644 index 0000000..5dd70ca --- /dev/null +++ b/substreams/crates/tycho-substreams/src/abi/erc20.rs @@ -0,0 +1,1066 @@ +const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; +/// Contract's functions. +#[allow(dead_code, unused_imports, unused_variables)] +pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Allowance { + pub owner: Vec, + pub spender: Vec, + } + impl Allowance { + const METHOD_ID: [u8; 4] = [221u8, 98u8, 237u8, 62u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::Uint(256usize)], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Allowance { + const NAME: &'static str = "allowance"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Allowance { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Approve { + pub spender: Vec, + pub value: substreams::scalar::BigInt, + } + impl Approve { + const METHOD_ID: [u8; 4] = [9u8, 94u8, 167u8, 179u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + spender: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian( + match self.value.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + )), + ]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::Bool], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok(values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR)) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Approve { + const NAME: &'static str = "approve"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Approve { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct BalanceOf { + pub owner: Vec, + } + impl BalanceOf { + const METHOD_ID: [u8; 4] = [112u8, 160u8, 130u8, 49u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode(&[ethabi::ParamType::Address], maybe_data.unwrap()) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = + ethabi::encode(&[ethabi::Token::Address(ethabi::Address::from_slice(&self.owner))]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::Uint(256usize)], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for BalanceOf { + const NAME: &'static str = "balanceOf"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for BalanceOf { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Decimals {} + impl Decimals { + const METHOD_ID: [u8; 4] = [49u8, 60u8, 229u8, 103u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::Uint(8usize)], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Decimals { + const NAME: &'static str = "decimals"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Decimals { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Name {} + impl Name { + const METHOD_ID: [u8; 4] = [6u8, 253u8, 222u8, 3u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::String], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok(values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR)) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Name { + const NAME: &'static str = "name"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Name { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Symbol {} + impl Symbol { + const METHOD_ID: [u8; 4] = [149u8, 216u8, 155u8, 65u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::String], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok(values + .pop() + .expect("one output data should have existed") + .into_string() + .expect(INTERNAL_ERR)) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Symbol { + const NAME: &'static str = "symbol"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Symbol { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TotalSupply {} + impl TotalSupply { + const METHOD_ID: [u8; 4] = [24u8, 22u8, 13u8, 221u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::Uint(256usize)], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for TotalSupply { + const NAME: &'static str = "totalSupply"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for TotalSupply { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Transfer { + pub to: Vec, + pub value: substreams::scalar::BigInt, + } + impl Transfer { + const METHOD_ID: [u8; 4] = [169u8, 5u8, 156u8, 187u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + to: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian( + match self.value.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + )), + ]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::Bool], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok(values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR)) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Transfer { + const NAME: &'static str = "transfer"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for Transfer { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TransferFrom { + pub from: Vec, + pub to: Vec, + pub value: substreams::scalar::BigInt, + } + impl TransferFrom { + const METHOD_ID: [u8; 4] = [35u8, 184u8, 114u8, 221u8]; + pub fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian( + match self.value.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + )), + ]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode(&[ethabi::ParamType::Bool], data.as_ref()) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok(values + .pop() + .expect("one output data should have existed") + .into_bool() + .expect(INTERNAL_ERR)) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![rpc::RpcCall { to_addr: address, data: self.encode() }], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, + err + ); + None + } + } + } + } + impl substreams_ethereum::Function for TransferFrom { + const NAME: &'static str = "transferFrom"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode(call: &substreams_ethereum::pb::eth::v2::Call) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable for TransferFrom { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } +} +/// Contract's events. +#[allow(dead_code, unused_imports, unused_variables)] +pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct Approval { + pub owner: Vec, + pub spender: Vec, + pub value: substreams::scalar::BigInt, + } + impl Approval { + const TOPIC_ID: [u8; 32] = [ + 140u8, 91u8, 225u8, 229u8, 235u8, 236u8, 125u8, 91u8, 209u8, 79u8, 113u8, 66u8, 125u8, + 30u8, 132u8, 243u8, 221u8, 3u8, 20u8, 192u8, 247u8, 178u8, 41u8, 30u8, 91u8, 32u8, + 10u8, 200u8, 199u8, 195u8, 185u8, 37u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 32usize { + return false; + } + return log + .topics + .get(0) + .expect("bounds already checked") + .as_ref() == + Self::TOPIC_ID; + } + pub fn decode(log: &substreams_ethereum::pb::eth::v2::Log) -> Result { + let mut values = + ethabi::decode(&[ethabi::ParamType::Uint(256usize)], log.data.as_ref()) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: ethabi::decode(&[ethabi::ParamType::Address], log.topics[1usize].as_ref()) + .map_err(|e| { + format!( + "unable to decode param 'owner' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: ethabi::decode(&[ethabi::ParamType::Address], log.topics[2usize].as_ref()) + .map_err(|e| { + format!( + "unable to decode param 'spender' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for Approval { + const NAME: &'static str = "Approval"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode(log: &substreams_ethereum::pb::eth::v2::Log) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Transfer { + pub from: Vec, + pub to: Vec, + pub value: substreams::scalar::BigInt, + } + impl Transfer { + const TOPIC_ID: [u8; 32] = [ + 221u8, 242u8, 82u8, 173u8, 27u8, 226u8, 200u8, 155u8, 105u8, 194u8, 176u8, 104u8, + 252u8, 55u8, 141u8, 170u8, 149u8, 43u8, 167u8, 241u8, 99u8, 196u8, 161u8, 22u8, 40u8, + 245u8, 90u8, 77u8, 245u8, 35u8, 179u8, 239u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() != 32usize { + return false; + } + return log + .topics + .get(0) + .expect("bounds already checked") + .as_ref() == + Self::TOPIC_ID; + } + pub fn decode(log: &substreams_ethereum::pb::eth::v2::Log) -> Result { + let mut values = + ethabi::decode(&[ethabi::ParamType::Uint(256usize)], log.data.as_ref()) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + from: ethabi::decode(&[ethabi::ParamType::Address], log.topics[1usize].as_ref()) + .map_err(|e| { + format!( + "unable to decode param 'from' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: ethabi::decode(&[ethabi::ParamType::Address], log.topics[2usize].as_ref()) + .map_err(|e| { + format!("unable to decode param 'to' from topic of type 'address': {:?}", e) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + } + impl substreams_ethereum::Event for Transfer { + const NAME: &'static str = "Transfer"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode(log: &substreams_ethereum::pb::eth::v2::Log) -> Result { + Self::decode(log) + } + } +} diff --git a/substreams/crates/tycho-substreams/src/abi/mod.rs b/substreams/crates/tycho-substreams/src/abi/mod.rs new file mode 100644 index 0000000..4542b55 --- /dev/null +++ b/substreams/crates/tycho-substreams/src/abi/mod.rs @@ -0,0 +1,2 @@ +#![allow(clippy::all)] +pub mod erc20; diff --git a/substreams/crates/tycho-substreams/src/balances.rs b/substreams/crates/tycho-substreams/src/balances.rs index 707f60d..afda1ff 100644 --- a/substreams/crates/tycho-substreams/src/balances.rs +++ b/substreams/crates/tycho-substreams/src/balances.rs @@ -21,7 +21,11 @@ //! Through this sequence, the module ensures the transformation from relative to absolute //! balances is conducted with high fidelity, upholding the integrity of transactional data. -use crate::pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas, Transaction}; +use crate::{ + abi, + pb::tycho::evm::v1::{BalanceChange, BlockBalanceDeltas, Transaction}, + prelude::BalanceDelta, +}; use itertools::Itertools; use std::{collections::HashMap, str::FromStr}; use substreams::{ @@ -29,6 +33,7 @@ use substreams::{ pb::substreams::StoreDeltas, prelude::{BigInt, StoreAdd}, }; +use substreams_ethereum::{pb::eth::v2::TransactionTrace, Event}; /// Stores relative balance changes in an additive manner. /// @@ -158,6 +163,74 @@ pub fn aggregate_balances_changes( .collect() } +/// Extracts balance deltas from a transaction trace based on a given address predicate. +/// +/// This function processes the logs within a transaction trace to identify ERC-20 token transfer +/// events. It applies the given predicate to determine which addresses are of interest and extracts +/// the balance changes (deltas) for those addresses. The balance deltas are then returned as a +/// vector. +/// +/// # Arguments +/// +/// * `tx` - A reference to a `TransactionTrace` which contains the transaction logs and other +/// details. +/// * `address_predicate` - A predicate function that takes two byte slices representing a token and +/// a component and returns a boolean. This function is used to filter which addresses' balance +/// changes should be extracted. +/// +/// # Returns +/// +/// A vector of `BalanceDelta` structs, each representing a change in balance for a specific address +/// within the transaction. +/// +/// # Example +/// +/// ``` +/// let predicate = |log_address: &[u8], transfer_address: &[u8]| -> bool { +/// // Your predicate logic here, e.g., checking if the address matches a specific pattern. +/// true +/// }; +/// +/// let balance_deltas = extract_balance_deltas_from_tx(&tx, predicate); +/// ``` +/// +/// # Notes +/// +/// - It is assumed that the transactor is the component. If the protocol follows a different +/// design, this function may not be applicable. +/// - The `address_predicate` is applied to both the log address and the `from`/`to` addresses in +/// the transfer event. +pub fn extract_balance_deltas_from_tx bool>( + tx: &TransactionTrace, + address_predicate: F, +) -> Vec { + let mut balance_deltas = vec![]; + + tx.logs_with_calls() + .for_each(|(log, _)| { + if let Some(transfer) = abi::erc20::events::Transfer::match_and_decode(log) { + let mut create_balance_delta = |transactor: &[u8], delta: BigInt| { + balance_deltas.push(BalanceDelta { + ord: log.ordinal, + tx: Some(tx.into()), + token: log.address.clone(), + delta: delta.to_signed_bytes_be(), + component_id: hex::encode(transactor).into(), + }); + }; + + if address_predicate(&log.address, &transfer.from) { + create_balance_delta(&transfer.from, transfer.value.neg()); + } + if address_predicate(&log.address, &transfer.to) { + create_balance_delta(&transfer.to, transfer.value); + } + } + }); + + balance_deltas +} + #[cfg(test)] mod tests { use super::*; diff --git a/substreams/crates/tycho-substreams/src/lib.rs b/substreams/crates/tycho-substreams/src/lib.rs index 03e9e03..60f3047 100644 --- a/substreams/crates/tycho-substreams/src/lib.rs +++ b/substreams/crates/tycho-substreams/src/lib.rs @@ -1,3 +1,4 @@ +mod abi; pub mod balances; pub mod contract; mod mock_store; diff --git a/substreams/ethereum-curve/Cargo.toml b/substreams/ethereum-curve/Cargo.toml index aba7f0c..c314547 100644 --- a/substreams/ethereum-curve/Cargo.toml +++ b/substreams/ethereum-curve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethereum-curve" -version = "0.1.0" +version = "0.2.0" edition = "2021" [lib] diff --git a/substreams/ethereum-curve/abi/get_abis.py b/substreams/ethereum-curve/abi/get_abis.py index d0758f2..79f98a5 100644 --- a/substreams/ethereum-curve/abi/get_abis.py +++ b/substreams/ethereum-curve/abi/get_abis.py @@ -13,6 +13,7 @@ abis = { "MainRegistry": "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5", "MetaPoolFactory": "0xB9fC157394Af804a3578134A6585C0dc9cc990d4", "CryptoPoolFactory": "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99", + "TwocryptoFactory": "0x98EE851a00abeE0d95D08cF4CA2BdCE32aeaAF7F", # pool "Pool": "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7", "3Pool": "0x5F890841f657d90E081bAbdB532A05996Af79Fe6", diff --git a/substreams/ethereum-curve/abi/main_registry.json b/substreams/ethereum-curve/abi/main_registry.json deleted file mode 100644 index 10bb96b..0000000 --- a/substreams/ethereum-curve/abi/main_registry.json +++ /dev/null @@ -1,940 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "pool", - "type": "address" - }, - { - "indexed": false, - "name": "rate_method_id", - "type": "bytes" - } - ], - "name": "PoolAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "pool", - "type": "address" - } - ], - "name": "PoolRemoved", - "type": "event" - }, - { - "inputs": [ - { - "name": "_address_provider", - "type": "address" - }, - { - "name": "_gauge_controller", - "type": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "name": "find_pool_for_coins", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "i", - "type": "uint256" - } - ], - "name": "find_pool_for_coins", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 1521, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_n_coins", - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 12102, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_coins", - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 12194, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_underlying_coins", - "outputs": [ - { - "name": "", - "type": "address[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 7874, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_decimals", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 7966, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_underlying_decimals", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 36992, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_rates", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 20157, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_gauges", - "outputs": [ - { - "name": "", - "type": "address[10]" - }, - { - "name": "", - "type": "int128[10]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 16583, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_balances", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 162842, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_underlying_balances", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 1927, - "inputs": [ - { - "name": "_token", - "type": "address" - } - ], - "name": "get_virtual_price_from_lp_token", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 1045, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_A", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 6305, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_parameters", - "outputs": [ - { - "name": "A", - "type": "uint256" - }, - { - "name": "future_A", - "type": "uint256" - }, - { - "name": "fee", - "type": "uint256" - }, - { - "name": "admin_fee", - "type": "uint256" - }, - { - "name": "future_fee", - "type": "uint256" - }, - { - "name": "future_admin_fee", - "type": "uint256" - }, - { - "name": "future_owner", - "type": "address" - }, - { - "name": "initial_A", - "type": "uint256" - }, - { - "name": "initial_A_time", - "type": "uint256" - }, - { - "name": "future_A_time", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 1450, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_fees", - "outputs": [ - { - "name": "", - "type": "uint256[2]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 36454, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_admin_balances", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 27131, - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "name": "get_coin_indices", - "outputs": [ - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "int128" - }, - { - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 32004, - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "name": "estimate_gas_used", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 1900, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "is_meta", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 8323, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_pool_name", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 1951, - "inputs": [ - { - "name": "_coin", - "type": "address" - } - ], - "name": "get_coin_swap_count", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2090, - "inputs": [ - { - "name": "_coin", - "type": "address" - }, - { - "name": "_index", - "type": "uint256" - } - ], - "name": "get_coin_swap_complement", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2011, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_pool_asset_type", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 61485845, - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_rate_info", - "type": "bytes32" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_underlying_decimals", - "type": "uint256" - }, - { - "name": "_has_initial_A", - "type": "bool" - }, - { - "name": "_is_v1", - "type": "bool" - }, - { - "name": "_name", - "type": "string" - } - ], - "name": "add_pool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 31306062, - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_rate_info", - "type": "bytes32" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_use_rates", - "type": "uint256" - }, - { - "name": "_has_initial_A", - "type": "bool" - }, - { - "name": "_is_v1", - "type": "bool" - }, - { - "name": "_name", - "type": "string" - } - ], - "name": "add_pool_without_underlying", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - } - ], - "name": "add_metapool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_decimals", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - }, - { - "name": "_base_pool", - "type": "address" - } - ], - "name": "add_metapool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 779731418758, - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "remove_pool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 390460, - "inputs": [ - { - "name": "_addr", - "type": "address[5]" - }, - { - "name": "_amount", - "type": "uint256[2][5]" - } - ], - "name": "set_pool_gas_estimates", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 392047, - "inputs": [ - { - "name": "_addr", - "type": "address[10]" - }, - { - "name": "_amount", - "type": "uint256[10]" - } - ], - "name": "set_coin_gas_estimates", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 72629, - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_estimator", - "type": "address" - } - ], - "name": "set_gas_estimate_contract", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 400675, - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_liquidity_gauges", - "type": "address[10]" - } - ], - "name": "set_liquidity_gauges", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 72667, - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_asset_type", - "type": "uint256" - } - ], - "name": "set_pool_asset_type", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 1173447, - "inputs": [ - { - "name": "_pools", - "type": "address[32]" - }, - { - "name": "_asset_types", - "type": "uint256[32]" - } - ], - "name": "batch_set_pool_asset_type", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "gas": 2048, - "inputs": [], - "name": "address_provider", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2078, - "inputs": [], - "name": "gauge_controller", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2217, - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "name": "pool_list", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2138, - "inputs": [], - "name": "pool_count", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2168, - "inputs": [], - "name": "coin_count", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2307, - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "name": "get_coin", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2443, - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "name": "get_pool_from_lp_token", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2473, - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "name": "get_lp_token", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "gas": 2288, - "inputs": [], - "name": "last_updated", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] \ No newline at end of file diff --git a/substreams/ethereum-curve/abi/susd.json b/substreams/ethereum-curve/abi/susd.json deleted file mode 100644 index 9c301d8..0000000 --- a/substreams/ethereum-curve/abi/susd.json +++ /dev/null @@ -1,760 +0,0 @@ -[ - { - "name": "TokenExchange", - "inputs": [ - { - "type": "address", - "name": "buyer", - "indexed": true - }, - { - "type": "int128", - "name": "sold_id", - "indexed": false - }, - { - "type": "uint256", - "name": "tokens_sold", - "indexed": false - }, - { - "type": "int128", - "name": "bought_id", - "indexed": false - }, - { - "type": "uint256", - "name": "tokens_bought", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "TokenExchangeUnderlying", - "inputs": [ - { - "type": "address", - "name": "buyer", - "indexed": true - }, - { - "type": "int128", - "name": "sold_id", - "indexed": false - }, - { - "type": "uint256", - "name": "tokens_sold", - "indexed": false - }, - { - "type": "int128", - "name": "bought_id", - "indexed": false - }, - { - "type": "uint256", - "name": "tokens_bought", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "AddLiquidity", - "inputs": [ - { - "type": "address", - "name": "provider", - "indexed": true - }, - { - "type": "uint256[4]", - "name": "token_amounts", - "indexed": false - }, - { - "type": "uint256[4]", - "name": "fees", - "indexed": false - }, - { - "type": "uint256", - "name": "invariant", - "indexed": false - }, - { - "type": "uint256", - "name": "token_supply", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidity", - "inputs": [ - { - "type": "address", - "name": "provider", - "indexed": true - }, - { - "type": "uint256[4]", - "name": "token_amounts", - "indexed": false - }, - { - "type": "uint256[4]", - "name": "fees", - "indexed": false - }, - { - "type": "uint256", - "name": "token_supply", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "RemoveLiquidityImbalance", - "inputs": [ - { - "type": "address", - "name": "provider", - "indexed": true - }, - { - "type": "uint256[4]", - "name": "token_amounts", - "indexed": false - }, - { - "type": "uint256[4]", - "name": "fees", - "indexed": false - }, - { - "type": "uint256", - "name": "invariant", - "indexed": false - }, - { - "type": "uint256", - "name": "token_supply", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewAdmin", - "inputs": [ - { - "type": "uint256", - "name": "deadline", - "indexed": true, - "unit": "sec" - }, - { - "type": "address", - "name": "admin", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewAdmin", - "inputs": [ - { - "type": "address", - "name": "admin", - "indexed": true - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "CommitNewParameters", - "inputs": [ - { - "type": "uint256", - "name": "deadline", - "indexed": true, - "unit": "sec" - }, - { - "type": "uint256", - "name": "A", - "indexed": false - }, - { - "type": "uint256", - "name": "fee", - "indexed": false - }, - { - "type": "uint256", - "name": "admin_fee", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "name": "NewParameters", - "inputs": [ - { - "type": "uint256", - "name": "A", - "indexed": false - }, - { - "type": "uint256", - "name": "fee", - "indexed": false - }, - { - "type": "uint256", - "name": "admin_fee", - "indexed": false - } - ], - "anonymous": false, - "type": "event" - }, - { - "outputs": [], - "inputs": [ - { - "type": "address[4]", - "name": "_coins" - }, - { - "type": "address[4]", - "name": "_underlying_coins" - }, - { - "type": "address", - "name": "_pool_token" - }, - { - "type": "uint256", - "name": "_A" - }, - { - "type": "uint256", - "name": "_fee" - } - ], - "constant": false, - "payable": false, - "type": "constructor" - }, - { - "name": "get_virtual_price", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 1570535 - }, - { - "name": "calc_token_amount", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "uint256[4]", - "name": "amounts" - }, - { - "type": "bool", - "name": "deposit" - } - ], - "constant": true, - "payable": false, - "type": "function", - "gas": 6103471 - }, - { - "name": "add_liquidity", - "outputs": [], - "inputs": [ - { - "type": "uint256[4]", - "name": "amounts" - }, - { - "type": "uint256", - "name": "min_mint_amount" - } - ], - "constant": false, - "payable": false, - "type": "function", - "gas": 9331701 - }, - { - "name": "get_dy", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "i" - }, - { - "type": "int128", - "name": "j" - }, - { - "type": "uint256", - "name": "dx" - } - ], - "constant": true, - "payable": false, - "type": "function", - "gas": 3489637 - }, - { - "name": "get_dy_underlying", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "i" - }, - { - "type": "int128", - "name": "j" - }, - { - "type": "uint256", - "name": "dx" - } - ], - "constant": true, - "payable": false, - "type": "function", - "gas": 3489467 - }, - { - "name": "exchange", - "outputs": [], - "inputs": [ - { - "type": "int128", - "name": "i" - }, - { - "type": "int128", - "name": "j" - }, - { - "type": "uint256", - "name": "dx" - }, - { - "type": "uint256", - "name": "min_dy" - } - ], - "constant": false, - "payable": false, - "type": "function", - "gas": 7034253 - }, - { - "name": "exchange_underlying", - "outputs": [], - "inputs": [ - { - "type": "int128", - "name": "i" - }, - { - "type": "int128", - "name": "j" - }, - { - "type": "uint256", - "name": "dx" - }, - { - "type": "uint256", - "name": "min_dy" - } - ], - "constant": false, - "payable": false, - "type": "function", - "gas": 7050488 - }, - { - "name": "remove_liquidity", - "outputs": [], - "inputs": [ - { - "type": "uint256", - "name": "_amount" - }, - { - "type": "uint256[4]", - "name": "min_amounts" - } - ], - "constant": false, - "payable": false, - "type": "function", - "gas": 241191 - }, - { - "name": "remove_liquidity_imbalance", - "outputs": [], - "inputs": [ - { - "type": "uint256[4]", - "name": "amounts" - }, - { - "type": "uint256", - "name": "max_burn_amount" - } - ], - "constant": false, - "payable": false, - "type": "function", - "gas": 9330864 - }, - { - "name": "commit_new_parameters", - "outputs": [], - "inputs": [ - { - "type": "uint256", - "name": "amplification" - }, - { - "type": "uint256", - "name": "new_fee" - }, - { - "type": "uint256", - "name": "new_admin_fee" - } - ], - "constant": false, - "payable": false, - "type": "function", - "gas": 146045 - }, - { - "name": "apply_new_parameters", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function", - "gas": 133452 - }, - { - "name": "revert_new_parameters", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function", - "gas": 21775 - }, - { - "name": "commit_transfer_ownership", - "outputs": [], - "inputs": [ - { - "type": "address", - "name": "_owner" - } - ], - "constant": false, - "payable": false, - "type": "function", - "gas": 74452 - }, - { - "name": "apply_transfer_ownership", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function", - "gas": 60508 - }, - { - "name": "revert_transfer_ownership", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function", - "gas": 21865 - }, - { - "name": "withdraw_admin_fees", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function", - "gas": 23448 - }, - { - "name": "kill_me", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function", - "gas": 37818 - }, - { - "name": "unkill_me", - "outputs": [], - "inputs": [], - "constant": false, - "payable": false, - "type": "function", - "gas": 21955 - }, - { - "name": "coins", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "arg0" - } - ], - "constant": true, - "payable": false, - "type": "function", - "gas": 2130 - }, - { - "name": "underlying_coins", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "arg0" - } - ], - "constant": true, - "payable": false, - "type": "function", - "gas": 2160 - }, - { - "name": "balances", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [ - { - "type": "int128", - "name": "arg0" - } - ], - "constant": true, - "payable": false, - "type": "function", - "gas": 2190 - }, - { - "name": "A", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2021 - }, - { - "name": "fee", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2051 - }, - { - "name": "admin_fee", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2081 - }, - { - "name": "owner", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2111 - }, - { - "name": "admin_actions_deadline", - "outputs": [ - { - "type": "uint256", - "unit": "sec", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2141 - }, - { - "name": "transfer_ownership_deadline", - "outputs": [ - { - "type": "uint256", - "unit": "sec", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2171 - }, - { - "name": "future_A", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2201 - }, - { - "name": "future_fee", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2231 - }, - { - "name": "future_admin_fee", - "outputs": [ - { - "type": "uint256", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2261 - }, - { - "name": "future_owner", - "outputs": [ - { - "type": "address", - "name": "" - } - ], - "inputs": [], - "constant": true, - "payable": false, - "type": "function", - "gas": 2291 - } -] \ No newline at end of file diff --git a/substreams/ethereum-curve/abi/crypto_swap_registry.json b/substreams/ethereum-curve/abi/twocrypto_factory.json similarity index 62% rename from substreams/ethereum-curve/abi/crypto_swap_registry.json rename to substreams/ethereum-curve/abi/twocrypto_factory.json index 3ba9500..d3ea2b9 100644 --- a/substreams/ethereum-curve/abi/crypto_swap_registry.json +++ b/substreams/ethereum-curve/abi/twocrypto_factory.json @@ -3,53 +3,380 @@ "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "name": "pool", "type": "address" - } - ], - "name": "PoolAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "basepool", - "type": "address" - } - ], - "name": "BasePoolAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "pool", - "type": "address" - } - ], - "name": "PoolRemoved", - "type": "event" - }, - { - "inputs": [ - { - "name": "_address_provider", - "type": "address" }, { - "name": "_base_pool_registry", + "indexed": false, + "name": "name", + "type": "string" + }, + { + "indexed": false, + "name": "symbol", + "type": "string" + }, + { + "indexed": false, + "name": "coins", + "type": "address[2]" + }, + { + "indexed": false, + "name": "math", + "type": "address" + }, + { + "indexed": false, + "name": "salt", + "type": "bytes32" + }, + { + "indexed": false, + "name": "precisions", + "type": "uint256[2]" + }, + { + "indexed": false, + "name": "packed_A_gamma", + "type": "uint256" + }, + { + "indexed": false, + "name": "packed_fee_params", + "type": "uint256" + }, + { + "indexed": false, + "name": "packed_rebalancing_params", + "type": "uint256" + }, + { + "indexed": false, + "name": "packed_prices", + "type": "uint256" + }, + { + "indexed": false, + "name": "deployer", "type": "address" } ], + "name": "TwocryptoPoolDeployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "pool", + "type": "address" + }, + { + "indexed": false, + "name": "gauge", + "type": "address" + } + ], + "name": "LiquidityGaugeDeployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_old_fee_receiver", + "type": "address" + }, + { + "indexed": false, + "name": "_new_fee_receiver", + "type": "address" + } + ], + "name": "UpdateFeeReceiver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_implemention_id", + "type": "uint256" + }, + { + "indexed": false, + "name": "_old_pool_implementation", + "type": "address" + }, + { + "indexed": false, + "name": "_new_pool_implementation", + "type": "address" + } + ], + "name": "UpdatePoolImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_old_gauge_implementation", + "type": "address" + }, + { + "indexed": false, + "name": "_new_gauge_implementation", + "type": "address" + } + ], + "name": "UpdateGaugeImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_old_math_implementation", + "type": "address" + }, + { + "indexed": false, + "name": "_new_math_implementation", + "type": "address" + } + ], + "name": "UpdateMathImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_old_views_implementation", + "type": "address" + }, + { + "indexed": false, + "name": "_new_views_implementation", + "type": "address" + } + ], + "name": "UpdateViewsImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "_old_owner", + "type": "address" + }, + { + "indexed": false, + "name": "_new_owner", + "type": "address" + } + ], + "name": "TransferOwnership", + "type": "event" + }, + { + "inputs": [], "outputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "name": "_fee_receiver", + "type": "address" + }, + { + "name": "_admin", + "type": "address" + } + ], + "name": "initialise_ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_coins", + "type": "address[2]" + }, + { + "name": "implementation_id", + "type": "uint256" + }, + { + "name": "A", + "type": "uint256" + }, + { + "name": "gamma", + "type": "uint256" + }, + { + "name": "mid_fee", + "type": "uint256" + }, + { + "name": "out_fee", + "type": "uint256" + }, + { + "name": "fee_gamma", + "type": "uint256" + }, + { + "name": "allowed_extra_profit", + "type": "uint256" + }, + { + "name": "adjustment_step", + "type": "uint256" + }, + { + "name": "ma_exp_time", + "type": "uint256" + }, + { + "name": "initial_price", + "type": "uint256" + } + ], + "name": "deploy_pool", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_pool", + "type": "address" + } + ], + "name": "deploy_gauge", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_fee_receiver", + "type": "address" + } + ], + "name": "set_fee_receiver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_pool_implementation", + "type": "address" + }, + { + "name": "_implementation_index", + "type": "uint256" + } + ], + "name": "set_pool_implementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_gauge_implementation", + "type": "address" + } + ], + "name": "set_gauge_implementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_views_implementation", + "type": "address" + } + ], + "name": "set_views_implementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_math_implementation", + "type": "address" + } + ], + "name": "set_math_implementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_addr", + "type": "address" + } + ], + "name": "commit_transfer_ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accept_transfer_ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -97,30 +424,8 @@ "type": "function" }, { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_n_coins", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_n_underlying_coins", + "inputs": [], + "name": "pool_count", "outputs": [ { "name": "", @@ -141,24 +446,7 @@ "outputs": [ { "name": "", - "type": "address[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_underlying_coins", - "outputs": [ - { - "name": "", - "type": "address[8]" + "type": "address[2]" } ], "stateMutability": "view", @@ -175,45 +463,7 @@ "outputs": [ { "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_underlying_decimals", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_gauges", - "outputs": [ - { - "name": "", - "type": "address[10]" - }, - { - "name": "", - "type": "int128[10]" + "type": "uint256[2]" } ], "stateMutability": "view", @@ -230,126 +480,7 @@ "outputs": [ { "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_underlying_balances", - "outputs": [ - { - "name": "", - "type": "uint256[8]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_token", - "type": "address" - } - ], - "name": "get_virtual_price_from_lp_token", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_A", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_D", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_gamma", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_fees", - "outputs": [ - { - "name": "", - "type": "uint256[4]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_admin_balances", - "outputs": [ - { - "name": "", - "type": "uint256[8]" + "type": "uint256[2]" } ], "stateMutability": "view", @@ -374,15 +505,11 @@ "outputs": [ { "name": "", - "type": "int128" + "type": "uint256" }, { "name": "", - "type": "int128" - }, - { - "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", @@ -395,24 +522,7 @@ "type": "address" } ], - "name": "is_meta", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "get_base_pool", + "name": "get_gauge", "outputs": [ { "name": "", @@ -425,175 +535,27 @@ { "inputs": [ { - "name": "_pool", + "name": "coin_a", + "type": "address" + }, + { + "name": "coin_b", "type": "address" } ], - "name": "get_pool_name", + "name": "get_market_counts", "outputs": [ { "name": "", - "type": "string" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_gauge", - "type": "address" - }, - { - "name": "_zap", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - } - ], - "name": "add_pool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_gauge", - "type": "address" - }, - { - "name": "_zap", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - }, - { - "name": "_base_pool", - "type": "address" - } - ], - "name": "add_pool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_lp_token", - "type": "address" - }, - { - "name": "_gauge", - "type": "address" - }, - { - "name": "_zap", - "type": "address" - }, - { - "name": "_n_coins", - "type": "uint256" - }, - { - "name": "_name", - "type": "string" - }, - { - "name": "_base_pool", - "type": "address" - }, - { - "name": "_has_positive_rebasing_tokens", - "type": "bool" - } - ], - "name": "add_pool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - } - ], - "name": "remove_pool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pool", - "type": "address" - }, - { - "name": "_liquidity_gauges", - "type": "address[10]" - } - ], - "name": "set_liquidity_gauges", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "name": "_pools", - "type": "address[10]" - }, - { - "name": "_liquidity_gauges", - "type": "address[10]" - } - ], - "name": "batch_set_liquidity_gauges", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], - "name": "address_provider", + "name": "admin", "outputs": [ { "name": "", @@ -605,7 +567,72 @@ }, { "inputs": [], - "name": "base_pool_registry", + "name": "future_admin", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "fee_receiver", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "arg0", + "type": "uint256" + } + ], + "name": "pool_implementations", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gauge_implementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "views_implementation", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "math_implementation", "outputs": [ { "name": "", @@ -631,121 +658,5 @@ ], "stateMutability": "view", "type": "function" - }, - { - "inputs": [], - "name": "pool_count", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "base_pool_count", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "arg0", - "type": "uint256" - } - ], - "name": "get_coin", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "coin_count", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "name": "get_pool_from_lp_token", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "name": "get_lp_token", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "name": "arg0", - "type": "address" - } - ], - "name": "get_zap", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "last_updated", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" } ] \ No newline at end of file diff --git a/substreams/ethereum-curve/src/abi/mod.rs b/substreams/ethereum-curve/src/abi/mod.rs index 13e7e2d..f0e96ac 100644 --- a/substreams/ethereum-curve/src/abi/mod.rs +++ b/substreams/ethereum-curve/src/abi/mod.rs @@ -1,11 +1,9 @@ #![allow(clippy::all)] pub mod crypto_pool_factory; pub mod stableswap_factory; -pub mod susd; pub mod crypto_swap_ng_factory; pub mod meta_registry; pub mod tricrypto_factory; -pub mod main_registry; +pub mod twocrypto_factory; pub mod erc20; pub mod meta_pool_factory; -pub mod crypto_swap_registry; diff --git a/substreams/ethereum-curve/src/abi/twocrypto_factory.rs b/substreams/ethereum-curve/src/abi/twocrypto_factory.rs new file mode 100644 index 0000000..7bb6a83 --- /dev/null +++ b/substreams/ethereum-curve/src/abi/twocrypto_factory.rs @@ -0,0 +1,3817 @@ + const INTERNAL_ERR: &'static str = "`ethabi_derive` internal error"; + /// Contract's functions. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod functions { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct AcceptTransferOwnership {} + impl AcceptTransferOwnership { + const METHOD_ID: [u8; 4] = [229u8, 234u8, 71u8, 184u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for AcceptTransferOwnership { + const NAME: &'static str = "accept_transfer_ownership"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Admin {} + impl Admin { + const METHOD_ID: [u8; 4] = [248u8, 81u8, 164u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for Admin { + const NAME: &'static str = "admin"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for Admin { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct CommitTransferOwnership { + pub addr: Vec, + } + impl CommitTransferOwnership { + const METHOD_ID: [u8; 4] = [107u8, 68u8, 26u8, 64u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + addr: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.addr))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for CommitTransferOwnership { + const NAME: &'static str = "commit_transfer_ownership"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct DeployGauge { + pub pool: Vec, + } + impl DeployGauge { + const METHOD_ID: [u8; 4] = [150u8, 190u8, 187u8, 52u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for DeployGauge { + const NAME: &'static str = "deploy_gauge"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for DeployGauge { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct DeployPool { + pub name: String, + pub symbol: String, + pub coins: [Vec; 2usize], + pub implementation_id: substreams::scalar::BigInt, + pub a: substreams::scalar::BigInt, + pub gamma: substreams::scalar::BigInt, + pub mid_fee: substreams::scalar::BigInt, + pub out_fee: substreams::scalar::BigInt, + pub fee_gamma: substreams::scalar::BigInt, + pub allowed_extra_profit: substreams::scalar::BigInt, + pub adjustment_step: substreams::scalar::BigInt, + pub ma_exp_time: substreams::scalar::BigInt, + pub initial_price: substreams::scalar::BigInt, + } + impl DeployPool { + const METHOD_ID: [u8; 4] = [201u8, 85u8, 250u8, 4u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::FixedArray( + Box::new(ethabi::ParamType::Address), + 2usize, + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + coins: { + let mut iter = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec() + }); + [ + iter.next().expect(INTERNAL_ERR), + iter.next().expect(INTERNAL_ERR), + ] + }, + implementation_id: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + a: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + gamma: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + mid_fee: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + out_fee: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + fee_gamma: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + allowed_extra_profit: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + adjustment_step: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + ma_exp_time: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + initial_price: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::String(self.name.clone()), + ethabi::Token::String(self.symbol.clone()), + { + let v = self + .coins + .iter() + .map(|inner| ethabi::Token::Address( + ethabi::Address::from_slice(&inner), + )) + .collect(); + ethabi::Token::FixedArray(v) + }, + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.implementation_id.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.a.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.gamma.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.mid_fee.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.out_fee.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.fee_gamma.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.allowed_extra_profit.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.adjustment_step.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.ma_exp_time.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.initial_price.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for DeployPool { + const NAME: &'static str = "deploy_pool"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for DeployPool { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FeeReceiver {} + impl FeeReceiver { + const METHOD_ID: [u8; 4] = [202u8, 180u8, 211u8, 219u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for FeeReceiver { + const NAME: &'static str = "fee_receiver"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for FeeReceiver { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FindPoolForCoins1 { + pub from: Vec, + pub to: Vec, + } + impl FindPoolForCoins1 { + const METHOD_ID: [u8; 4] = [168u8, 125u8, 240u8, 108u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for FindPoolForCoins1 { + const NAME: &'static str = "find_pool_for_coins1"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for FindPoolForCoins1 { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FindPoolForCoins2 { + pub from: Vec, + pub to: Vec, + pub i: substreams::scalar::BigInt, + } + impl FindPoolForCoins2 { + const METHOD_ID: [u8; 4] = [105u8, 130u8, 235u8, 11u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + i: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.i.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for FindPoolForCoins2 { + const NAME: &'static str = "find_pool_for_coins2"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for FindPoolForCoins2 { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct FutureAdmin {} + impl FutureAdmin { + const METHOD_ID: [u8; 4] = [23u8, 247u8, 24u8, 42u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for FutureAdmin { + const NAME: &'static str = "future_admin"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for FutureAdmin { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GaugeImplementation {} + impl GaugeImplementation { + const METHOD_ID: [u8; 4] = [141u8, 242u8, 66u8, 7u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GaugeImplementation { + const NAME: &'static str = "gauge_implementation"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GaugeImplementation { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetBalances { + pub pool: Vec, + } + impl GetBalances { + const METHOD_ID: [u8; 4] = [146u8, 227u8, 204u8, 45u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[substreams::scalar::BigInt; 2usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result<[substreams::scalar::BigInt; 2usize], String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedArray( + Box::new(ethabi::ParamType::Uint(256usize)), + 2usize, + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut iter = values + .pop() + .expect("one output data should have existed") + .into_fixed_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }); + [iter.next().expect(INTERNAL_ERR), iter.next().expect(INTERNAL_ERR)] + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<[substreams::scalar::BigInt; 2usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetBalances { + const NAME: &'static str = "get_balances"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[substreams::scalar::BigInt; 2usize]> + for GetBalances { + fn output( + data: &[u8], + ) -> Result<[substreams::scalar::BigInt; 2usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCoinIndices { + pub pool: Vec, + pub from: Vec, + pub to: Vec, + } + impl GetCoinIndices { + const METHOD_ID: [u8; 4] = [235u8, 133u8, 34u8, 109u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.pool)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + )) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<(substreams::scalar::BigInt, substreams::scalar::BigInt)> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCoinIndices { + const NAME: &'static str = "get_coin_indices"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + > for GetCoinIndices { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCoins { + pub pool: Vec, + } + impl GetCoins { + const METHOD_ID: [u8; 4] = [154u8, 201u8, 13u8, 61u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[Vec; 2usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<[Vec; 2usize], String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedArray( + Box::new(ethabi::ParamType::Address), + 2usize, + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut iter = values + .pop() + .expect("one output data should have existed") + .into_fixed_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }); + [iter.next().expect(INTERNAL_ERR), iter.next().expect(INTERNAL_ERR)] + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option<[Vec; 2usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetCoins { + const NAME: &'static str = "get_coins"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[Vec; 2usize]> for GetCoins { + fn output(data: &[u8]) -> Result<[Vec; 2usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetDecimals { + pub pool: Vec, + } + impl GetDecimals { + const METHOD_ID: [u8; 4] = [82u8, 181u8, 21u8, 85u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result<[substreams::scalar::BigInt; 2usize], String> { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result<[substreams::scalar::BigInt; 2usize], String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedArray( + Box::new(ethabi::ParamType::Uint(256usize)), + 2usize, + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut iter = values + .pop() + .expect("one output data should have existed") + .into_fixed_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }); + [iter.next().expect(INTERNAL_ERR), iter.next().expect(INTERNAL_ERR)] + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call( + &self, + address: Vec, + ) -> Option<[substreams::scalar::BigInt; 2usize]> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetDecimals { + const NAME: &'static str = "get_decimals"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable<[substreams::scalar::BigInt; 2usize]> + for GetDecimals { + fn output( + data: &[u8], + ) -> Result<[substreams::scalar::BigInt; 2usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetGauge { + pub pool: Vec, + } + impl GetGauge { + const METHOD_ID: [u8; 4] = [218u8, 242u8, 151u8, 185u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ethabi::Token::Address(ethabi::Address::from_slice(&self.pool))], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetGauge { + const NAME: &'static str = "get_gauge"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for GetGauge { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMarketCounts { + pub coin_a: Vec, + pub coin_b: Vec, + } + impl GetMarketCounts { + const METHOD_ID: [u8; 4] = [193u8, 133u8, 107u8, 82u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + coin_a: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + coin_b: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.coin_a), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.coin_b)), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for GetMarketCounts { + const NAME: &'static str = "get_market_counts"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable + for GetMarketCounts { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct InitialiseOwnership { + pub fee_receiver: Vec, + pub admin: Vec, + } + impl InitialiseOwnership { + const METHOD_ID: [u8; 4] = [69u8, 230u8, 47u8, 133u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + fee_receiver: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + admin: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.fee_receiver), + ), + ethabi::Token::Address(ethabi::Address::from_slice(&self.admin)), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for InitialiseOwnership { + const NAME: &'static str = "initialise_ownership"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct MathImplementation {} + impl MathImplementation { + const METHOD_ID: [u8; 4] = [161u8, 60u8, 143u8, 129u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for MathImplementation { + const NAME: &'static str = "math_implementation"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for MathImplementation { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolCount {} + impl PoolCount { + const METHOD_ID: [u8; 4] = [149u8, 106u8, 174u8, 58u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let mut v = [0 as u8; 32]; + values + .pop() + .expect("one output data should have existed") + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for PoolCount { + const NAME: &'static str = "pool_count"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable + for PoolCount { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolImplementations { + pub arg0: substreams::scalar::BigInt, + } + impl PoolImplementations { + const METHOD_ID: [u8; 4] = [50u8, 115u8, 255u8, 71u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + arg0: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.arg0.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for PoolImplementations { + const NAME: &'static str = "pool_implementations"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for PoolImplementations { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct PoolList { + pub arg0: substreams::scalar::BigInt, + } + impl PoolList { + const METHOD_ID: [u8; 4] = [58u8, 29u8, 93u8, 142u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + arg0: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.arg0.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for PoolList { + const NAME: &'static str = "pool_list"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for PoolList { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetFeeReceiver { + pub fee_receiver: Vec, + } + impl SetFeeReceiver { + const METHOD_ID: [u8; 4] = [228u8, 26u8, 183u8, 113u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + fee_receiver: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.fee_receiver), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetFeeReceiver { + const NAME: &'static str = "set_fee_receiver"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetGaugeImplementation { + pub gauge_implementation: Vec, + } + impl SetGaugeImplementation { + const METHOD_ID: [u8; 4] = [143u8, 3u8, 24u8, 44u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + gauge_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.gauge_implementation), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetGaugeImplementation { + const NAME: &'static str = "set_gauge_implementation"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetMathImplementation { + pub math_implementation: Vec, + } + impl SetMathImplementation { + const METHOD_ID: [u8; 4] = [176u8, 116u8, 38u8, 244u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + math_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.math_implementation), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetMathImplementation { + const NAME: &'static str = "set_math_implementation"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetPoolImplementation { + pub pool_implementation: Vec, + pub implementation_index: substreams::scalar::BigInt, + } + impl SetPoolImplementation { + const METHOD_ID: [u8; 4] = [111u8, 56u8, 95u8, 246u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + pool_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + implementation_index: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.pool_implementation), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.implementation_index.clone().to_bytes_be() { + (num_bigint::Sign::Plus, bytes) => bytes, + (num_bigint::Sign::NoSign, bytes) => bytes, + (num_bigint::Sign::Minus, _) => { + panic!("negative numbers are not supported") + } + } + .as_slice(), + ), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetPoolImplementation { + const NAME: &'static str = "set_pool_implementation"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SetViewsImplementation { + pub views_implementation: Vec, + } + impl SetViewsImplementation { + const METHOD_ID: [u8; 4] = [246u8, 250u8, 147u8, 127u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + let maybe_data = call.input.get(4..); + if maybe_data.is_none() { + return Err("no data to decode".to_string()); + } + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + views_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address( + ethabi::Address::from_slice(&self.views_implementation), + ), + ], + ); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + } + impl substreams_ethereum::Function for SetViewsImplementation { + const NAME: &'static str = "set_views_implementation"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ViewsImplementation {} + impl ViewsImplementation { + const METHOD_ID: [u8; 4] = [227u8, 21u8, 147u8, 216u8]; + pub fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Ok(Self {}) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[]); + let mut encoded = Vec::with_capacity(4 + data.len()); + encoded.extend(Self::METHOD_ID); + encoded.extend(data); + encoded + } + pub fn output_call( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result, String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result, String> { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok( + values + .pop() + .expect("one output data should have existed") + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + } + pub fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + match call.input.get(0..4) { + Some(signature) => Self::METHOD_ID == signature, + None => false, + } + } + pub fn call(&self, address: Vec) -> Option> { + use substreams_ethereum::pb::eth::rpc; + let rpc_calls = rpc::RpcCalls { + calls: vec![ + rpc::RpcCall { to_addr : address, data : self.encode(), } + ], + }; + let responses = substreams_ethereum::rpc::eth_call(&rpc_calls).responses; + let response = responses + .get(0) + .expect("one response should have existed"); + if response.failed { + return None; + } + match Self::output(response.raw.as_ref()) { + Ok(data) => Some(data), + Err(err) => { + use substreams_ethereum::Function; + substreams::log::info!( + "Call output for function `{}` failed to decode with error: {}", + Self::NAME, err + ); + None + } + } + } + } + impl substreams_ethereum::Function for ViewsImplementation { + const NAME: &'static str = "views_implementation"; + fn match_call(call: &substreams_ethereum::pb::eth::v2::Call) -> bool { + Self::match_call(call) + } + fn decode( + call: &substreams_ethereum::pb::eth::v2::Call, + ) -> Result { + Self::decode(call) + } + fn encode(&self) -> Vec { + self.encode() + } + } + impl substreams_ethereum::rpc::RPCDecodable> for ViewsImplementation { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + } + /// Contract's events. + #[allow(dead_code, unused_imports, unused_variables)] + pub mod events { + use super::INTERNAL_ERR; + #[derive(Debug, Clone, PartialEq)] + pub struct LiquidityGaugeDeployed { + pub pool: Vec, + pub gauge: Vec, + } + impl LiquidityGaugeDeployed { + const TOPIC_ID: [u8; 32] = [ + 101u8, + 107u8, + 179u8, + 76u8, + 32u8, + 73u8, + 25u8, + 112u8, + 168u8, + 193u8, + 99u8, + 243u8, + 189u8, + 98u8, + 234u8, + 216u8, + 32u8, + 34u8, + 179u8, + 121u8, + 195u8, + 146u8, + 73u8, + 96u8, + 236u8, + 96u8, + 246u8, + 219u8, + 252u8, + 90u8, + 171u8, + 59u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + gauge: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for LiquidityGaugeDeployed { + const NAME: &'static str = "LiquidityGaugeDeployed"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TransferOwnership { + pub old_owner: Vec, + pub new_owner: Vec, + } + impl TransferOwnership { + const TOPIC_ID: [u8; 32] = [ + 92u8, + 72u8, + 101u8, + 40u8, + 236u8, + 62u8, + 63u8, + 14u8, + 169u8, + 17u8, + 129u8, + 207u8, + 248u8, + 17u8, + 111u8, + 2u8, + 191u8, + 163u8, + 80u8, + 224u8, + 59u8, + 139u8, + 111u8, + 18u8, + 224u8, + 7u8, + 101u8, + 173u8, + 187u8, + 90u8, + 248u8, + 92u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + old_owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + new_owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for TransferOwnership { + const NAME: &'static str = "TransferOwnership"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TwocryptoPoolDeployed { + pub pool: Vec, + pub name: String, + pub symbol: String, + pub coins: [Vec; 2usize], + pub math: Vec, + pub salt: [u8; 32usize], + pub precisions: [substreams::scalar::BigInt; 2usize], + pub packed_a_gamma: substreams::scalar::BigInt, + pub packed_fee_params: substreams::scalar::BigInt, + pub packed_rebalancing_params: substreams::scalar::BigInt, + pub packed_prices: substreams::scalar::BigInt, + pub deployer: Vec, + } + impl TwocryptoPoolDeployed { + const TOPIC_ID: [u8; 32] = [ + 129u8, + 82u8, + 163u8, + 3u8, + 126u8, + 61u8, + 197u8, + 65u8, + 84u8, + 173u8, + 13u8, + 44u8, + 173u8, + 177u8, + 207u8, + 126u8, + 29u8, + 27u8, + 158u8, + 43u8, + 98u8, + 95u8, + 170u8, + 61u8, + 251u8, + 79u8, + 224u8, + 61u8, + 96u8, + 145u8, + 2u8, + 202u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() < 512usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Address, + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::FixedArray( + Box::new(ethabi::ParamType::Address), + 2usize, + ), + ethabi::ParamType::Address, + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::FixedArray( + Box::new(ethabi::ParamType::Uint(256usize)), + 2usize, + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + name: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + symbol: values + .pop() + .expect(INTERNAL_ERR) + .into_string() + .expect(INTERNAL_ERR), + coins: { + let mut iter = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec() + }); + [ + iter.next().expect(INTERNAL_ERR), + iter.next().expect(INTERNAL_ERR), + ] + }, + math: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + salt: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + precisions: { + let mut iter = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let mut v = [0 as u8; 32]; + inner + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }); + [ + iter.next().expect(INTERNAL_ERR), + iter.next().expect(INTERNAL_ERR), + ] + }, + packed_a_gamma: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + packed_fee_params: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + packed_rebalancing_params: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + packed_prices: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + deployer: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for TwocryptoPoolDeployed { + const NAME: &'static str = "TwocryptoPoolDeployed"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct UpdateFeeReceiver { + pub old_fee_receiver: Vec, + pub new_fee_receiver: Vec, + } + impl UpdateFeeReceiver { + const TOPIC_ID: [u8; 32] = [ + 40u8, + 97u8, + 68u8, + 134u8, + 120u8, + 240u8, + 190u8, + 103u8, + 241u8, + 27u8, + 251u8, + 84u8, + 129u8, + 179u8, + 227u8, + 180u8, + 207u8, + 235u8, + 58u8, + 204u8, + 97u8, + 38u8, + 173u8, + 96u8, + 160u8, + 95u8, + 149u8, + 191u8, + 198u8, + 83u8, + 6u8, + 102u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + old_fee_receiver: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + new_fee_receiver: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for UpdateFeeReceiver { + const NAME: &'static str = "UpdateFeeReceiver"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct UpdateGaugeImplementation { + pub old_gauge_implementation: Vec, + pub new_gauge_implementation: Vec, + } + impl UpdateGaugeImplementation { + const TOPIC_ID: [u8; 32] = [ + 31u8, + 215u8, + 5u8, + 249u8, + 199u8, + 112u8, + 83u8, + 150u8, + 42u8, + 80u8, + 63u8, + 47u8, + 47u8, + 87u8, + 240u8, + 134u8, + 43u8, + 76u8, + 58u8, + 246u8, + 135u8, + 194u8, + 86u8, + 21u8, + 193u8, + 56u8, + 23u8, + 168u8, + 105u8, + 70u8, + 195u8, + 89u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + old_gauge_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + new_gauge_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for UpdateGaugeImplementation { + const NAME: &'static str = "UpdateGaugeImplementation"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct UpdateMathImplementation { + pub old_math_implementation: Vec, + pub new_math_implementation: Vec, + } + impl UpdateMathImplementation { + const TOPIC_ID: [u8; 32] = [ + 104u8, + 254u8, + 143u8, + 195u8, + 172u8, + 118u8, + 236u8, + 23u8, + 226u8, + 17u8, + 23u8, + 223u8, + 94u8, + 133u8, + 76u8, + 140u8, + 37u8, + 183u8, + 181u8, + 247u8, + 118u8, + 170u8, + 210u8, + 173u8, + 201u8, + 39u8, + 253u8, + 209u8, + 86u8, + 188u8, + 214u8, + 222u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + old_math_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + new_math_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for UpdateMathImplementation { + const NAME: &'static str = "UpdateMathImplementation"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct UpdatePoolImplementation { + pub implemention_id: substreams::scalar::BigInt, + pub old_pool_implementation: Vec, + pub new_pool_implementation: Vec, + } + impl UpdatePoolImplementation { + const TOPIC_ID: [u8; 32] = [ + 106u8, + 66u8, + 239u8, + 150u8, + 5u8, + 225u8, + 53u8, + 175u8, + 175u8, + 106u8, + 228u8, + 243u8, + 104u8, + 59u8, + 22u8, + 26u8, + 59u8, + 115u8, + 105u8, + 208u8, + 124u8, + 157u8, + 82u8, + 199u8, + 1u8, + 171u8, + 105u8, + 85u8, + 62u8, + 4u8, + 195u8, + 182u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 96usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Address, + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + implemention_id: { + let mut v = [0 as u8; 32]; + values + .pop() + .expect(INTERNAL_ERR) + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + old_pool_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + new_pool_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for UpdatePoolImplementation { + const NAME: &'static str = "UpdatePoolImplementation"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct UpdateViewsImplementation { + pub old_views_implementation: Vec, + pub new_views_implementation: Vec, + } + impl UpdateViewsImplementation { + const TOPIC_ID: [u8; 32] = [ + 216u8, + 78u8, + 177u8, + 234u8, + 112u8, + 205u8, + 164u8, + 10u8, + 107u8, + 250u8, + 161u8, + 31u8, + 79u8, + 105u8, + 239u8, + 161u8, + 12u8, + 188u8, + 94u8, + 184u8, + 39u8, + 96u8, + 179u8, + 5u8, + 143u8, + 68u8, + 5u8, + 18u8, + 236u8, + 29u8, + 109u8, + 31u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + return false; + } + if log.data.len() != 64usize { + return false; + } + return log.topics.get(0).expect("bounds already checked").as_ref() + == Self::TOPIC_ID; + } + pub fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + let mut values = ethabi::decode( + &[ethabi::ParamType::Address, ethabi::ParamType::Address], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + old_views_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + new_views_implementation: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for UpdateViewsImplementation { + const NAME: &'static str = "UpdateViewsImplementation"; + fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + Self::match_log(log) + } + fn decode( + log: &substreams_ethereum::pb::eth::v2::Log, + ) -> Result { + Self::decode(log) + } + } + } \ No newline at end of file diff --git a/substreams/ethereum-curve/src/consts.rs b/substreams/ethereum-curve/src/consts.rs index 356bf1f..50181a8 100644 --- a/substreams/ethereum-curve/src/consts.rs +++ b/substreams/ethereum-curve/src/consts.rs @@ -9,6 +9,7 @@ pub const META_POOL_FACTORY: [u8; 20] = hex!("B9fC157394Af804a3578134A6585C0dc9c pub const META_POOL_FACTORY_OLD: [u8; 20] = hex!("0959158b6040D32d04c301A72CBFD6b39E21c9AE"); pub const CRYPTO_SWAP_NG_FACTORY: [u8; 20] = hex!("6A8cbed756804B16E05E741eDaBd5cB544AE21bf"); pub const TRICRYPTO_FACTORY: [u8; 20] = hex!("0c0e5f2fF0ff18a3be9b835635039256dC4B4963"); +pub const TWOCRYPTO_FACTORY: [u8; 20] = hex!("98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f"); pub const STABLESWAP_FACTORY: [u8; 20] = hex!("4F8846Ae9380B90d2E71D5e3D042dff3E7ebb40d"); // Important addresses diff --git a/substreams/ethereum-curve/src/modules.rs b/substreams/ethereum-curve/src/modules.rs index b2437e7..b8ef29f 100644 --- a/substreams/ethereum-curve/src/modules.rs +++ b/substreams/ethereum-curve/src/modules.rs @@ -10,13 +10,11 @@ use substreams::{ use substreams_ethereum::pb::eth; -use crate::{ - pool_changes::{emit_deltas, emit_eth_deltas}, - pool_factories, - pools::emit_specific_pools, -}; +use crate::{pool_changes::emit_eth_deltas, pool_factories, pools::emit_specific_pools}; use tycho_substreams::{ - balances::store_balance_changes, contract::extract_contract_changes, prelude::*, + balances::{extract_balance_deltas_from_tx, store_balance_changes}, + contract::extract_contract_changes, + prelude::*, }; /// This struct purely exists to spoof the `PartialEq` trait for `Transaction` so we can use it in @@ -115,7 +113,15 @@ pub fn map_relative_balances( .flat_map(|tx| { emit_eth_deltas(tx, &tokens_store) .into_iter() - .chain(emit_deltas(tx, &tokens_store)) + .chain(extract_balance_deltas_from_tx(tx, |token, transactor| { + let pool_key = format!("pool:{}", hex::encode(transactor)); + if let Some(tokens) = tokens_store.get_last(pool_key) { + let token_id = hex::encode(token); + tokens.split(':').any(|t| t == token_id) + } else { + false + } + })) }) .collect(); diff --git a/substreams/ethereum-curve/src/pool_changes.rs b/substreams/ethereum-curve/src/pool_changes.rs index e17778e..0efa8a6 100644 --- a/substreams/ethereum-curve/src/pool_changes.rs +++ b/substreams/ethereum-curve/src/pool_changes.rs @@ -2,13 +2,10 @@ use substreams::{ scalar::BigInt, store::{StoreGet, StoreGetString}, }; -use substreams_ethereum::{pb::eth::v2::TransactionTrace, Event}; +use substreams_ethereum::pb::eth::v2::TransactionTrace; use tycho_substreams::prelude::*; -use crate::{ - abi, - consts::{ETH_ADDRESS, WETH_ADDRESS}, -}; +use crate::consts::{ETH_ADDRESS, WETH_ADDRESS}; fn get_pool_tokens(pool_address: &Vec, tokens_store: &StoreGetString) -> Option> { let pool_key = format!("pool:{}", hex::encode(pool_address)); @@ -21,42 +18,6 @@ fn get_pool_tokens(pool_address: &Vec, tokens_store: &StoreGetString) -> Opt ) } -/// Tracks `Transfers` in and out of tracked pools if it matches the specific tokens. -pub fn emit_deltas(tx: &TransactionTrace, tokens_store: &StoreGetString) -> Vec { - tx.logs_with_calls() - .filter_map(|(log, _)| { - let transfer = abi::erc20::events::Transfer::match_and_decode(log)?; - let (component_id, pool_tokens, is_incoming) = - if let Some(pool_tokens) = get_pool_tokens(&transfer.to, tokens_store) { - (hex::encode(&transfer.to), pool_tokens, true) - } else if let Some(pool_tokens) = get_pool_tokens(&transfer.from, tokens_store) { - (hex::encode(&transfer.from), pool_tokens, false) - } else { - return None; - }; - - let token_id = hex::encode(log.address.clone()); - if pool_tokens.contains(&token_id) { - let delta = if is_incoming { transfer.value } else { transfer.value * -1 }; - Some(BalanceDelta { - ord: log.ordinal, - tx: Some(Transaction { - to: tx.to.clone(), - from: tx.from.clone(), - hash: tx.hash.clone(), - index: tx.index.into(), - }), - token: hex::decode(token_id).unwrap(), - delta: delta.to_signed_bytes_be(), - component_id: component_id.into(), - }) - } else { - None - } - }) - .collect::>() -} - /// Tracks ETH balance changes in and out of tracked pools if it matches the specific tokens. /// Note: Pools might report as WETH or ETH. Some pools might even accept either WETH or ETH and /// convert them on the fly (checkout pools with `WETHOptimized` in the name). It's a bit tricky diff --git a/substreams/ethereum-curve/src/pool_factories.rs b/substreams/ethereum-curve/src/pool_factories.rs index d58dc54..cf3c658 100644 --- a/substreams/ethereum-curve/src/pool_factories.rs +++ b/substreams/ethereum-curve/src/pool_factories.rs @@ -566,7 +566,11 @@ pub fn address_map( hash: tx.hash.clone(), index: tx.index.into(), }), - tokens: pool_added.coins.into(), + tokens: pool_added + .coins + .into_iter() + .filter(|token| *token != [0; 20]) + .collect(), contracts: vec![component_id.into()], static_att: vec![ Attribute { @@ -677,6 +681,54 @@ pub fn address_map( None } } + TWOCRYPTO_FACTORY => { + if let Some(pool_added) = + abi::twocrypto_factory::events::TwocryptoPoolDeployed::match_and_decode(log) + { + Some(ProtocolComponent { + id: hex::encode(&pool_added.pool), + tx: Some(Transaction { + to: tx.to.clone(), + from: tx.from.clone(), + hash: tx.hash.clone(), + index: tx.index.into(), + }), + tokens: pool_added.coins.into(), + contracts: vec![pool_added.pool], + static_att: vec![ + Attribute { + name: "pool_type".into(), + value: "twocrypto".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "name".into(), + value: pool_added.name.into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory_name".into(), + value: "twocrypto_factory".into(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "factory".into(), + value: address_to_bytes_with_0x(&TWOCRYPTO_FACTORY), + change: ChangeType::Creation.into(), + }, + ], + change: ChangeType::Creation.into(), + protocol_type: Some(ProtocolType { + name: "curve_pool".into(), + financial_type: FinancialType::Swap.into(), + attribute_schema: Vec::new(), + implementation_type: ImplementationType::Vm.into(), + }), + }) + } else { + None + } + } _ => None, } } @@ -706,6 +758,10 @@ fn get_token_from_pool(pool: &Vec) -> Vec { "bebc44782c7db0a1a60cb6fe97d0b483032ff1c7" => { hex::decode("6c3F90f043a72FA612cbac8115EE7e52BDe6E490").ok() } + // Curve.fi renBTC/wBTC/sBTC (crvRenWSBTC) + "7fc77b5c7614e1533320ea6ddc2eb61fa00a9714" => { + hex::decode("075b1bb99792c9e1041ba13afef80c91a1e70fb3").ok() + } // Placeholder if we can't find the token. It will help us to detect these missing // token easily with a SQL query. _ => hex::decode("1111111111111111111111111111111111111111").ok(), diff --git a/substreams/ethereum-curve/substreams.yaml b/substreams/ethereum-curve/substreams.yaml index 18a7a24..d1a8d6b 100644 --- a/substreams/ethereum-curve/substreams.yaml +++ b/substreams/ethereum-curve/substreams.yaml @@ -1,7 +1,7 @@ specVersion: v0.1.0 package: name: "substreams_curve" - version: v0.1.0 + version: v0.2.0 protobuf: files: diff --git a/substreams/ethereum-curve/test_assets.yaml b/substreams/ethereum-curve/test_assets.yaml index 008d8ae..73e6a9b 100644 --- a/substreams/ethereum-curve/test_assets.yaml +++ b/substreams/ethereum-curve/test_assets.yaml @@ -104,3 +104,38 @@ tests: - "0x0000000000000000000000000000000000000000" static_attributes: creation_tx: "0x2bd59c19f993b83729fb23498f897a58567c6f0b3ee2f00613ba515a7b19fe23" + - name: test_twocrypto_factory_creation + start_block: 19760009 + stop_block: 19763634 + expected_state: + protocol_components: + - id: "0x011e998d2d794424de95935d55a6ca81822ecb2b" + tokens: + - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + static_attributes: + creation_tx: "0x412b745a9467aed14f22d2a4cc30651939872d19cee65053f14dd3eb9d488003" + - id: "0x19d2b5ce188ca60790755204691e38102749297b" + tokens: + - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" + - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + static_attributes: + creation_tx: "0x61118d9903f8344e5971d1e7c781f76e855996408dac979d3a4971cefafa6587" + - id: "0xb3341ca63b6cecf1e1a0d1a99bf0587f4c305652" + tokens: + - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + static_attributes: + creation_tx: "0xc69332294313b3a8f260e0d5b6a50f0d83707f715fbd8016c32ca61a39ce7ad5" + - id: "0x99ca0fbaa278cd62e26f0e9b6d167b07d1f0d51b" + tokens: + - "0x6c4a8973e6633da2da7187669479c27830c7b1c4" + - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + static_attributes: + creation_tx: "0xf2b0c697161f08384c642297e01b3a35f7ec00dd3871d4237a16ae4bb8a1ca99" + - id: "0xde73e407efc75edbafc5bcd62ebb1e7a9b38ebcd" + tokens: + - "0x0d86883faf4ffd7aeb116390af37746f45b6f378" + - "0x78da5799cf427fee11e9996982f4150ece7a99a7" + static_attributes: + creation_tx: "0xd4ad7efdcc16d797dd3494ba02b377da4127fd5b1bd25089858b66e5a7e456ab"