diff --git a/Cargo.lock b/Cargo.lock index 05986d6..f73ae7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,7 +227,7 @@ dependencies = [ "either", "serde", "serde_with", - "sha2", + "sha2 0.10.9", "thiserror", ] @@ -1521,7 +1521,7 @@ dependencies = [ "http 0.2.12", "http 1.3.1", "percent-encoding", - "sha2", + "sha2 0.10.9", "time", "tracing", ] @@ -1705,6 +1705,58 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" +dependencies = [ + "axum-core", + "bytes", + "form_urlencoded", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.7.0", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "az" version = "1.2.1" @@ -1824,6 +1876,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -2287,7 +2348,7 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", "crypto-common", "subtle", @@ -3190,19 +3251,21 @@ dependencies = [ [[package]] name = "init4-bin-base" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3a3aebe88976ad2f1a5ebff463b648825f658156cfed2bd31de301ec71602a" +checksum = "7519d5251ed1e80d8fc38c4b65459955cfea0e6c54241a902181f89883947256" dependencies = [ "alloy", "async-trait", "aws-config", "aws-sdk-kms", + "axum", "chrono", "init4-from-env-derive", "metrics", "metrics-exporter-prometheus", "opentelemetry", + "opentelemetry-http", "opentelemetry-otlp", "opentelemetry-semantic-conventions", "opentelemetry_sdk", @@ -3210,6 +3273,7 @@ dependencies = [ "serde", "signet-constants", "thiserror", + "tower", "tracing", "tracing-core", "tracing-opentelemetry", @@ -3330,7 +3394,7 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -3380,6 +3444,52 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libsecp256k1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79019718125edc905a079a70cfa5f3820bc76139fc91d6f9abc27ea2a887139" +dependencies = [ + "arrayref", + "base64 0.22.1", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -3442,6 +3552,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "memchr" version = "2.7.6" @@ -3693,6 +3809,12 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.74" @@ -3830,7 +3952,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -3918,9 +4040,9 @@ dependencies = [ [[package]] name = "phf" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", @@ -3929,19 +4051,19 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "fastrand", "phf_shared", + "rand 0.8.5", ] [[package]] name = "phf_macros" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", @@ -3952,9 +4074,9 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.13.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] @@ -4477,9 +4599,9 @@ dependencies = [ [[package]] name = "revm" -version = "30.2.0" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76df793c6ef3bef8f88f05b3873ebebce1494385a3ce8f58ad2e2e111aa0de11" +checksum = "718d90dce5f07e115d0e66450b1b8aa29694c1cf3f89ebddaddccc2ccbd2f13e" dependencies = [ "revm-bytecode", "revm-context", @@ -4496,9 +4618,9 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.0.2" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451748b17ac78bd2b0748ec472a5392cd78fc0f7d19d528be44770fda28fd6f7" +checksum = "66c52031b73cae95d84cd1b07725808b5fd1500da3e5e24574a3b2dc13d9f16d" dependencies = [ "bitvec", "phf", @@ -4508,9 +4630,9 @@ dependencies = [ [[package]] name = "revm-context" -version = "10.1.2" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7adcce0c14cf59b7128de34185a0fbf8f63309539b9263b35ead870d73584114" +checksum = "5a20c98e7008591a6f012550c2a00aa36cba8c14cc88eb88dec32eb9102554b4" dependencies = [ "bitvec", "cfg-if", @@ -4525,9 +4647,9 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "11.1.2" +version = "10.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d620a9725e443c171fb195a074331fa4a745fa5cbb0018b4bbf42619e64b563" +checksum = "b50d241ed1ce647b94caf174fcd0239b7651318b2c4c06b825b59b973dfb8495" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -4541,9 +4663,9 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.2" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdefd7f40835e992bab40a245124cb1243e6c7a1c4659798827c809a59b0fea9" +checksum = "39a276ed142b4718dcf64bc9624f474373ed82ef20611025045c3fb23edbef9c" dependencies = [ "alloy-eips", "revm-bytecode", @@ -4555,9 +4677,9 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "8.0.3" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa488a73ac2738f11478650cdf1a0f263864c09d5f0e9bf6309e891a05323c60" +checksum = "8c523c77e74eeedbac5d6f7c092e3851dbe9c7fec6f418b85992bd79229db361" dependencies = [ "auto_impl", "either", @@ -4568,9 +4690,9 @@ dependencies = [ [[package]] name = "revm-handler" -version = "11.2.0" +version = "10.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d8049b2fbff6636150f4740c95369aa174e41b0383034e0e256cfdffcfcd23" +checksum = "550331ea85c1d257686e672081576172fe3d5a10526248b663bbf54f1bef226a" dependencies = [ "auto_impl", "derive-where", @@ -4587,9 +4709,9 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "11.2.0" +version = "10.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a21dd773b654ec7e080025eecef4ac84c711150d1bd36acadf0546f471329a" +checksum = "7c0a6e9ccc2ae006f5bed8bd80cd6f8d3832cd55c5e861b9402fdd556098512f" dependencies = [ "auto_impl", "either", @@ -4605,9 +4727,9 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.31.2" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "782c38fa94f99b4b15f1690bffc2c3cbf06a0f460cf163b470d126914b47d343" +checksum = "de23199c4b6181a6539e4131cf7e31cde4df05e1192bcdce491c34a511241588" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -4623,22 +4745,21 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "28.0.0" +version = "25.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1de5c790122f8ded67992312af8acd41ccfcee629b25b819e10c5b1f69caf57" +checksum = "06575dc51b1d8f5091daa12a435733a90b4a132dca7ccee0666c7db3851bc30c" dependencies = [ "revm-bytecode", "revm-context-interface", "revm-primitives", - "revm-state", "serde", ] [[package]] name = "revm-precompile" -version = "28.1.1" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57aadd7a2087705f653b5aaacc8ad4f8e851f5d330661e3f4c43b5475bbceae" +checksum = "25b57d4bd9e6b5fe469da5452a8a137bc2d030a3cd47c46908efc615bbc699da" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -4651,19 +4772,20 @@ dependencies = [ "c-kzg", "cfg-if", "k256", + "libsecp256k1", "p256", "revm-primitives", "ripemd", "rug", "secp256k1 0.31.1", - "sha2", + "sha2 0.10.9", ] [[package]] name = "revm-primitives" -version = "21.0.1" +version = "20.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536f30e24c3c2bf0d3d7d20fa9cf99b93040ed0f021fd9301c78cddb0dacda13" +checksum = "5aa29d9da06fe03b249b6419b33968ecdf92ad6428e2f012dc57bcd619b5d94e" dependencies = [ "alloy-primitives", "num_enum", @@ -4673,9 +4795,9 @@ dependencies = [ [[package]] name = "revm-state" -version = "8.0.2" +version = "7.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e6bd5e669b02007872a8ca2643a14e308fe1739ee4475d74122587c3388a06a" +checksum = "1f64fbacb86008394aaebd3454f9643b7d5a782bd251135e17c5b33da592d84d" dependencies = [ "bitflags", "revm-bytecode", @@ -5148,6 +5270,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -5212,6 +5345,19 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.9" @@ -5279,15 +5425,14 @@ dependencies = [ [[package]] name = "signet-bundle" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247b8b7bdf32d08fd8ce345d3567f3f00ee597ef35e01564d793c41e321f205" +checksum = "250b22c00b6b664d4346438c2e56cb1035de8a6a6d0acbf6e9135702b422ef88" dependencies = [ "alloy", "serde", "signet-evm", "signet-types", - "signet-zenith", "thiserror", "tracing", "trevm", @@ -5295,9 +5440,9 @@ dependencies = [ [[package]] name = "signet-constants" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a044fc6cc42e8100a8c4080a812430dfc41d2e85c2579e903c35b08ce5e7956b" +checksum = "4339f67fe49673c91dbb1fc51835e5d52e8288d05476257a00237ea77373c6d9" dependencies = [ "alloy", "serde", @@ -5307,9 +5452,9 @@ dependencies = [ [[package]] name = "signet-evm" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b014f5edb134a0376099bccce51fae44d833762c7f713e486d6048b1ee52e25d" +checksum = "23851c76a2f8cbedb67ac8aae96c4a24d7a18df7cf618e532b1a273a0a64bd8a" dependencies = [ "alloy", "signet-extract", @@ -5323,9 +5468,9 @@ dependencies = [ [[package]] name = "signet-extract" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41782e8810ea9e081f3ea65d212c0a16d43e96350f372831c048fe2e73f24bfc" +checksum = "e2e427fcc1cc6f619f9f6b91d5ad3aa9f89a6dab7a9b97c4f4799519d87a0cc4" dependencies = [ "alloy", "signet-types", @@ -5335,9 +5480,9 @@ dependencies = [ [[package]] name = "signet-journal" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59471ed6d55f2cd755eb229a8f6dd059e5186b69b1e8ec31c8648a5364398fed" +checksum = "f925c23032f3cccda8a137514000f6d3a731dbb2f26df208b444a92059082bbb" dependencies = [ "alloy", "futures-util", @@ -5366,9 +5511,9 @@ dependencies = [ [[package]] name = "signet-tx-cache" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092d3c5c5a8f4c636c404a5a54d393078a0ad0d1ae486cb85c7a41971d8b8fce" +checksum = "d18561db9d474e6f58cd8e975dbb0183fb611298ba69a6066e7ed1bb43320a95" dependencies = [ "alloy", "eyre", @@ -5383,9 +5528,9 @@ dependencies = [ [[package]] name = "signet-types" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fe99cb3143d341b48e42862eb28aabbc2e848c28ec764ffcd223b2154585856" +checksum = "7420906cb7539f6d2131cc7ae4e6d14262fdbce581d950bb5310031ee83685d4" dependencies = [ "alloy", "chrono", @@ -5397,9 +5542,9 @@ dependencies = [ [[package]] name = "signet-zenith" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cbd7f4422eac2f9069d472b64f72e9fd54d2c071112b9fb05d71fa2b45cc8a" +checksum = "394c1539846b41d689cb32fa96765a73c3e3176c065b3426000bf4895aa9512f" dependencies = [ "alloy", "alloy-core", @@ -5870,6 +6015,7 @@ dependencies = [ "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -5908,6 +6054,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6005,9 +6152,9 @@ dependencies = [ [[package]] name = "trevm" -version = "0.30.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691435bfd64ff8bb46ff75a1a76cbd550cf93cf38d07560d98714c6b4c1dc19" +checksum = "46c55b9cf58baa3727871f0d694bb0b07d6fcae6eea095fde796f338f880dbda" dependencies = [ "alloy", "dashmap", diff --git a/Cargo.toml b/Cargo.toml index 1fd92b6..706c2f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,13 +25,13 @@ name = "submit_transaction" path = "bin/submit_transaction.rs" [dependencies] -init4-bin-base = { version = "0.15.0", features = ["alloy", "aws"] } +init4-bin-base = { version = "0.16.0", features = ["alloy", "aws"] } -signet-constants = { version = "0.12.0" } -signet-zenith = { version = "0.12.0" } -signet-types = { version = "0.12.0" } -signet-tx-cache = { version = "0.12.0" } -signet-bundle = { version = "0.12.0" } +signet-constants = { version = "0.13.0" } +signet-zenith = { version = "0.13.0" } +signet-types = { version = "0.13.0" } +signet-tx-cache = { version = "0.13.0" } +signet-bundle = { version = "0.13.0" } alloy = { version = "1.0.35", features = [ "full", diff --git a/README.md b/README.md index 4b88a95..17deca4 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,8 @@ You can freely modify the example Order to: ```bash export CHAIN_NAME=pecorino export RU_RPC_URL=https://rpc.pecorino.signet.sh/ +export HOST_RPC_URL=https://host-rpc.pecorino.signet.sh/ export SIGNER_KEY=[AWS KMS key ID or local private key] -export SIGNER_CHAIN_ID=14174 ``` 2. **Fund your key** @@ -82,6 +82,7 @@ This key acts as **both** the Order Initiator and Filler, and must be funded wit - Input tokens on the Rollup - Output tokens on the Host and/or Rollup - Gas tokens to pay for Rollup transactions +- Gas tokens to pay for Host transactions By default, the example swaps **1 Rollup WETH Input → 1 Host WETH Output**, but you can edit the Order freely. diff --git a/bin/roundtrip.rs b/bin/roundtrip.rs index 91032eb..3f0d977 100644 --- a/bin/roundtrip.rs +++ b/bin/roundtrip.rs @@ -36,8 +36,12 @@ async fn main() -> eyre::Result<()> { let args = OrdersArgs::parse(); // connect signer and provider - let signer = config.signer_config.connect().await?; - let provider = connect_provider(signer.clone(), config.ru_rpc_url.clone()).await?; + let mut signer = config.signer_config.connect().await?; + // ensure signer chain ID is unset so it can be used for Host and Rollup + signer.set_chain_id(None); + + let ru_provider = connect_provider(signer.clone(), config.ru_rpc_url.clone()).await?; + let host_provider = connect_provider(signer.clone(), config.host_rpc_url.clone()).await?; info!(signer_address = %signer.address(), "Connected to Signer and Provider"); // create an example order @@ -52,7 +56,7 @@ async fn main() -> eyre::Result<()> { sleep(Duration::from_secs(1)).await; // fill the order from the transaction cache - fill_orders(&signed, signer, provider, config).await?; + fill_orders(&signed, signer, ru_provider, host_provider, config).await?; info!("Bundle sent to tx cache successfully; wait for bundle to mine."); Ok(()) @@ -90,7 +94,7 @@ fn get_example_order( } /// Sign and send an order to the transaction cache. -#[instrument(skip(order, signer, config), level = "debug", fields(signer_address = %signer.address()))] +#[instrument(skip_all, level = "debug", fields(signer_address = %signer.address()))] async fn send_order( order: UnsignedOrder<'_>, signer: &LocalOrAws, @@ -113,15 +117,16 @@ async fn send_order( } /// Fill example [`SignedOrder`]s from the transaction cache. -#[instrument(skip(target_order, signer, provider, config), level = "debug")] +#[instrument(skip_all, level = "debug")] async fn fill_orders( target_order: &SignedOrder, signer: LocalOrAws, - provider: TxSenderProvider, + ru_provider: TxSenderProvider, + host_provider: TxSenderProvider, config: FillerConfig, ) -> eyre::Result<()> { info!("filling orders from transaction cache"); - let filler = Filler::new(signer, provider, config.constants)?; + let filler = Filler::new(signer, ru_provider, host_provider, config.constants)?; // get all the [`SignedOrder`]s from tx cache let mut orders: Vec = filler.get_orders().await?; diff --git a/bin/submit_order.rs b/bin/submit_order.rs index 9ce7831..971ce3b 100644 --- a/bin/submit_order.rs +++ b/bin/submit_order.rs @@ -42,8 +42,12 @@ async fn main() -> eyre::Result<()> { sleep_time, } = OrdersArgs::from_env()?; - let signer = config.signer_config.connect().await?; - let provider = connect_provider(signer.clone(), config.ru_rpc_url.clone()).await?; + let mut signer = config.signer_config.connect().await?; + // ensure signer chain ID is unset so it can be used for Host and Rollup + signer.set_chain_id(None); + + let ru_provider = connect_provider(signer.clone(), config.ru_rpc_url.clone()).await?; + let host_provider = connect_provider(signer.clone(), config.host_rpc_url.clone()).await?; info!(signer_address = %signer.address(), "Connected to Signer and Provider"); loop { @@ -54,7 +58,14 @@ async fn main() -> eyre::Result<()> { sleep(TX_CACHE_WAIT_TIME).await; - fill_orders(&signed, signer.clone(), provider.clone(), &config).await?; + fill_orders( + &signed, + signer.clone(), + ru_provider.clone(), + host_provider.clone(), + &config, + ) + .await?; sleep(Duration::from_millis(sleep_time)).await; } @@ -92,7 +103,7 @@ fn get_example_order( } /// Sign and send an order to the transaction cache. -#[instrument(skip(order, signer, config), fields(signer_address = %signer.address()))] +#[instrument(skip_all, fields(signer_address = %signer.address()))] async fn send_order( order: UnsignedOrder<'_>, signer: &LocalOrAws, @@ -119,15 +130,16 @@ async fn send_order( } /// Fill example [`SignedOrder`]s from the transaction cache. -#[instrument(skip(target_order, signer, provider, config), fields(target_order_signature = %target_order.permit.signature, target_order_owner = %target_order.permit.owner))] +#[instrument(skip_all, fields(target_order_signature = %target_order.permit.signature, target_order_owner = %target_order.permit.owner))] async fn fill_orders( target_order: &SignedOrder, signer: LocalOrAws, - provider: TxSenderProvider, + ru_provider: TxSenderProvider, + host_provider: TxSenderProvider, config: &FillerConfig, ) -> eyre::Result<()> { info!("filling orders from transaction cache"); - let filler = Filler::new(signer, provider, config.constants.clone())?; + let filler = Filler::new(signer, ru_provider, host_provider, config.constants.clone())?; // get all the [`SignedOrder`]s from tx cache let mut orders: Vec = filler.get_orders().await?; diff --git a/src/filler.rs b/src/filler.rs index b33d820..40c4793 100644 --- a/src/filler.rs +++ b/src/filler.rs @@ -15,7 +15,7 @@ use init4_bin_base::{ }; use signet_bundle::SignetEthBundle; use signet_constants::SignetConstants; -use signet_tx_cache::{client::TxCache, types::TxCacheSendBundleResponse}; +use signet_tx_cache::client::TxCache; use signet_types::{AggregateOrders, SignedFill, SignedOrder, UnsignedFill}; use std::{collections::HashMap, slice::from_ref}; @@ -30,9 +30,12 @@ pub struct FillerConfig { /// The Rollup RPC URL. #[from_env(var = "RU_RPC_URL", desc = "RPC URL for the Rollup")] pub ru_rpc_url: String, - /// The signer to use for signing transactions. - /// NOTE: For the example, this key must be funded with USDC on both the Host and Rollup, as well as gas on the Rollup. - /// .env vars: SIGNER_KEY, SIGNER_CHAIN_ID + /// The Host RPC URL. + #[from_env(var = "HOST_RPC_URL", desc = "RPC URL for the Host")] + pub host_rpc_url: String, + /// The signer to use for signing transactions on the Host and Rollup. + /// NOTE: For the example, this key must be funded with gas on both the Host and Rollup, as well as Input/Output tokens for the Orders on the Host/Rollup. + /// .env var: SIGNER_KEY pub signer_config: LocalOrAwsConfig, /// The Signet constants. /// .env var: CHAIN_NAME @@ -47,6 +50,8 @@ pub struct Filler { signer: S, /// The provider to use for building transactions on the Rollup. ru_provider: TxSenderProvider, + /// The provider to use for building transactions on the Host. + host_provider: TxSenderProvider, /// The transaction cache endpoint. tx_cache: TxCache, /// The system constants. @@ -61,6 +66,7 @@ where pub fn new( signer: S, ru_provider: TxSenderProvider, + host_provider: TxSenderProvider, constants: SignetConstants, ) -> Result { let tx_cache_url: reqwest::Url = constants.environment().transaction_cache().parse()?; @@ -74,6 +80,7 @@ where Ok(Self { signer, ru_provider, + host_provider, tx_cache: TxCache::new_with_client(tx_cache_url, client), constants, }) @@ -95,14 +102,13 @@ where /// without simulating to check whether it has already been filled, because they can rely on Builder simulation. /// Order `initiate` transactions will revert if the Order has already been filled, /// in which case the entire Bundle would simply be discarded by the Builder. - #[instrument(skip(self, orders))] + #[instrument(skip_all)] pub async fn fill_individually(&self, orders: &[SignedOrder]) -> Result<(), Error> { debug!(orders_count = orders.len(), "Filling orders individually"); // submit one bundle per individual order for order in orders { - let response = self.fill(from_ref(order)).await?; - debug!(bundle_id = response.id.to_string(), "Bundle sent to cache"); + self.fill(from_ref(order)).await?; } Ok(()) @@ -121,8 +127,8 @@ where /// If a single Order is passed to this fn, /// Filling Orders individually ensures that even if some Orders are not fillable, others may still mine; /// however, it is less gas efficient. - #[instrument(skip(self, orders))] - pub async fn fill(&self, orders: &[SignedOrder]) -> Result { + #[instrument(skip_all)] + pub async fn fill(&self, orders: &[SignedOrder]) -> Result<(), Error> { info!(orders_count = orders.len(), "Filling orders in bundle"); // if orders is empty, error out @@ -131,44 +137,68 @@ where } // sign a SignedFill for the orders - let mut signed_fills: HashMap = self.sign_fills(orders).await?; + let signed_fills: HashMap = self.sign_fills(orders).await?; debug!(?signed_fills, "Signed fills for orders"); info!("Successfully signed fills"); // get the transaction requests for the rollup let tx_requests = self.rollup_txn_requests(&signed_fills, orders).await?; - debug!(?tx_requests, "Transaction requests"); + debug!(?tx_requests, "Rollup transaction requests"); + + // sign & encode the rollup transactions for the Bundle + let txs: Vec = self + .sign_and_encode_txns(&self.ru_provider, tx_requests) + .await?; + debug!(?txs, "Rollup encoded transactions"); - // sign & encode the transactions for the Bundle - let txs = self.sign_and_encode_txns(tx_requests).await?; - debug!(?txs, "Encoded transactions"); + // get the transaction requests for the host + let host_tx_requests = self.host_txn_requests(&signed_fills).await?; + debug!(?host_tx_requests, "Host transaction requests"); - // get the aggregated host fill for the Bundle, if any - let host_fills = signed_fills.remove(&self.constants.host().chain_id()); - debug!(?host_fills, "Host fills for bundle"); + // sign & encode the host transactions for the Bundle + let host_txs = self + .sign_and_encode_txns(&self.host_provider, host_tx_requests) + .await?; + debug!(?host_txs, "Host encoded transactions"); // set the Bundle to only be valid if mined in the next rollup block - let block_number = self.ru_provider.get_block_number().await? + 1; + let latest_ru_block_number = self.ru_provider.get_block_number().await?; + + // send the Bundle to the transaction cache + self.send_bundle(txs.clone(), host_txs.clone(), latest_ru_block_number + 1) + .await?; + + Ok(()) + } + async fn send_bundle( + &self, + ru_txs: Vec, + host_txs: Vec, + target_ru_block_number: u64, + ) -> Result<(), Error> { // construct a Bundle containing the Rollup transactions and the Host fill (if any) let bundle = SignetEthBundle { - host_fills, + host_txs, bundle: EthSendBundle { - txs, - reverting_tx_hashes: vec![], // generally, if the Order initiations revert, then fills should not be submitted - block_number, - min_timestamp: None, // sufficiently covered by pinning to next block number - max_timestamp: None, // sufficiently covered by pinning to next block number - replacement_uuid: None, // optional if implementing strategies that replace or cancel bundles + txs: ru_txs, + block_number: target_ru_block_number, ..Default::default() }, - host_txs: vec![], }; debug!(?bundle, "bundle contents"); - info!("forwarding bundle to transaction cache"); + info!( + ru_tx_count = bundle.bundle.txs.len(), + host_tx_count = bundle.host_txs.len(), + target_ru_block_number, + "forwarding bundle to transaction cache" + ); // submit the Bundle to the transaction cache - self.tx_cache.forward_bundle(bundle).await + let response = self.tx_cache.forward_bundle(bundle).await?; + debug!(bundle_id = response.id.to_string(), "Bundle sent to cache"); + + Ok(()) } /// Aggregate the given orders into a SignedFill, sign it, and @@ -182,7 +212,7 @@ where /// If filling multiple Orders, they may wish to utilize one Order's Outputs to provide another Order's rollup Inputs. /// In this case, the Filler would wish to split up the Fills for each Order, /// rather than signing a single, aggregate a Fill for each chain, as is done here. - #[instrument(skip(self, orders))] + #[instrument(skip_all, fields(orders_count = orders.len()))] async fn sign_fills(&self, orders: &[SignedOrder]) -> Result, Error> { if orders.is_empty() { eyre::bail!("no orders to fill"); @@ -202,19 +232,9 @@ where let mut unsigned_fill = UnsignedFill::from(&agg); unsigned_fill = unsigned_fill .with_deadline(deadline) - .with_ru_chain_id(self.constants.rollup().chain_id()); + .with_ru_chain_id(self.constants.rollup().chain_id()) + .with_chain(self.constants.system().clone()); debug!(?unsigned_fill, "Unsigned fill created"); - // populate the Order contract addresses for each chain - for chain_id in agg.target_chain_ids() { - unsigned_fill = unsigned_fill.with_chain( - chain_id, - self.constants - .system() - .orders_for(chain_id) - .ok_or(eyre!("invalid target chain id {}", chain_id))?, - ); - } - debug!(?unsigned_fill, "Unsigned fill with chain addresses"); // sign the UnsignedFill, producing a SignedFill for each target chain Ok(unsigned_fill.sign(&self.signer).await?) } @@ -229,7 +249,7 @@ where /// /// For example, Fillers might utilize one Order's Inputs to fill subsequent Orders' Outputs. /// In this case, the rollup transactions should look like [`fill_1`, `inititate_1`, `fill_2`, `initiate_2`]. - #[instrument(skip(self, signed_fills, orders))] + #[instrument(skip_all)] async fn rollup_txn_requests( &self, signed_fills: &HashMap, @@ -243,6 +263,7 @@ where // Host `fill` transactions are always considered to be mined "before" the rollup block is processed, // but Rollup `fill` transactions MUST take care to be ordered before the Orders are `initiate`d if let Some(rollup_fill) = signed_fills.get(&self.constants.rollup().chain_id()) { + debug!(?rollup_fill, "Rollup fill"); // add the fill tx to the rollup txns let ru_fill_tx = rollup_fill.to_fill_tx(self.constants.rollup().orders()); tx_requests.push(ru_fill_tx); @@ -259,11 +280,37 @@ where Ok(tx_requests) } + /// Construct a set of transaction requests to be submitted on the host. + /// + /// This example only includes one Host transaction, + /// which performs a single, aggregate Fill on the Host chain. + /// + /// This is the simplest, minimally viable way to get a set of Orders mined; + /// Fillers may wish to implement more complex strategies. + /// + /// For example, Fillers might wish to include swaps on Host AMMs to source liquidity as part of their filling strategy. + #[instrument(skip_all)] + async fn host_txn_requests( + &self, + signed_fills: &HashMap, + ) -> Result, Error> { + // If there is a SignedFill for the Host, add a transaction to submit the fill + if let Some(host_fill) = signed_fills.get(&self.constants.host().chain_id()) { + debug!(?host_fill, "Host fill"); + // add the fill tx to the host txns + let host_fill_tx = host_fill.to_fill_tx(self.constants.host().orders()); + Ok(vec![host_fill_tx]) + } else { + Ok(vec![]) + } + } + /// Given an ordered set of Transaction Requests, /// Sign them and encode them for inclusion in a Bundle. - #[instrument(skip(self, tx_requests))] + #[instrument(skip_all)] pub async fn sign_and_encode_txns( &self, + provider: &TxSenderProvider, tx_requests: Vec, ) -> Result, Error> { let mut encoded_txs: Vec = Vec::new(); @@ -277,7 +324,7 @@ where ); // sign the transaction - let SendableTx::Envelope(filled) = self.ru_provider.fill(tx).await? else { + let SendableTx::Envelope(filled) = provider.fill(tx).await? else { eyre::bail!("Failed to fill transaction") }; @@ -285,7 +332,8 @@ where let encoded = filled.encoded_2718(); info!( tx_hash = filled.hash().to_string(), - "Rollup transaction signed and encoded" + chain_id = provider.get_chain_id().await?, + "Transaction signed and encoded" ); // add to array diff --git a/src/order.rs b/src/order.rs index 5f31d9a..2ff5344 100644 --- a/src/order.rs +++ b/src/order.rs @@ -39,16 +39,15 @@ where } /// Sign an Order and forward it to the transaction cache to be Filled. + #[instrument(skip_all)] pub async fn sign_and_send_order(&self, order: Order) -> Result<()> { let signed = self.sign_order(order).await?; self.send_order(signed).await } /// Sign an Order. - #[instrument(skip(self, order))] + #[instrument(skip_all, level = "debug")] pub async fn sign_order(&self, order: Order) -> Result { - debug!(?order, "Signing order"); - // make an UnsignedOrder from the Order let unsigned = UnsignedOrder::from(&order); @@ -58,13 +57,16 @@ where .sign(&self.signer) .await .map_err(Into::into) + .inspect(|signed_order| { + debug!(order_hash = %signed_order.order_hash(), "Order signed"); + }) } /// Forward a SignedOrder to the transaction cache. - #[instrument(skip(self, signed))] + #[instrument(skip_all, fields(order_hash = %signed.order_hash()))] pub async fn send_order(&self, signed: SignedOrder) -> Result<()> { // send the SignedOrder to the transaction cache - debug!(order = ?signed, "Forwarding signed order to transaction cache"); + debug!("Forwarding signed order to transaction cache"); self.tx_cache.forward_order(signed).await } }