feat(balancer): add missing weighted factories (#103)

* feat(balancer): add weigthed pool factory v1

* feat(balancer): add weigthed pool factory v2 and v3

* fix(evm): fix compilation bug due to a bugged solc version

---------

Co-authored-by: zizou <111426680+flopell@users.noreply.github.com>
This commit is contained in:
Zizou
2024-10-31 18:24:10 +07:00
committed by GitHub
parent d12834cfc5
commit 64ca72cfa9
13 changed files with 5749 additions and 10 deletions

View File

@@ -3,6 +3,7 @@ src = "src"
out = "out"
libs = ["lib"]
via_ir = true
solc_version = "0.8.27" # 0.8.25 and 0.8.26 are broken with via-ir (see https://github.com/ethereum/solidity/issues/15004)
[rpc_endpoints]
mainnet = "${ETH_RPC_URL}"

View File

@@ -9,7 +9,10 @@ import urllib.request
abis = {
# Factories
"WeightedPoolFactory (v4)": "0x897888115Ada5773E02aA29F775430BFB5F34c51",
"WeightedPoolFactoryV1": "0x8E9aa87E45e92bad84D5F8DD1bff34Fb92637dE9",
"WeightedPoolFactoryV2": "0xcC508a455F5b0073973107Db6a878DdBDab957bC",
"WeightedPoolFactoryV3": "0x5Dd94Da3644DDD055fcf6B3E1aa310Bb7801EB8b",
"WeightedPoolFactoryV4": "0x897888115Ada5773E02aA29F775430BFB5F34c51",
"WeightedPool2TokensFactory": "0xA5bf2ddF098bb0Ef6d120C98217dD6B141c74EE0", # 80Bal-20WETH
"ComposableStablePoolFactory (v5)": "0xDB8d758BCb971e482B2C45f7F8a7740283A1bd3A",
"ERC4626LinearPoolFactory (v4)": "0x813EE7a840CE909E7Fea2117A44a90b8063bd4fd",
@@ -33,7 +36,7 @@ if etherscan_key := os.environ.get("ETHERSCAN_API_TOKEN"):
def __main__():
for name, addr in abis.items():
normalized_name = "_".join(re.findall(r"[A-Z]+[a-z]*", name)).lower()
normalized_name = "_".join(re.findall(r"[A-Z]+[a-z]*\d*", name)).lower()
print(f"Getting ABI for {name} at {addr} ({normalized_name})")
try:

View File

@@ -0,0 +1,120 @@
[
{
"inputs": [
{
"internalType": "contract IVault",
"name": "vault",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "PoolCreated",
"type": "event"
},
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "contract IERC20[]",
"name": "tokens",
"type": "address[]"
},
{
"internalType": "uint256[]",
"name": "weights",
"type": "uint256[]"
},
{
"internalType": "uint256",
"name": "swapFeePercentage",
"type": "uint256"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "create",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getPauseConfiguration",
"outputs": [
{
"internalType": "uint256",
"name": "pauseWindowDuration",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "bufferPeriodDuration",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getVault",
"outputs": [
{
"internalType": "contract IVault",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "isPoolFromFactory",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]

View File

@@ -0,0 +1,232 @@
[
{
"inputs": [
{
"internalType": "contract IVault",
"name": "vault",
"type": "address"
},
{
"internalType": "contract IProtocolFeePercentagesProvider",
"name": "protocolFeeProvider",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [],
"name": "FactoryDisabled",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "PoolCreated",
"type": "event"
},
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "contract IERC20[]",
"name": "tokens",
"type": "address[]"
},
{
"internalType": "uint256[]",
"name": "normalizedWeights",
"type": "uint256[]"
},
{
"internalType": "contract IRateProvider[]",
"name": "rateProviders",
"type": "address[]"
},
{
"internalType": "uint256",
"name": "swapFeePercentage",
"type": "uint256"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "create",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "disable",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "selector",
"type": "bytes4"
}
],
"name": "getActionId",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getAuthorizer",
"outputs": [
{
"internalType": "contract IAuthorizer",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getCreationCode",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getCreationCodeContracts",
"outputs": [
{
"internalType": "address",
"name": "contractA",
"type": "address"
},
{
"internalType": "address",
"name": "contractB",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getPauseConfiguration",
"outputs": [
{
"internalType": "uint256",
"name": "pauseWindowDuration",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "bufferPeriodDuration",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getProtocolFeePercentagesProvider",
"outputs": [
{
"internalType": "contract IProtocolFeePercentagesProvider",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getVault",
"outputs": [
{
"internalType": "contract IVault",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isDisabled",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "isPoolFromFactory",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]

View File

@@ -0,0 +1,268 @@
[
{
"inputs": [
{
"internalType": "contract IVault",
"name": "vault",
"type": "address"
},
{
"internalType": "contract IProtocolFeePercentagesProvider",
"name": "protocolFeeProvider",
"type": "address"
},
{
"internalType": "string",
"name": "factoryVersion",
"type": "string"
},
{
"internalType": "string",
"name": "poolVersion",
"type": "string"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [],
"name": "FactoryDisabled",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "PoolCreated",
"type": "event"
},
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"internalType": "string",
"name": "symbol",
"type": "string"
},
{
"internalType": "contract IERC20[]",
"name": "tokens",
"type": "address[]"
},
{
"internalType": "uint256[]",
"name": "normalizedWeights",
"type": "uint256[]"
},
{
"internalType": "contract IRateProvider[]",
"name": "rateProviders",
"type": "address[]"
},
{
"internalType": "uint256",
"name": "swapFeePercentage",
"type": "uint256"
},
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "create",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "disable",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "selector",
"type": "bytes4"
}
],
"name": "getActionId",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getAuthorizer",
"outputs": [
{
"internalType": "contract IAuthorizer",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getCreationCode",
"outputs": [
{
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getCreationCodeContracts",
"outputs": [
{
"internalType": "address",
"name": "contractA",
"type": "address"
},
{
"internalType": "address",
"name": "contractB",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getPauseConfiguration",
"outputs": [
{
"internalType": "uint256",
"name": "pauseWindowDuration",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "bufferPeriodDuration",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getPoolVersion",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getProtocolFeePercentagesProvider",
"outputs": [
{
"internalType": "contract IProtocolFeePercentagesProvider",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getVault",
"outputs": [
{
"internalType": "contract IVault",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "isDisabled",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "pool",
"type": "address"
}
],
"name": "isPoolFromFactory",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
]

View File

@@ -24,8 +24,8 @@ initialized_accounts:
# - "0x1d8f8f00cfa6758d7be78336684788fb0ee0fa46"
# - "0xae78736cd615f374d3085123a210448e74fc6393"
tests:
# WeightedPoolFactory - 0x897888115Ada5773E02aA29F775430BFB5F34c51
- name: test_weighted_pool_creation
# WeightedPoolFactoryV4 - 0x897888115Ada5773E02aA29F775430BFB5F34c51
- name: test_weighted_pool_v4
start_block: 20128706
stop_block: 20128806
expected_components:
@@ -38,7 +38,7 @@ tests:
normalized_weights: "0x5b22307830623161326263326563353030303030222c22307830326336386166306262313430303030225d"
fee: "0x11c37937e08000"
manual_updates: "0x01"
pool_type: "0x5765696768746564506f6f6c466163746f7279"
pool_type: "0x5765696768746564506f6f6c466163746f72795634"
creation_tx: "0xa63c671046ad2075ec8ea83ac21199cf3e3a5f433e72ec4c117cbabfb9b18de2"
# WeightedPool2TokensFactory - 0xA5bf2ddF098bb0Ef6d120C98217dD6B141c74EE0
@@ -160,3 +160,57 @@ tests:
main_token: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
skip_simulation: true
creation_tx: "0x497aa03ce84d236c183204ddfc6762c8e4158da1ebc5e7e18e7f6cceaa497a2a"
# WeigthedPoolFactoryV1 - 0x8E9aa87E45e92bad84D5F8DD1bff34Fb92637dE9
- name: test_weighted_pool_v1
start_block: 13899835
stop_block: 13901090
expected_components:
- id: "0xcb0e14e96f2cefa8550ad8e4aea344f211e5061d00020000000000000000011a"
tokens:
- "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
- "0xcAfE001067cDEF266AfB7Eb5A286dCFD277f3dE5"
static_attributes:
manual_updates: "0x01"
fee: "0x038d7ea4c68000"
normalized_weights: "0x5b22307830326336386166306262313430303030222c22307830623161326263326563353030303030225d"
pool_type: "0x5765696768746564506f6f6c466163746f72795631"
skip_simulation: false
creation_tx: "0xc5c3b384644363aa15cf9a0c33dfebd22df351446bce92ee49ead7d5d896b4e9"
# WeigthedPoolFactoryV2 - 0xcC508a455F5b0073973107Db6a878DdBDab957bC
- name: test_weighted_pool_v2
start_block: 15732922
stop_block: 15742922
initialized_accounts:
expected_components:
- id: "0xe340ebfcaa544da8bb1ee9005f1a346d50ec422e000200000000000000000396"
tokens:
- "0x3472A5A71965499acd81997a54BBA8D852C6E53d"
- "0xae78736Cd615f374D3085123A210448E74Fc6393"
static_attributes:
manual_updates: "0x01"
fee: "0x08e1bc9bf04000"
normalized_weights: "0x5b22307830366630356235396433623230303030222c22307830366630356235396433623230303030225d"
rate_providers: "0x5b22307830303030303030303030303030303030303030303030303030303030303030303030303030303030222c22307831613866383163323536616565396336343065313462623034353363653234376561306466653666225d"
pool_type: "0x5765696768746564506f6f6c466163746f72795632"
skip_simulation: true # can't simulate because it has rate provider
creation_tx: "0x9a949a52e4179d0c57dcffd6884d5787febfb92f8f4b7e114ef8cfbda0292a79"
# WeigthedPoolFactoryV3 - 0x5Dd94Da3644DDD055fcf6B3E1aa310Bb7801EB8b
- name: test_weighted_pool_v3
start_block: 16975289
stop_block: 16975290
expected_components:
- id: "0xd278166dabaf26707362f7cfdd204b277fd2a4600002000000000000000004f6"
tokens:
- "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
- "0xE60779CC1b2c1d0580611c526a8DF0E3f870EC48"
static_attributes:
manual_updates: "0x01"
fee: "0x11c37937e08000"
normalized_weights: "0x5b22307830366630356235396433623230303030222c22307830366630356235396433623230303030225d"
rate_providers: "0x5b22307830303030303030303030303030303030303030303030303030303030303030303030303030303030222c22307830303030303030303030303030303030303030303030303030303030303030303030303030303030225d"
pool_type: "0x5765696768746564506f6f6c466163746f72795633"
skip_simulation: true # not enough liquidity added within more than 100k blocks
creation_tx: "0x3dda8ac9423f0018dffdda343c376cc1781ad12cb49827770351411d84036bf8"

View File

@@ -2,10 +2,13 @@
pub mod yearn_linear_pool_factory;
pub mod composable_stable_pool_factory;
pub mod vault;
pub mod weighted_pool_factory_v4;
pub mod weighted_pool_tokens_factory;
pub mod silo_linear_pool_factory;
pub mod weighted_pool_factory_v3;
pub mod weighted_pool_factory_v2;
pub mod euler_linear_pool_factory;
pub mod weighted_pool_factory;
pub mod weighted_pool_factory_v1;
pub mod managed_pool_factory;
pub mod erc_linear_pool_factory;
pub mod gearbox_linear_pool_factory;

View File

@@ -0,0 +1,633 @@
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 Create {
pub name: String,
pub symbol: String,
pub tokens: Vec<Vec<u8>>,
pub weights: Vec<substreams::scalar::BigInt>,
pub swap_fee_percentage: substreams::scalar::BigInt,
pub owner: Vec<u8>,
}
impl Create {
const METHOD_ID: [u8; 4] = [251u8, 206u8, 3u8, 147u8];
pub fn decode(
call: &substreams_ethereum::pb::eth::v2::Call,
) -> Result<Self, String> {
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::Array(
Box::new(ethabi::ParamType::Address),
),
ethabi::ParamType::Array(
Box::new(ethabi::ParamType::Uint(256usize)),
),
ethabi::ParamType::Uint(256usize),
ethabi::ParamType::Address,
],
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),
tokens: values
.pop()
.expect(INTERNAL_ERR)
.into_array()
.expect(INTERNAL_ERR)
.into_iter()
.map(|inner| {
inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec()
})
.collect(),
weights: values
.pop()
.expect(INTERNAL_ERR)
.into_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)
})
.collect(),
swap_fee_percentage: {
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)
},
owner: values
.pop()
.expect(INTERNAL_ERR)
.into_address()
.expect(INTERNAL_ERR)
.as_bytes()
.to_vec(),
})
}
pub fn encode(&self) -> Vec<u8> {
let data = ethabi::encode(
&[
ethabi::Token::String(self.name.clone()),
ethabi::Token::String(self.symbol.clone()),
{
let v = self
.tokens
.iter()
.map(|inner| ethabi::Token::Address(
ethabi::Address::from_slice(&inner),
))
.collect();
ethabi::Token::Array(v)
},
{
let v = self
.weights
.iter()
.map(|inner| ethabi::Token::Uint(
ethabi::Uint::from_big_endian(
match inner.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(),
),
))
.collect();
ethabi::Token::Array(v)
},
ethabi::Token::Uint(
ethabi::Uint::from_big_endian(
match self.swap_fee_percentage.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::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<Vec<u8>, String> {
Self::output(call.return_data.as_ref())
}
pub fn output(data: &[u8]) -> Result<Vec<u8>, 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<u8>) -> Option<Vec<u8>> {
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 Create {
const NAME: &'static str = "create";
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, String> {
Self::decode(call)
}
fn encode(&self) -> Vec<u8> {
self.encode()
}
}
impl substreams_ethereum::rpc::RPCDecodable<Vec<u8>> for Create {
fn output(data: &[u8]) -> Result<Vec<u8>, String> {
Self::output(data)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct GetPauseConfiguration {}
impl GetPauseConfiguration {
const METHOD_ID: [u8; 4] = [45u8, 164u8, 124u8, 64u8];
pub fn decode(
call: &substreams_ethereum::pb::eth::v2::Call,
) -> Result<Self, String> {
Ok(Self {})
}
pub fn encode(&self) -> Vec<u8> {
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<
(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<u8>,
) -> 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 GetPauseConfiguration {
const NAME: &'static str = "getPauseConfiguration";
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, String> {
Self::decode(call)
}
fn encode(&self) -> Vec<u8> {
self.encode()
}
}
impl substreams_ethereum::rpc::RPCDecodable<
(substreams::scalar::BigInt, substreams::scalar::BigInt),
> for GetPauseConfiguration {
fn output(
data: &[u8],
) -> Result<
(substreams::scalar::BigInt, substreams::scalar::BigInt),
String,
> {
Self::output(data)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct GetVault {}
impl GetVault {
const METHOD_ID: [u8; 4] = [141u8, 146u8, 138u8, 248u8];
pub fn decode(
call: &substreams_ethereum::pb::eth::v2::Call,
) -> Result<Self, String> {
Ok(Self {})
}
pub fn encode(&self) -> Vec<u8> {
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<Vec<u8>, String> {
Self::output(call.return_data.as_ref())
}
pub fn output(data: &[u8]) -> Result<Vec<u8>, 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<u8>) -> Option<Vec<u8>> {
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 GetVault {
const NAME: &'static str = "getVault";
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, String> {
Self::decode(call)
}
fn encode(&self) -> Vec<u8> {
self.encode()
}
}
impl substreams_ethereum::rpc::RPCDecodable<Vec<u8>> for GetVault {
fn output(data: &[u8]) -> Result<Vec<u8>, String> {
Self::output(data)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct IsPoolFromFactory {
pub pool: Vec<u8>,
}
impl IsPoolFromFactory {
const METHOD_ID: [u8; 4] = [102u8, 52u8, 183u8, 83u8];
pub fn decode(
call: &substreams_ethereum::pb::eth::v2::Call,
) -> Result<Self, String> {
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<u8> {
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<bool, String> {
Self::output(call.return_data.as_ref())
}
pub fn output(data: &[u8]) -> Result<bool, String> {
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<u8>) -> Option<bool> {
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 IsPoolFromFactory {
const NAME: &'static str = "isPoolFromFactory";
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, String> {
Self::decode(call)
}
fn encode(&self) -> Vec<u8> {
self.encode()
}
}
impl substreams_ethereum::rpc::RPCDecodable<bool> for IsPoolFromFactory {
fn output(data: &[u8]) -> Result<bool, 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 PoolCreated {
pub pool: Vec<u8>,
}
impl PoolCreated {
const TOPIC_ID: [u8; 32] = [
131u8,
164u8,
143u8,
188u8,
252u8,
153u8,
19u8,
53u8,
49u8,
78u8,
116u8,
208u8,
73u8,
106u8,
171u8,
106u8,
25u8,
135u8,
233u8,
146u8,
221u8,
200u8,
93u8,
221u8,
188u8,
196u8,
214u8,
221u8,
110u8,
242u8,
233u8,
252u8,
];
pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool {
if log.topics.len() != 2usize {
return false;
}
if log.data.len() != 0usize {
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<Self, String> {
Ok(Self {
pool: ethabi::decode(
&[ethabi::ParamType::Address],
log.topics[1usize].as_ref(),
)
.map_err(|e| {
format!(
"unable to decode param 'pool' from topic of type 'address': {:?}",
e
)
})?
.pop()
.expect(INTERNAL_ERR)
.into_address()
.expect(INTERNAL_ERR)
.as_bytes()
.to_vec(),
})
}
}
impl substreams_ethereum::Event for PoolCreated {
const NAME: &'static str = "PoolCreated";
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, String> {
Self::decode(log)
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -52,11 +52,11 @@ pub fn address_map(
tx: &TransactionTrace,
) -> Option<ProtocolComponent> {
match *pool_factory_address {
hex!("897888115Ada5773E02aA29F775430BFB5F34c51") => {
hex!("8E9aa87E45e92bad84D5F8DD1bff34Fb92637dE9") => {
let create_call =
abi::weighted_pool_factory::functions::Create::match_and_decode(call)?;
abi::weighted_pool_factory_v1::functions::Create::match_and_decode(call)?;
let pool_created =
abi::weighted_pool_factory::events::PoolCreated::match_and_decode(log)?;
abi::weighted_pool_factory_v1::events::PoolCreated::match_and_decode(log)?;
let pool_registered = get_pool_registered(tx, &pool_created.pool);
Some(
@@ -67,7 +67,99 @@ pub fn address_map(
.with_contracts(&[pool_created.pool, VAULT_ADDRESS.to_vec()])
.with_tokens(&create_call.tokens)
.with_attributes(&[
("pool_type", "WeightedPoolFactory".as_bytes()),
("pool_type", "WeightedPoolFactoryV1".as_bytes()),
("normalized_weights", &json_serialize_bigint_list(&create_call.weights)),
(
"fee",
&create_call
.swap_fee_percentage
.to_signed_bytes_be(),
),
("manual_updates", &[1u8]),
])
.as_swap_type("balancer_pool", ImplementationType::Vm),
)
}
hex!("cC508a455F5b0073973107Db6a878DdBDab957bC") => {
let create_call =
abi::weighted_pool_factory_v2::functions::Create::match_and_decode(call)?;
let pool_created =
abi::weighted_pool_factory_v2::events::PoolCreated::match_and_decode(log)?;
let pool_registered = get_pool_registered(tx, &pool_created.pool);
Some(
ProtocolComponent::new(
&format!("0x{}", hex::encode(pool_registered.pool_id)),
&(tx.into()),
)
.with_contracts(&[pool_created.pool, VAULT_ADDRESS.to_vec()])
.with_tokens(&create_call.tokens)
.with_attributes(&[
("pool_type", "WeightedPoolFactoryV2".as_bytes()),
(
"normalized_weights",
&json_serialize_bigint_list(&create_call.normalized_weights),
),
("rate_providers", &json_serialize_address_list(&create_call.rate_providers)),
(
"fee",
&create_call
.swap_fee_percentage
.to_signed_bytes_be(),
),
("manual_updates", &[1u8]),
])
.as_swap_type("balancer_pool", ImplementationType::Vm),
)
}
hex!("5Dd94Da3644DDD055fcf6B3E1aa310Bb7801EB8b") => {
let create_call =
abi::weighted_pool_factory_v3::functions::Create::match_and_decode(call)?;
let pool_created =
abi::weighted_pool_factory_v3::events::PoolCreated::match_and_decode(log)?;
let pool_registered = get_pool_registered(tx, &pool_created.pool);
Some(
ProtocolComponent::new(
&format!("0x{}", hex::encode(pool_registered.pool_id)),
&(tx.into()),
)
.with_contracts(&[pool_created.pool, VAULT_ADDRESS.to_vec()])
.with_tokens(&create_call.tokens)
.with_attributes(&[
("pool_type", "WeightedPoolFactoryV3".as_bytes()),
(
"normalized_weights",
&json_serialize_bigint_list(&create_call.normalized_weights),
),
("rate_providers", &json_serialize_address_list(&create_call.rate_providers)),
(
"fee",
&create_call
.swap_fee_percentage
.to_signed_bytes_be(),
),
("manual_updates", &[1u8]),
])
.as_swap_type("balancer_pool", ImplementationType::Vm),
)
}
hex!("897888115Ada5773E02aA29F775430BFB5F34c51") => {
let create_call =
abi::weighted_pool_factory_v4::functions::Create::match_and_decode(call)?;
let pool_created =
abi::weighted_pool_factory_v4::events::PoolCreated::match_and_decode(log)?;
let pool_registered = get_pool_registered(tx, &pool_created.pool);
Some(
ProtocolComponent::new(
&format!("0x{}", hex::encode(pool_registered.pool_id)),
&(tx.into()),
)
.with_contracts(&[pool_created.pool, VAULT_ADDRESS.to_vec()])
.with_tokens(&create_call.tokens)
.with_attributes(&[
("pool_type", "WeightedPoolFactoryV4".as_bytes()),
(
"normalized_weights",
&json_serialize_bigint_list(&create_call.normalized_weights),