diff --git a/Cargo.lock b/Cargo.lock index 53aec90..19ad98d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,6 +216,27 @@ dependencies = [ "typenum", ] +[[package]] +name = "curve_finance_substream" +version = "0.0.1" +dependencies = [ + "anyhow", + "ethabi", + "hex", + "hex-literal", + "num-bigint", + "num-traits", + "prost 0.11.9", + "prost-types 0.11.9", + "regex", + "substreams 0.5.10", + "substreams-common", + "substreams-database-change", + "substreams-entity-change 1.3.0", + "substreams-ethereum", + "substreams-helper", +] + [[package]] name = "digest" version = "0.10.7" @@ -1118,6 +1139,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "substreams-database-change" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed32ca6fc7fa4b7a684d3abd5bb0545aadd2df82402e7336443cdbb6f8b350c3" +dependencies = [ + "prost 0.11.9", + "prost-types 0.11.9", + "substreams 0.5.10", +] + [[package]] name = "substreams-entity-change" version = "0.3.0" @@ -1172,11 +1204,12 @@ dependencies = [ [[package]] name = "substreams-ethereum" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a426822f6032fa28145cb2cb7661e70554da839a40ee08b6348f1479a44e1b" +checksum = "8bd2614efbfe4fc3f9e5bc342d68b6d5a20640b2e3c2258094c7bce59ea29667" dependencies = [ "getrandom", + "num-bigint", "substreams 0.5.10", "substreams-ethereum-abigen", "substreams-ethereum-core", @@ -1185,9 +1218,9 @@ dependencies = [ [[package]] name = "substreams-ethereum-abigen" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2ba34bc4d19288e7487aa2b13ee75955222809d2dab48c9dad33230a6f4732" +checksum = "c7e52092b876ccda2087dd08cf769398c3dce591de3a3f46570d5596b8fd6144" dependencies = [ "anyhow", "ethabi", @@ -1202,9 +1235,9 @@ dependencies = [ [[package]] name = "substreams-ethereum-core" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f680a56fc8df55dfd0b3465af2ed6f0eb471b4a0b5a9e0e56c13377911104b01" +checksum = "06601ff5192dc844f4c48961f196b12104e4cbf47dcfdef78ba77d10358b1109" dependencies = [ "bigdecimal", "ethabi", @@ -1218,13 +1251,14 @@ dependencies = [ [[package]] name = "substreams-ethereum-derive" -version = "0.8.0" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b40d3bcb83759b62c2ed372b582be8ba46fc844362a7f7a35fa0269590066118" +checksum = "01728bb412313d36b376be0aed38a8ca7dfbc28adaa658e3df47530b528b4c64" dependencies = [ "ethabi", "heck", "hex", + "num-bigint", "proc-macro2", "quote", "substreams-ethereum-abigen", diff --git a/Cargo.toml b/Cargo.toml index eedf6a7..cd05b87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,12 +15,13 @@ members = [ "eth-supply", "synthetix", "aave-v2", + "curve-finance", ] exclude = ["messari-cli"] [workspace.dependencies] substreams = "0.5.0" -substreams-ethereum = "0.8.0" +substreams-ethereum = "0.9" substreams-solana = "0.1.0" [build] diff --git a/curve-finance/Cargo.toml b/curve-finance/Cargo.toml new file mode 100644 index 0000000..4b80fbc --- /dev/null +++ b/curve-finance/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "curve_finance_substream" +version = "0.0.1" +edition = "2021" +repository = "https://github.com/messari/substreams/" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +ethabi = "17" +hex = "0.4.3" +hex-literal = "0.3.4" +num-bigint = "0.4" +num-traits = "0.2.15" +prost = "0.11" +prost-types = "0.11" +substreams = "0.5" +substreams-ethereum = "0.9" +substreams-database-change = "1" +substreams-entity-change = "1" +substreams-helper = { path = "../substreams-helper" } + +[build-dependencies] +anyhow = "1" +regex = "1.8" +substreams-ethereum = "0.9" +substreams-common = { path = "../common" } diff --git a/curve-finance/Makefile b/curve-finance/Makefile new file mode 100644 index 0000000..0f72285 --- /dev/null +++ b/curve-finance/Makefile @@ -0,0 +1,21 @@ +.PHONY: build_all +build_all: + $(MAKE) -C ../erc20-price build + $(MAKE) -C ../erc20-price pack + cargo build --target wasm32-unknown-unknown --release + +.PHONY: build +build: + cargo build --target wasm32-unknown-unknown --release + +.PHONY: run +run: + substreams run -e polygon.streamingfast.io:443 substreams.yaml map_pool_fees --debug-modules-initial-snapshot store_pools -s 13991900 -t +10 + +.PHONY: build_csv +build_csv: + substreams-sink-csv -e polygon.substreams.pinax.network:9000 --manifest ./curve-finance-substream-v0.1.0.spkg --module-name map_pool_fees --start-block 13991900 + +.PHONY: pack +pack: + substreams pack ./substreams.yaml diff --git a/curve-finance/abi/pool_contract.json b/curve-finance/abi/pool_contract.json new file mode 100644 index 0000000..33ca7d3 --- /dev/null +++ b/curve-finance/abi/pool_contract.json @@ -0,0 +1,629 @@ +[ + { + "name": "TokenExchange", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "int128", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "int128", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "TokenExchangeUnderlying", + "inputs": [ + { "name": "buyer", "type": "address", "indexed": true }, + { "name": "sold_id", "type": "int128", "indexed": false }, + { "name": "tokens_sold", "type": "uint256", "indexed": false }, + { "name": "bought_id", "type": "int128", "indexed": false }, + { "name": "tokens_bought", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "AddLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "fees", "type": "uint256[3]", "indexed": false }, + { "name": "invariant", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidity", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "fees", "type": "uint256[3]", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityOne", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amount", "type": "uint256", "indexed": false }, + { "name": "coin_amount", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RemoveLiquidityImbalance", + "inputs": [ + { "name": "provider", "type": "address", "indexed": true }, + { "name": "token_amounts", "type": "uint256[3]", "indexed": false }, + { "name": "fees", "type": "uint256[3]", "indexed": false }, + { "name": "invariant", "type": "uint256", "indexed": false }, + { "name": "token_supply", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewAdmin", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "admin", "type": "address", "indexed": true } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewAdmin", + "inputs": [{ "name": "admin", "type": "address", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "name": "CommitNewFee", + "inputs": [ + { "name": "deadline", "type": "uint256", "indexed": true }, + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "offpeg_fee_multiplier", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "NewFee", + "inputs": [ + { "name": "fee", "type": "uint256", "indexed": false }, + { "name": "admin_fee", "type": "uint256", "indexed": false }, + { "name": "offpeg_fee_multiplier", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "RampA", + "inputs": [ + { "name": "old_A", "type": "uint256", "indexed": false }, + { "name": "new_A", "type": "uint256", "indexed": false }, + { "name": "initial_time", "type": "uint256", "indexed": false }, + { "name": "future_time", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "StopRampA", + "inputs": [ + { "name": "A", "type": "uint256", "indexed": false }, + { "name": "t", "type": "uint256", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [ + { "name": "_coins", "type": "address[3]" }, + { "name": "_underlying_coins", "type": "address[3]" }, + { "name": "_pool_token", "type": "address" }, + { "name": "_A", "type": "uint256" }, + { "name": "_fee", "type": "uint256" }, + { "name": "_admin_fee", "type": "uint256" }, + { "name": "_offpeg_fee_multiplier", "type": "uint256" } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 10374 + }, + { + "stateMutability": "view", + "type": "function", + "name": "A_precise", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 10336 + }, + { + "stateMutability": "view", + "type": "function", + "name": "dynamic_fee", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 22113 + }, + { + "stateMutability": "view", + "type": "function", + "name": "balances", + "inputs": [{ "name": "i", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 7358 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 2702067 + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_token_amount", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "is_deposit", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 5368162 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_min_mint_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_liquidity", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_min_mint_amount", "type": "uint256" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6289374 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_dy_underlying", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6289404 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6465508 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "exchange_underlying", + "inputs": [ + { "name": "i", "type": "int128" }, + { "name": "j", "type": "int128" }, + { "name": "dx", "type": "uint256" }, + { "name": "min_dy", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 6484358 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "_min_amounts", "type": "uint256[3]" } + ], + "outputs": [{ "name": "", "type": "uint256[3]" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity", + "inputs": [ + { "name": "_amount", "type": "uint256" }, + { "name": "_min_amounts", "type": "uint256[3]" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256[3]" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_imbalance", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_max_burn_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_imbalance", + "inputs": [ + { "name": "_amounts", "type": "uint256[3]" }, + { "name": "_max_burn_amount", "type": "uint256" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "calc_withdraw_one_coin", + "inputs": [ + { "name": "_token_amount", "type": "uint256" }, + { "name": "i", "type": "int128" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 4491030 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "_token_amount", "type": "uint256" }, + { "name": "i", "type": "int128" }, + { "name": "_min_amount", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_liquidity_one_coin", + "inputs": [ + { "name": "_token_amount", "type": "uint256" }, + { "name": "i", "type": "int128" }, + { "name": "_min_amount", "type": "uint256" }, + { "name": "_use_underlying", "type": "bool" } + ], + "outputs": [{ "name": "", "type": "uint256" }] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "ramp_A", + "inputs": [ + { "name": "_future_A", "type": "uint256" }, + { "name": "_future_time", "type": "uint256" } + ], + "outputs": [], + "gas": 159459 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "stop_ramp_A", + "inputs": [], + "outputs": [], + "gas": 154920 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_new_fee", + "inputs": [ + { "name": "new_fee", "type": "uint256" }, + { "name": "new_admin_fee", "type": "uint256" }, + { "name": "new_offpeg_fee_multiplier", "type": "uint256" } + ], + "outputs": [], + "gas": 148809 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_new_fee", + "inputs": [], + "outputs": [], + "gas": 141271 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_new_parameters", + "inputs": [], + "outputs": [], + "gas": 23012 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "commit_transfer_ownership", + "inputs": [{ "name": "_owner", "type": "address" }], + "outputs": [], + "gas": 77050 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "apply_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 65727 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "revert_transfer_ownership", + "inputs": [], + "outputs": [], + "gas": 23102 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "withdraw_admin_fees", + "inputs": [], + "outputs": [], + "gas": 90981 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "donate_admin_fees", + "inputs": [], + "outputs": [], + "gas": 63303 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "kill_me", + "inputs": [], + "outputs": [], + "gas": 40385 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "unkill_me", + "inputs": [], + "outputs": [], + "gas": 23222 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_aave_referral", + "inputs": [{ "name": "referral_code", "type": "uint256" }], + "outputs": [], + "gas": 38352 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_reward_receiver", + "inputs": [{ "name": "_reward_receiver", "type": "address" }], + "outputs": [], + "gas": 38385 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_admin_fee_receiver", + "inputs": [{ "name": "_admin_fee_receiver", "type": "address" }], + "outputs": [], + "gas": 38415 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coins", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3397 + }, + { + "stateMutability": "view", + "type": "function", + "name": "underlying_coins", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3427 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_balances", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3457 + }, + { + "stateMutability": "view", + "type": "function", + "name": "fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3378 + }, + { + "stateMutability": "view", + "type": "function", + "name": "offpeg_fee_multiplier", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3408 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3438 + }, + { + "stateMutability": "view", + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3468 + }, + { + "stateMutability": "view", + "type": "function", + "name": "lp_token", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3498 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3528 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3558 + }, + { + "stateMutability": "view", + "type": "function", + "name": "initial_A_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3588 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_A_time", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3618 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_actions_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3648 + }, + { + "stateMutability": "view", + "type": "function", + "name": "transfer_ownership_deadline", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3678 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3708 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_admin_fee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3738 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_offpeg_fee_multiplier", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3768 + }, + { + "stateMutability": "view", + "type": "function", + "name": "future_owner", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3798 + }, + { + "stateMutability": "view", + "type": "function", + "name": "reward_receiver", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3828 + }, + { + "stateMutability": "view", + "type": "function", + "name": "admin_fee_receiver", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3858 + } +] diff --git a/curve-finance/abi/registry_contract.json b/curve-finance/abi/registry_contract.json new file mode 100644 index 0000000..6b8afd3 --- /dev/null +++ b/curve-finance/abi/registry_contract.json @@ -0,0 +1,438 @@ +[ + { + "name": "PoolAdded", + "inputs": [ + { "name": "pool", "type": "address", "indexed": true }, + { "name": "rate_method_id", "type": "bytes", "indexed": false } + ], + "anonymous": false, + "type": "event" + }, + { + "name": "PoolRemoved", + "inputs": [{ "name": "pool", "type": "address", "indexed": true }], + "anonymous": false, + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [{ "name": "_address_provider", "type": "address" }], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" } + ], + "outputs": [{ "name": "", "type": "address" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "find_pool_for_coins", + "inputs": [ + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" }, + { "name": "i", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "address" }] + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_n_coins", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[2]" }], + "gas": 2836 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coins", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "address[8]" }], + "gas": 23802 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_coins", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "address[8]" }], + "gas": 23894 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_decimals", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 10474 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_decimals", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 10566 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_rates", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 92272 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_gauges", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [ + { "name": "", "type": "address[10]" }, + { "name": "", "type": "int128[10]" } + ], + "gas": 28534 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_balances", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 42130 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_underlying_balances", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 379602 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_virtual_price_from_lp_token", + "inputs": [{ "name": "_token", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 5287 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_A", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3105 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_parameters", + "inputs": [{ "name": "_pool", "type": "address" }], + "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" } + ], + "gas": 25860 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_fees", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[2]" }], + "gas": 5601 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_admin_balances", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256[8]" }], + "gas": 87173 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_indices", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" } + ], + "outputs": [ + { "name": "", "type": "int128" }, + { "name": "", "type": "int128" }, + { "name": "", "type": "bool" } + ], + "gas": 47931 + }, + { + "stateMutability": "view", + "type": "function", + "name": "estimate_gas_used", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_from", "type": "address" }, + { "name": "_to", "type": "address" } + ], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 60049 + }, + { + "stateMutability": "view", + "type": "function", + "name": "is_meta", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "bool" }], + "gas": 3200 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_name", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "string" }], + "gas": 13523 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_count", + "inputs": [{ "name": "_coin", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3251 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin_swap_complement", + "inputs": [ + { "name": "_coin", "type": "address" }, + { "name": "_index", "type": "uint256" } + ], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3390 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_asset_type", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3311 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool", + "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": "_name", "type": "string" } + ], + "outputs": [], + "gas": 63156468 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_pool_without_underlying", + "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": "_name", "type": "string" } + ], + "outputs": [], + "gas": 32112470 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_n_coins", "type": "uint256" }, + { "name": "_lp_token", "type": "address" }, + { "name": "_decimals", "type": "uint256" }, + { "name": "_name", "type": "string" } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "add_metapool", + "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" } + ], + "outputs": [] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "remove_pool", + "inputs": [{ "name": "_pool", "type": "address" }], + "outputs": [], + "gas": 801545294718 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_gas_estimates", + "inputs": [ + { "name": "_addr", "type": "address[5]" }, + { "name": "_amount", "type": "uint256[2][5]" } + ], + "outputs": [], + "gas": 393820 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_coin_gas_estimates", + "inputs": [ + { "name": "_addr", "type": "address[10]" }, + { "name": "_amount", "type": "uint256[10]" } + ], + "outputs": [], + "gas": 395407 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_gas_estimate_contract", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_estimator", "type": "address" } + ], + "outputs": [], + "gas": 75989 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_liquidity_gauges", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_liquidity_gauges", "type": "address[10]" } + ], + "outputs": [], + "gas": 422130 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "set_pool_asset_type", + "inputs": [ + { "name": "_pool", "type": "address" }, + { "name": "_asset_type", "type": "uint256" } + ], + "outputs": [], + "gas": 76027 + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "batch_set_pool_asset_type", + "inputs": [ + { "name": "_pools", "type": "address[32]" }, + { "name": "_asset_types", "type": "uint256[32]" } + ], + "outputs": [], + "gas": 1176807 + }, + { + "stateMutability": "view", + "type": "function", + "name": "address_provider", + "inputs": [], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3348 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_list", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3487 + }, + { + "stateMutability": "view", + "type": "function", + "name": "pool_count", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3408 + }, + { + "stateMutability": "view", + "type": "function", + "name": "coin_count", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3438 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_coin", + "inputs": [{ "name": "arg0", "type": "uint256" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3577 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_pool_from_lp_token", + "inputs": [{ "name": "arg0", "type": "address" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3713 + }, + { + "stateMutability": "view", + "type": "function", + "name": "get_lp_token", + "inputs": [{ "name": "arg0", "type": "address" }], + "outputs": [{ "name": "", "type": "address" }], + "gas": 3743 + }, + { + "stateMutability": "view", + "type": "function", + "name": "last_updated", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256" }], + "gas": 3558 + } +] diff --git a/curve-finance/build.rs b/curve-finance/build.rs new file mode 100644 index 0000000..fb321d3 --- /dev/null +++ b/curve-finance/build.rs @@ -0,0 +1,10 @@ +use anyhow::{Ok, Result}; +use substreams_common::codegen; + +fn main() -> Result<(), anyhow::Error> { + println!("cargo:rerun-if-changed=proto"); + println!("cargo:rerun-if-changed=abi"); + codegen::generate(None)?; + + Ok(()) +} diff --git a/curve-finance/proto/contract.proto b/curve-finance/proto/contract.proto new file mode 100644 index 0000000..add2764 --- /dev/null +++ b/curve-finance/proto/contract.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +import "google/protobuf/timestamp.proto"; +package messari.contract.v1; + +message Pools { + repeated Pool pools = 1; +} + +message Pool { + string address = 1; + + int64 log_index = 2; + int64 block_number = 3; + + google.protobuf.Timestamp block_timestmap = 4; + int64 transaction_index = 5; + string transaction_hash = 6; +} + +message PoolFees { + repeated PoolFee fees = 1; +} + +message PoolFee { + string address = 1; + + optional uint64 fee = 2; + optional uint64 admin_fee = 3; + + int64 log_index = 5; + int64 block_number = 6; + + google.protobuf.Timestamp block_timestmap = 7; + int64 transaction_index = 8; + string transaction_hash = 9; +} \ No newline at end of file diff --git a/curve-finance/rust-toolchain.toml b/curve-finance/rust-toolchain.toml new file mode 100644 index 0000000..0a0b90a --- /dev/null +++ b/curve-finance/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "1.64.0" +components = [ "rustfmt" ] +targets = [ "wasm32-unknown-unknown" ] diff --git a/curve-finance/src/abi.rs b/curve-finance/src/abi.rs new file mode 100644 index 0000000..84650b3 --- /dev/null +++ b/curve-finance/src/abi.rs @@ -0,0 +1,10 @@ +// DO NOT EDIT - the file is generated by build script +#[rustfmt::skip] +#[allow(unused_imports)] +#[path = "../target/abi/pool_contract.rs"] +pub mod pool_contract; + +#[rustfmt::skip] +#[allow(unused_imports)] +#[path = "../target/abi/registry_contract.rs"] +pub mod registry_contract; diff --git a/curve-finance/src/common/constants.rs b/curve-finance/src/common/constants.rs new file mode 100644 index 0000000..e23af3e --- /dev/null +++ b/curve-finance/src/common/constants.rs @@ -0,0 +1 @@ +pub const REGISTRY_ADDRESS: &str = "0x094d12e5b541784701fd8d65f11fc0598fbc6332"; \ No newline at end of file diff --git a/curve-finance/src/common/mod.rs b/curve-finance/src/common/mod.rs new file mode 100644 index 0000000..49e8074 --- /dev/null +++ b/curve-finance/src/common/mod.rs @@ -0,0 +1,2 @@ +#[path = "constants.rs"] +pub(crate) mod constants; diff --git a/curve-finance/src/lib.rs b/curve-finance/src/lib.rs new file mode 100644 index 0000000..6470a6d --- /dev/null +++ b/curve-finance/src/lib.rs @@ -0,0 +1,6 @@ +mod abi; +mod common; +mod modules; +mod pb; + +pub use modules::*; diff --git a/curve-finance/src/modules/1_map_pool_created.rs b/curve-finance/src/modules/1_map_pool_created.rs new file mode 100644 index 0000000..36d5492 --- /dev/null +++ b/curve-finance/src/modules/1_map_pool_created.rs @@ -0,0 +1,37 @@ +use std::str::FromStr; + +use ethabi::ethereum_types::Address; +use substreams_ethereum::pb::eth::v2::{self as eth}; +use substreams_helper::event_handler::EventHandler; +use substreams_helper::hex::Hexable; + +use crate::abi::registry_contract::events::PoolAdded; +use crate::common::constants; +use crate::pb::contract::v1::{Pool, Pools}; + +#[substreams::handlers::map] +pub fn map_pool_created(blk: eth::Block) -> Result { + let mut pools: Vec = vec![]; + + get_pools(&blk, &mut pools); + Ok(Pools { pools }) +} + +fn get_pools(blk: ð::Block, pools: &mut Vec) { + let mut on_pair_created = |event: PoolAdded, tx: ð::TransactionTrace, log: ð::Log| { + pools.push(Pool { + address: event.pool.to_hex(), + log_index: log.index as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + transaction_index: tx.index as i64, + transaction_hash: tx.hash.to_hex(), + }) + }; + + let mut eh = EventHandler::new(blk); + eh.filter_by_address(vec![Address::from_str(constants::REGISTRY_ADDRESS).unwrap()]); + + eh.on::(&mut on_pair_created); + eh.handle_events(); +} diff --git a/curve-finance/src/modules/2_store_pools.rs b/curve-finance/src/modules/2_store_pools.rs new file mode 100644 index 0000000..6254d78 --- /dev/null +++ b/curve-finance/src/modules/2_store_pools.rs @@ -0,0 +1,12 @@ +use substreams::store::StoreNew; +use substreams::store::StoreSetIfNotExists; +use substreams::store::StoreSetIfNotExistsString; + +use crate::pb::contract::v1::Pools; + +#[substreams::handlers::store] +pub fn store_pools(pools_created: Pools, store: StoreSetIfNotExistsString) { + for pool in pools_created.pools { + store.set_if_not_exists(0, &pool.address, &pool.address); + } +} diff --git a/curve-finance/src/modules/3_map_pool_fees.rs b/curve-finance/src/modules/3_map_pool_fees.rs new file mode 100644 index 0000000..714dfec --- /dev/null +++ b/curve-finance/src/modules/3_map_pool_fees.rs @@ -0,0 +1,62 @@ +use substreams::log; +use substreams::scalar::BigInt; +use substreams::store::{StoreGet, StoreGetString}; +use substreams_ethereum::pb::eth::rpc::RpcResponse; +use substreams_ethereum::pb::eth::v2::{self as eth}; +use substreams_ethereum::rpc::RpcBatch; +use substreams_helper::hex::Hexable; + +use crate::abi::pool_contract::functions::{AdminFee, Fee}; +use crate::pb::contract::v1::{PoolFee, PoolFees}; + +#[substreams::handlers::map] +pub fn map_pool_fees( + blk: eth::Block, + pools_store: StoreGetString, +) -> Result { + let mut fees: Vec = vec![]; + + for log in blk.logs() { + if pools_store + .get_last(log.address().to_owned().to_hex()) + .is_none() + { + continue; + } + + let pool_fees = get_pool_fees(log.address().to_vec()); + + fees.push(PoolFee { + address: log.address().to_owned().to_hex(), + + fee: RpcBatch::decode::<_, Fee>(&pool_fees[0]).map(|x| x.to_u64()), + admin_fee: RpcBatch::decode::<_, Fee>(&pool_fees[1]).map(|x| x.to_u64()), + // admin_balances: admin_balances, + + log_index: log.index() as i64, + block_number: blk.number as i64, + block_timestmap: Some(blk.timestamp().to_owned()), + + transaction_index: log.receipt.transaction.index as i64, + transaction_hash: log.receipt.transaction.hash.to_hex(), + }) + } + + Ok(PoolFees { fees }) +} + +fn get_pool_fees(contract: Vec) -> Vec { + let batch = RpcBatch::new(); + + let responses = batch + .add(Fee {}, contract.clone()) + .add(AdminFee {}, contract.clone()) + .execute() + .unwrap() + .responses; + + // let fee = RpcBatch::decode::<_, Fee>(&responses[0]); + // let admin_fee = RpcBatch::decode::<_, AdminFee>(&responses[1]); + + responses +} diff --git a/curve-finance/src/modules/mod.rs b/curve-finance/src/modules/mod.rs new file mode 100644 index 0000000..dab7481 --- /dev/null +++ b/curve-finance/src/modules/mod.rs @@ -0,0 +1,12 @@ +#[path = "1_map_pool_created.rs"] +mod map_pool_created; + +#[path = "2_store_pools.rs"] +mod store_pools; + +#[path = "3_map_pool_fees.rs"] +mod map_pool_fees; + +pub use map_pool_created::map_pool_created; +pub use store_pools::store_pools; +pub use map_pool_fees::map_pool_fees; diff --git a/curve-finance/src/pb.rs b/curve-finance/src/pb.rs new file mode 100644 index 0000000..7d94c4f --- /dev/null +++ b/curve-finance/src/pb.rs @@ -0,0 +1,29 @@ +#[rustfmt::skip] +#[path = "../target/pb/messari.common.v1.rs"] +pub(in crate::pb) mod common_v1; + +pub mod common { + pub mod v1 { + pub use super::super::common_v1::*; + } +} + +#[rustfmt::skip] +#[path = "../target/pb/messari.contract.v1.rs"] +pub(in crate::pb) mod contract_v1; + +pub mod contract { + pub mod v1 { + pub use super::super::contract_v1::*; + } +} + +#[rustfmt::skip] +#[path = "../target/pb/messari.erc20.v1.rs"] +pub(in crate::pb) mod erc20_v1; + +pub mod erc20 { + pub mod v1 { + pub use super::super::erc20_v1::*; + } +} diff --git a/curve-finance/substreams.yaml b/curve-finance/substreams.yaml new file mode 100644 index 0000000..2004836 --- /dev/null +++ b/curve-finance/substreams.yaml @@ -0,0 +1,51 @@ +specVersion: v0.1.0 +package: + name: curve_finance_substream + version: v0.1.0 + +imports: + sql: https://github.com/streamingfast/substreams-sink-sql/releases/download/protodefs-v1.0.7/substreams-sink-sql-protodefs-v1.0.7.spkg + graph: https://github.com/streamingfast/substreams-sink-subgraph/releases/download/v0.1.0/substreams-sink-subgraph-protodefs-v0.1.0.spkg + database_change: https://github.com/streamingfast/substreams-sink-database-changes/releases/download/v1.2.1/substreams-database-change-v1.2.1.spkg + entity: https://github.com/streamingfast/substreams-entity-change/releases/download/v1.1.0/substreams-entity-change-v1.1.0.spkg + +protobuf: + files: + - common.proto + - erc20.proto + - contract.proto + importPaths: + - ./proto + - ../common/proto + +binaries: + default: + type: wasm/rust-v1 + file: "../target/wasm32-unknown-unknown/release/curve_finance_substream.wasm" + +modules: + - name: map_pool_created + kind: map + initialBlock: 13991825 + inputs: + - source: sf.ethereum.type.v2.Block + output: + type: proto:messari.contract.v1.Pools + + - name: store_pools + kind: store + updatePolicy: set_if_not_exists + valueType: string + inputs: + - map: map_pool_created + + - name: map_pool_fees + kind: map + initialBlock: 13991825 + inputs: + - source: sf.ethereum.type.v2.Block + - store: store_pools + output: + type: proto:messari.contract.v1.PoolFees + +network: polygon