diff --git a/lib/starknet_explorer/pedersen.ex b/lib/starknet_explorer/pedersen.ex new file mode 100644 index 00000000..e8e4b38c --- /dev/null +++ b/lib/starknet_explorer/pedersen.ex @@ -0,0 +1,14 @@ +defmodule StarknetExplorer.Pedersen do + use Rustler, otp_app: :starknet_explorer, crate: "pedersen" + # @spec decode(binary, atom) :: binary + # def decode(_b64, _opt \\ :standard), do: error() + + # @spec encode(binary, atom) :: binary + # def encode(_s, _opt \\ :standard), do: error() + + # defp _error(), do: :erlang.nif_error(:nif_not_loaded) + + # fn caclulate_contract_hash<'a>(salt: String, class_hash: String, constructor_calldata: Vec, deployer_address: String) -> NifResult { + def calculate_contract_address(salt, class_hash, constructor_calldata, deployer_address), + do: :erlang.nif_error(:nif_not_loaded) +end diff --git a/lib/starknet_explorer/transaction.ex b/lib/starknet_explorer/transaction.ex index 7d617e14..c11295ab 100644 --- a/lib/starknet_explorer/transaction.ex +++ b/lib/starknet_explorer/transaction.ex @@ -2,7 +2,7 @@ defmodule StarknetExplorer.Transaction do use Ecto.Schema import Ecto.Changeset import Ecto.Query - alias StarknetExplorer.{Transaction, Repo, TransactionReceipt} + alias StarknetExplorer.{Transaction, Repo, TransactionReceipt, Pedersen} @l1_handler_tx_fields [ :hash, diff --git a/lib/starknet_explorer_web/live/transaction_live.ex b/lib/starknet_explorer_web/live/transaction_live.ex index d6c0558d..3a70c8c2 100644 --- a/lib/starknet_explorer_web/live/transaction_live.ex +++ b/lib/starknet_explorer_web/live/transaction_live.ex @@ -709,6 +709,17 @@ defmodule StarknetExplorerWeb.TransactionLive do (Message.from_transaction_receipt(receipt) ++ [Message.from_transaction(transaction)]) |> Enum.reject(&is_nil/1) + # constructor_calldata: Vec, deployer_address: String) -> NifResult { + address = + StarknetExplorer.Pedersen.calculate_contract_address( + transaction.contract_address_salt, + transaction.class_hash, + transaction.constructor_calldata, + "0x0" + ) + + IO.inspect(address) + # change fee formatting actual_fee = Utils.hex_wei_to_eth(transaction.receipt.actual_fee) diff --git a/mix.exs b/mix.exs index 25fe987c..be524b53 100644 --- a/mix.exs +++ b/mix.exs @@ -60,6 +60,7 @@ defmodule StarknetExplorer.MixProject do {:ex_aws, "~> 2.0"}, {:ex_keccak, "~> 0.7.1"}, {:ex_aws_s3, "~> 2.0"}, + {:rustler, "~> 0.29.0"}, {:poison, "~> 3.1"}, {:hackney, "~> 1.6"}, {:sweet_xml, "~> 0.7.0"}, diff --git a/mix.lock b/mix.lock index 3bd37795..f0210e98 100644 --- a/mix.lock +++ b/mix.lock @@ -55,6 +55,7 @@ "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "redbug": {:hex, :redbug, "1.2.2", "366d8961770ddc7bb5d209fbadddfa7271005487f938c087a0e385a57abfee33", [:rebar3], [], "hexpm", "b5fe7b94e487be559cb0ec1c0e938c9761205d3e91a96bf263bdf1beaebea729"}, "rexbug": {:hex, :rexbug, "1.0.6", "024071c67d970151fbdc06f299faf8db3e1b2ac759a28623a9cc80a517fc74f2", [:mix], [{:mix_test_watch, ">= 0.5.0", [hex: :mix_test_watch, repo: "hexpm", optional: true]}, {:redbug, "~> 1.2", [hex: :redbug, repo: "hexpm", optional: false]}], "hexpm", "148ea724979413e9fd84ca3b4bb5d2d8b840ac481adfd645f5846fda409a642c"}, + "rustler": {:hex, :rustler, "0.29.1", "880f20ae3027bd7945def6cea767f5257bc926f33ff50c0d5d5a5315883c084d", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "109497d701861bfcd26eb8f5801fe327a8eef304f56a5b63ef61151ff44ac9b6"}, "rustler_precompiled": {:hex, :rustler_precompiled, "0.6.3", "f838d94bc35e1844973ee7266127b156fdc962e9e8b7ff666c8fb4fed7964d23", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "e18ecca3669a7454b3a2be75ae6c3ef01d550bc9a8cf5fbddcfff843b881d7c6"}, "scrivener": {:hex, :scrivener, "2.7.2", "1d913c965ec352650a7f864ad7fd8d80462f76a32f33d57d1e48bc5e9d40aba2", [:mix], [], "hexpm", "7866a0ec4d40274efbee1db8bead13a995ea4926ecd8203345af8f90d2b620d9"}, "scrivener_ecto": {:hex, :scrivener_ecto, "2.7.0", "cf64b8cb8a96cd131cdbcecf64e7fd395e21aaa1cb0236c42a7c2e34b0dca580", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:scrivener, "~> 2.4", [hex: :scrivener, repo: "hexpm", optional: false]}], "hexpm", "e809f171687806b0031129034352f5ae44849720c48dd839200adeaf0ac3e260"}, @@ -68,6 +69,7 @@ "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, "tesla": {:hex, :tesla, "1.7.0", "a62dda2f80d4f8a925eb7b8c5b78c461e0eb996672719fe1a63b26321a5f8b4e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "2e64f01ebfdb026209b47bc651a0e65203fcff4ae79c11efb73c4852b00dc313"}, + "toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm", "6c7729a2d214806450d29766abc2afaa7a2cbecf415be64f36a6691afebb50e5"}, "websock": {:hex, :websock, "0.5.2", "b3c08511d8d79ed2c2f589ff430bd1fe799bb389686dafce86d28801783d8351", [:mix], [], "hexpm", "925f5de22fca6813dfa980fb62fd542ec43a2d1a1f83d2caec907483fe66ff05"}, diff --git a/native/pedersen/.cargo/config.toml b/native/pedersen/.cargo/config.toml new file mode 100644 index 00000000..20f03f3d --- /dev/null +++ b/native/pedersen/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.'cfg(target_os = "macos")'] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] diff --git a/native/pedersen/.gitignore b/native/pedersen/.gitignore new file mode 100644 index 00000000..4fffb2f8 --- /dev/null +++ b/native/pedersen/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/native/pedersen/Cargo.toml b/native/pedersen/Cargo.toml new file mode 100644 index 00000000..c4322421 --- /dev/null +++ b/native/pedersen/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pedersen" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rustler = "0.29" +starknet_in_rust = { git = "https://github.com/lambdaclass/starknet_in_rust", version="0.4.0" } \ No newline at end of file diff --git a/native/pedersen/src/lib.rs b/native/pedersen/src/lib.rs new file mode 100644 index 00000000..aa481f4a --- /dev/null +++ b/native/pedersen/src/lib.rs @@ -0,0 +1,22 @@ +extern crate rustler; +use rustler::{NifResult, Error}; +use starknet_in_rust::{hash_utils::calculate_contract_address, felt::{Felt252, felt_str}, utils::Address}; + +rustler::init!("Elixir.Pedersen", + [caclulate_contract_hash] +); + +#[rustler::nif] +fn caclulate_contract_hash<'a>(salt: String, class_hash: String, constructor_calldata: Vec, deployer_address: String) -> NifResult { + let salt = felt_str!(salt.strip_prefix("0x").unwrap_or(&salt), 16); + let class_hash: Felt252 = felt_str!(class_hash.strip_prefix("0x").unwrap_or(&class_hash), 16); + let constructor_calldata: Vec = constructor_calldata.iter().map(|f| felt_str!(f.strip_prefix("0x").unwrap_or(&f), 16)).collect(); + let deployer_address = felt_str!(deployer_address.strip_prefix("0x").unwrap_or(&deployer_address), 16); + + let contract_address = calculate_contract_address(&salt, &class_hash, &constructor_calldata, Address(deployer_address)); + + match contract_address { + Ok(v) => NifResult::Ok(v.to_str_radix(16)), + Err(err) => NifResult::Err(Error::Term(Box::new(format!("Error calculating contract address: {}", err)))) + } +} diff --git a/priv/repo/migrations/20230926222639_create_internal_calls.exs b/priv/repo/migrations/20230926222639_create_internal_calls.exs new file mode 100644 index 00000000..36d26f96 --- /dev/null +++ b/priv/repo/migrations/20230926222639_create_internal_calls.exs @@ -0,0 +1,15 @@ +defmodule StarknetExplorer.Repo.Migrations.CreateInternalCalls do + use Ecto.Migration + + def change do + create table(:internal_calls) do + add :transaction_hash, :string + add :type, :string + add :function_selector, :string + add :contract_address, :string + add :calldata, {:array, :string} + + timestamps() + end + end +end diff --git a/rustler.exs b/rustler.exs new file mode 100644 index 00000000..767f5f77 --- /dev/null +++ b/rustler.exs @@ -0,0 +1,9 @@ +[ + rustlers: [ + [ + name: "pedersen", + path: "native/pedersen", + cargo_target: "release" + ] + ] +]