diff --git a/Cargo.lock b/Cargo.lock index f270f07..3423c70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,88 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "alloy-chains" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b515e82c8468ddb6ff8db21c78a5997442f113fd8471fd5b2261b2602dd0c67" +dependencies = [ + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c309895995eaa4bfcc345f5515a39c7df9447798645cc8bf462b6c5bf1dc96" +dependencies = [ + "alloy-eips", + "alloy-primitives 0.7.7", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4e0ef72b0876ae3068b2ed7dfae9ae1779ce13cfaec2ee1f08f5bd0348dc57" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives 0.7.7", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "thiserror", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413902aa18a97569e60f679c23f46a18db1656d87ab4d4e49d0e1e52042f66df" +dependencies = [ + "alloy-json-abi", + "alloy-primitives 0.7.7", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.6.16", +] + +[[package]] +name = "alloy-eips" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9431c99a3b3fe606ede4b3d4043bdfbcb780c45b8d8d226c3804e2b75cfbe68" +dependencies = [ + "alloy-primitives 0.7.7", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "once_cell", + "serde", + "sha2", +] + [[package]] name = "alloy-ethers-typecast" version = "0.2.0" @@ -92,6 +174,52 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alloy-json-rpc" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e2865c4c3bb4cdad3f0d9ec1ab5c0c657ba69a375651bd35e32fb6c180ccc2" +dependencies = [ + "alloy-primitives 0.7.7", + "alloy-sol-types", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e701fc87ef9a3139154b0b4ccb935b565d27ffd9de020fe541bf2dec5ae4ede" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives 0.7.7", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "futures-utils-wasm", + "thiserror", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec9d5a0f9170b10988b6774498a022845e13eda94318440d17709d50687f67f9" +dependencies = [ + "alloy-primitives 0.7.7", + "alloy-serde", + "serde", +] + [[package]] name = "alloy-primitives" version = "0.5.4" @@ -136,16 +264,144 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "alloy-provider" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9c0ab10b93de601a6396fc7ff2ea10d3b28c46f079338fa562107ebf9857c8" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives 0.7.7", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "futures-utils-wasm", + "lru", + "pin-project", + "reqwest 0.12.5", + "serde", + "serde_json", + "tokio", + "tracing", + "url", +] + [[package]] name = "alloy-rlp" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] +[[package]] +name = "alloy-rlp-derive" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d0f2d905ebd295e7effec65e5f6868d153936130ae718352771de3e7d03c75c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b38e3ffdb285df5d9f60cb988d336d9b8e3505acb78750c3bc60336a7af41d3" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest 0.12.5", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e18424d962d7700a882fe423714bd5b9dde74c7a7589d4255ea64068773aef" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives 0.7.7", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.13.0", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33feda6a53e6079895aed1d08dcb98a1377b000d80d16370fbbdb8155d547ef" +dependencies = [ + "alloy-primitives 0.7.7", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740a25b92e849ed7b0fa013951fe2f64be9af1ad5abe805037b44fb7770c5c47" +dependencies = [ + "alloy-primitives 0.7.7", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + +[[package]] +name = "alloy-signer-local" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b0707d4f63e4356a110b30ef3add8732ab6d181dd7be4607bf79b8777105cee" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives 0.7.7", + "alloy-signer", + "async-trait", + "elliptic-curve", + "eth-keystore", + "k256", + "rand", + "thiserror", +] + [[package]] name = "alloy-sol-macro" version = "0.7.7" @@ -215,6 +471,40 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-transport" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0590afbdacf2f8cca49d025a2466f3b6584a016a8b28f532f29f8da1007bae" +dependencies = [ + "alloy-json-rpc", + "base64 0.22.1", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-transport-http" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2437d145d80ea1aecde8574d2058cceb8b3c9cba05f6aea8e67907c660d46698" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest 0.12.5", + "serde_json", + "tower", + "tracing", + "url", +] + [[package]] name = "anstream" version = "0.6.15" @@ -403,6 +693,28 @@ dependencies = [ "term", ] +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "async-trait" version = "0.1.81" @@ -475,6 +787,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -535,6 +853,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blst" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "brotli-sys" version = "0.3.2" @@ -647,6 +977,20 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "c-kzg" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "serde", +] + [[package]] name = "camino" version = "1.1.7" @@ -689,11 +1033,16 @@ dependencies = [ name = "cargo-stylus-check" version = "0.4.2" dependencies = [ + "alloy-contract", "alloy-ethers-typecast", "alloy-json-abi", "alloy-primitives 0.7.7", + "alloy-provider", + "alloy-signer", + "alloy-signer-local", "alloy-sol-macro", "alloy-sol-types", + "alloy-transport", "brotli2", "bytes", "bytesize", @@ -1566,7 +1915,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "reqwest", + "reqwest 0.11.27", "serde", "serde_json", "syn 2.0.72", @@ -1628,7 +1977,7 @@ checksum = "e79e5973c26d4baf0ce55520bd732314328cabe53193286671b47144145b9649" dependencies = [ "chrono", "ethers-core", - "reqwest", + "reqwest 0.11.27", "semver 1.0.23", "serde", "serde_json", @@ -1653,7 +2002,7 @@ dependencies = [ "futures-locks", "futures-util", "instant", - "reqwest", + "reqwest 0.11.27", "serde", "serde_json", "thiserror", @@ -1680,12 +2029,12 @@ dependencies = [ "futures-timer", "futures-util", "hashers", - "http", + "http 0.2.12", "instant", "jsonwebtoken", "once_cell", "pin-project", - "reqwest", + "reqwest 0.11.27", "serde", "serde_json", "thiserror", @@ -1828,6 +2177,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1977,6 +2341,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -2065,7 +2435,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap 2.2.6", "slab", "tokio", @@ -2089,6 +2459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", + "allocator-api2", "serde", ] @@ -2157,6 +2528,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -2164,7 +2546,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -2191,8 +2596,8 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -2204,6 +2609,25 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -2211,13 +2635,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.12", + "hyper 0.14.30", "rustls", "tokio", "tokio-rustls", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.4.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -2347,6 +2807,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -2514,6 +2983,15 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lru" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "mach" version = "0.3.2" @@ -2599,6 +3077,23 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -2711,6 +3206,50 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "openssl" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -3254,9 +3793,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", "hyper-rustls", "ipnet", "js-sys", @@ -3266,11 +3805,11 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-rustls", @@ -3280,7 +3819,46 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "webpki-roots", - "winreg", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.1.3", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.52.0", ] [[package]] @@ -3487,6 +4065,22 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -3563,6 +4157,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -3611,6 +4214,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.11.0" @@ -3936,7 +4562,7 @@ dependencies = [ "fs2", "hex", "once_cell", - "reqwest", + "reqwest 0.11.27", "semver 1.0.23", "serde", "serde_json", @@ -3986,6 +4612,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "sys-info" version = "0.9.1" @@ -4072,6 +4704,15 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.3.36" @@ -4154,6 +4795,16 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.24.1" @@ -4164,6 +4815,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + [[package]] name = "tokio-tungstenite" version = "0.20.1" @@ -4237,6 +4900,28 @@ dependencies = [ "winnow 0.6.16", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.2" @@ -4249,6 +4934,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4299,7 +4985,7 @@ dependencies = [ "byteorder 1.5.0", "bytes", "data-encoding", - "http", + "http 0.2.12", "httparse", "log", "rand", @@ -4436,6 +5122,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" @@ -5021,6 +5713,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "ws_stream_wasm" version = "0.7.4" diff --git a/check/Cargo.toml b/check/Cargo.toml index d94052f..509232a 100644 --- a/check/Cargo.toml +++ b/check/Cargo.toml @@ -38,3 +38,8 @@ wasm-encoder = "0.213.0" wasm-gen = "0.1.4" toml = "0.8.14" sys-info = "0.9.1" +alloy-contract = "0.2.1" +alloy-provider = "0.2.1" +alloy-signer-local = { version = "0.2.1", features = ["keystore"] } +alloy-signer = "0.2.1" +alloy-transport = "0.2.1" diff --git a/check/src/cache.rs b/check/src/cache.rs index f850e50..c4b1972 100644 --- a/check/src/cache.rs +++ b/check/src/cache.rs @@ -1,30 +1,34 @@ // Copyright 2023-2024, Offchain Labs, Inc. // For licensing, see https://github.com/OffchainLabs/cargo-stylus/blob/stylus/licenses/COPYRIGHT.md -use alloy_primitives::Address; +use alloy_contract::Error; +use alloy_primitives::{keccak256, Address, U256}; +use alloy_provider::{Provider, ProviderBuilder}; use alloy_sol_macro::sol; -use alloy_sol_types::{SolCall, SolInterface}; +use bytesize::ByteSize; use cargo_stylus_util::color::{Color, DebugColor}; -use cargo_stylus_util::sys; -use ethers::middleware::{Middleware, SignerMiddleware}; -use ethers::signers::Signer; -use ethers::types::spoof::State; -use ethers::types::transaction::eip2718::TypedTransaction; -use ethers::types::{Eip1559TransactionRequest, H160, U256}; -use eyre::{bail, Context, Result}; +use eyre::{bail, Result}; +use CacheManager::CacheManagerErrors; -use crate::check::{eth_call, EthCallError}; -use crate::constants::ARB_WASM_CACHE_H160; -use crate::deploy::{format_gas, run_tx}; +use crate::constants::ARB_WASM_CACHE_ADDRESS; +use crate::deploy::gwei_to_wei; use crate::macros::greyln; -use crate::CacheConfig; +use crate::{CacheBidConfig, CacheStatusConfig, CacheSuggestionsConfig}; sol! { + #[sol(rpc)] interface ArbWasmCache { function allCacheManagers() external view returns (address[] memory managers); + function codehashIsCached(bytes32 codehash) external view returns (bool); } + #[sol(rpc)] interface CacheManager { + function cacheSize() external view returns (uint64); + function queueSize() external view returns (uint64); + function isPaused() external view returns (bool); function placeBid(address program) external payable; + function getMinBid(address program) external view returns (uint192 min); + function getMinBid(uint64 size) public view returns (uint192 min); error AsmTooLarge(uint256 asm, uint256 queueSize, uint256 cacheSize); error AlreadyCached(bytes32 codehash); @@ -34,89 +38,221 @@ sol! { } } -pub async fn cache_contract(cfg: &CacheConfig) -> Result<()> { - let provider = sys::new_provider(&cfg.common_cfg.endpoint)?; - let chain_id = provider - .get_chainid() +/// Recommends a minimum bid to the user for caching a Stylus program by address. If the program +/// has not yet been activated, the user will be informed. +pub async fn suggest_bid(cfg: &CacheSuggestionsConfig) -> Result<()> { + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .on_builtin(&cfg.endpoint) + .await?; + let cache_manager_addr = get_cache_manager_address(provider.clone()).await?; + let cache_manager = CacheManager::new(cache_manager_addr, provider.clone()); + match cache_manager + .getMinBid_0(cfg.address.to_fixed_bytes().into()) + .call() .await - .wrap_err("failed to get chain id")?; - - let wallet = cfg.auth.wallet().wrap_err("failed to load wallet")?; - let wallet = wallet.with_chain_id(chain_id.as_u64()); - let client = SignerMiddleware::new(provider.clone(), wallet); - - let data = ArbWasmCache::allCacheManagersCall {}.abi_encode(); - let tx = Eip1559TransactionRequest::new() - .to(*ARB_WASM_CACHE_H160) - .data(data); - let tx = TypedTransaction::Eip1559(tx); - let result = client.call(&tx, None).await?; - let cache_managers_result = - ArbWasmCache::allCacheManagersCall::abi_decode_returns(&result, true)?; - let cache_manager_addrs = cache_managers_result.managers; - if cache_manager_addrs.is_empty() { - bail!("no cache managers found in ArbWasmCache, perhaps the Stylus cache is not yet enabled on this chain"); + { + Ok(CacheManager::getMinBid_0Return { min: min_bid }) => { + greyln!( + "Minimum bid for contract {}: {} wei", + cfg.address, + min_bid.debug_mint() + ); + Ok(()) + } + Err(e) => { + let Error::TransportError(tperr) = e else { + bail!("failed to send cache bid tx: {:?}", e) + }; + let Some(err_resp) = tperr.as_error_resp() else { + bail!("no error payload received in response: {:?}", tperr) + }; + let Some(errs) = err_resp.as_decoded_error::(true) else { + bail!("failed to decode CacheManager error: {:?}", err_resp) + }; + handle_cache_manager_error(errs) + } } - let cache_manager = *cache_manager_addrs.last().unwrap(); - let cache_manager = H160::from_slice(cache_manager.as_slice()); +} - let contract: Address = cfg.address.to_fixed_bytes().into(); - let data = CacheManager::placeBidCall { program: contract }.abi_encode(); - let mut tx = Eip1559TransactionRequest::new() - .to(cache_manager) - .data(data); +/// Checks the status of the Stylus cache manager, including the cache size, queue size, and minimum bid +/// for different contract sizes as reference points. It also checks if a specified Stylus contract address +/// is currently cached. +pub async fn check_status(cfg: &CacheStatusConfig) -> Result<()> { + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .on_builtin(&cfg.endpoint) + .await?; + let arb_wasm_cache = ArbWasmCache::new(ARB_WASM_CACHE_ADDRESS, provider.clone()); + let cache_manager_addr = get_cache_manager_address(provider.clone()).await?; + let cache_manager = CacheManager::new(cache_manager_addr, provider.clone()); + let CacheManager::isPausedReturn { _0: is_paused } = cache_manager.isPaused().call().await?; + let CacheManager::queueSizeReturn { _0: queue_size } = cache_manager.queueSize().call().await?; + let CacheManager::cacheSizeReturn { _0: cache_size } = cache_manager.cacheSize().call().await?; + let CacheManager::getMinBid_1Return { min: min_bid_smol } = cache_manager + .getMinBid_1(ByteSize::kb(8).as_u64()) + .call() + .await?; + let CacheManager::getMinBid_1Return { min: min_bid_med } = cache_manager + .getMinBid_1(ByteSize::kb(16).as_u64()) + .call() + .await?; + let CacheManager::getMinBid_1Return { min: min_bid_big } = cache_manager + .getMinBid_1(ByteSize::kb(24).as_u64()) + .call() + .await?; - // If a bid is set, specify it. Otherwise, a zero bid will be sent. - if let Some(bid) = cfg.bid { - tx = tx.value(U256::from(bid)); - greyln!("Setting bid value of {} wei", bid.debug_mint()); + greyln!( + "Cache manager address: {}", + cache_manager_addr.debug_lavender() + ); + greyln!( + "Cache manager status: {}", + if is_paused { + "paused".debug_red() + } else { + "active".debug_mint() + } + ); + let cache_size = ByteSize::b(cache_size); + let queue_size = ByteSize::b(queue_size); + greyln!("Cache size: {}", cache_size.debug_grey()); + greyln!("Queue size: {}", queue_size.debug_grey()); + greyln!( + "Minimum bid for {} {} {}", + "8kb".debug_mint(), + "contract:".grey(), + min_bid_smol.debug_lavender() + ); + greyln!( + "Minimum bid for {} {} {}", + "16kb".debug_yellow(), + "contract:".grey(), + min_bid_med.debug_lavender() + ); + greyln!( + "Minimum bid for {} {} {}", + "24kb".debug_red(), + "contract:".grey(), + min_bid_big.debug_lavender() + ); + if queue_size < cache_size { + greyln!("Cache is not yet at capacity, so bids of size 0 are accepted"); + } else { + greyln!("Cache is at capacity, bids must be >= 0 to be accepted"); } - - if let Err(EthCallError { data, msg }) = - eth_call(tx.clone(), State::default(), &provider).await? - { - let error = match CacheManager::CacheManagerErrors::abi_decode(&data, true) { - Ok(err) => err, - Err(err_details) => bail!("unknown CacheManager error: {msg} and {:?}", err_details), - }; - use CacheManager::CacheManagerErrors as C; - match error { - C::AsmTooLarge(_) => bail!("Stylus contract was too large to cache"), - C::AlreadyCached(_) => bail!("Stylus contract is already cached"), - C::BidsArePaused(_) => { - bail!("Bidding is currently paused for the Stylus cache manager") - } - C::BidTooSmall(_) => { - bail!("Bid amount {} (wei) too small", cfg.bid.unwrap_or_default()) - } - C::ProgramNotActivated(_) => { - bail!("Your Stylus contract {} is not yet activated. To activate it, use the `cargo stylus activate` subcommand", hex::encode(contract)) + if let Some(address) = cfg.address { + let code = provider + .get_code_at(address.to_fixed_bytes().into()) + .await?; + let codehash = keccak256(code); + let ArbWasmCache::codehashIsCachedReturn { _0: is_cached } = + arb_wasm_cache.codehashIsCached(codehash).call().await?; + greyln!( + "Contract at address {} {}", + address.debug_lavender(), + if is_cached { + "is cached".debug_mint() + } else { + "is not yet cached".debug_red() + " please use cargo stylus cache bid to cache it" } - } + ); } - let verbose = cfg.common_cfg.verbose; - let receipt = run_tx( - "cache", - tx, - None, - cfg.common_cfg.max_fee_per_gas_gwei, - &client, - verbose, - ) - .await?; + Ok(()) +} - let address = cfg.address.debug_lavender(); +/// Attempts to cache a Stylus contract by address by placing a bid by sending a tx to the network. +/// It will handle the different cache manager errors that can be encountered along the way and +/// print friendlier errors if failed. +pub async fn place_bid(cfg: &CacheBidConfig) -> Result<()> { + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .on_builtin(&cfg.endpoint) + .await?; + let chain_id = provider.get_chain_id().await?; + let wallet = cfg.auth.alloy_wallet(chain_id)?; + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .wallet(wallet) + .on_builtin(&cfg.endpoint) + .await?; + let cache_manager_addr = get_cache_manager_address(provider.clone()).await?; + let cache_manager = CacheManager::new(cache_manager_addr, provider.clone()); + let addr = cfg.address.to_fixed_bytes().into(); + let mut place_bid_call = cache_manager.placeBid(addr).value(U256::from(cfg.bid)); + if let Some(max_fee) = cfg.max_fee_per_gas_gwei { + place_bid_call = place_bid_call.max_fee_per_gas(gwei_to_wei(max_fee)?); + }; - if verbose { - let gas = format_gas(receipt.gas_used.unwrap_or_default()); + greyln!("Checking if contract can be cached..."); + + let raw_output = place_bid_call.clone().call().await; + if let Err(e) = raw_output { + let Error::TransportError(tperr) = e else { + bail!("failed to send cache bid tx: {:?}", e) + }; + let Some(err_resp) = tperr.as_error_resp() else { + bail!("no error payload received in response: {:?}", tperr) + }; + let Some(errs) = err_resp.as_decoded_error::(true) else { + bail!("failed to decode CacheManager error: {:?}", err_resp) + }; + handle_cache_manager_error(errs)?; + } + greyln!("Sending cache bid tx..."); + let pending_tx = place_bid_call.send().await?; + let receipt = pending_tx.get_receipt().await?; + if cfg.verbose { + let gas = format_gas(receipt.gas_used); greyln!( - "Successfully cached contract at address: {address} {} {gas}", + "Successfully cached contract at address: {addr} {} {gas} gas used", "with".grey() ); } else { - greyln!("Successfully cached contract at address: {address}"); + greyln!("Successfully cached contract at address: {addr}"); } let tx_hash = receipt.transaction_hash.debug_lavender(); - greyln!("Sent Stylus cache tx with hash: {tx_hash}"); + greyln!("Sent Stylus cache bid tx with hash: {tx_hash}"); Ok(()) } + +async fn get_cache_manager_address

(provider: P) -> Result

+where + P: Provider + Clone + Send + Sync, +{ + let arb_wasm_cache = ArbWasmCache::new(ARB_WASM_CACHE_ADDRESS, provider.clone()); + let result = arb_wasm_cache.allCacheManagers().call().await?; + if result.managers.is_empty() { + bail!("no cache managers found in ArbWasmCache, perhaps the Stylus cache is not yet enabled on this chain"); + } + Ok(*result.managers.last().unwrap()) +} + +fn format_gas(gas: u128) -> String { + let gas: u128 = gas.try_into().unwrap_or(u128::MAX); + let text = format!("{gas} gas"); + if gas <= 3_000_000 { + text.mint() + } else if gas <= 7_000_000 { + text.yellow() + } else { + text.pink() + } +} + +fn handle_cache_manager_error(err: CacheManagerErrors) -> Result<()> { + use CacheManager::CacheManagerErrors as C; + match err { + C::AsmTooLarge(_) => bail!("Stylus contract was too large to cache"), + C::AlreadyCached(_) => bail!("Stylus contract is already cached"), + C::BidsArePaused(_) => { + bail!("Bidding is currently paused for the Stylus cache manager") + } + C::BidTooSmall(_) => { + bail!("Bid amount (wei) too small"); + } + C::ProgramNotActivated(_) => { + bail!("Your Stylus contract is not yet activated. To activate it, use the `cargo stylus activate` subcommand"); + } + } +} diff --git a/check/src/constants.rs b/check/src/constants.rs index 935d9b9..628ef38 100644 --- a/check/src/constants.rs +++ b/check/src/constants.rs @@ -43,3 +43,6 @@ pub const PROJECT_HASH_SECTION_NAME: &str = "project_hash"; /// Name of the toolchain file used to specify the Rust toolchain version for a project. pub const TOOLCHAIN_FILE_NAME: &str = "rust-toolchain.toml"; + +/// The default endpoint for connections to a Stylus-enabled Arbitrum node. +pub const DEFAULT_ENDPOINT: &str = "https://sepolia-rollup.arbitrum.io/rpc"; diff --git a/check/src/deploy.rs b/check/src/deploy.rs index 4dc424a..cfb7fff 100644 --- a/check/src/deploy.rs +++ b/check/src/deploy.rs @@ -98,6 +98,14 @@ pub async fn deploy(cfg: DeployConfig) -> Result<()> { } ContractCheck::Active { .. } => greyln!("wasm already activated!"), } + println!(""); + let note = format!( + r#"NOTE: We recommend running cargo stylus cache bid 0 {} to cache your activated contract in ArbOS. +Cached contracts benefit from cheaper calls. To read more about the Stylus contract cache, see +https://docs.arbitrum.io/stylus/concepts/stylus-cache-manager"#, + hex::encode(contract_addr), + ).debug_mint(); + println!("{note}"); Ok(()) } @@ -162,12 +170,6 @@ impl DeployConfig { } let tx_hash = receipt.transaction_hash.debug_lavender(); greyln!("deployment tx hash: {tx_hash}"); - println!( - r#"INFO: Your program is not yet part of the Stylus contract cache. We recommend running `cargo stylus cache --address={}` to cache your activated contract in ArbOS. -Cached contracts benefit from cheaper calls. To read more about the Stylus contract cache, see -https://docs.arbitrum.io/stylus/concepts/stylus-cache-manager"#, - hex::encode(contract) - ); Ok(contract) } @@ -228,7 +230,7 @@ pub async fn run_tx( name: &str, tx: Eip1559TransactionRequest, gas: Option, - max_fee_per_gas_gwei: Option, + max_fee_per_gas_gwei: Option, client: &SignerClient, verbose: bool, ) -> Result { @@ -237,7 +239,7 @@ pub async fn run_tx( tx.gas = Some(gas); } if let Some(max_fee) = max_fee_per_gas_gwei { - tx.max_fee_per_gas = Some(gwei_to_wei(max_fee)?); + tx.max_fee_per_gas = Some(U256::from(gwei_to_wei(max_fee)?)); } let tx = TypedTransaction::Eip1559(tx); let tx = client.send_transaction(tx, None).await?; @@ -301,8 +303,8 @@ pub fn format_gas(gas: U256) -> String { } } -fn gwei_to_wei(gwei: U256) -> Result { - let wei_per_gwei: U256 = U256::from(10u64.pow(9)); +pub fn gwei_to_wei(gwei: u128) -> Result { + let wei_per_gwei: u128 = 10u128.pow(9); match gwei.checked_mul(wei_per_gwei) { Some(wei) => Ok(wei), None => bail!("overflow occurred while converting gwei to wei"), diff --git a/check/src/main.rs b/check/src/main.rs index 239d6f4..490e38b 100644 --- a/check/src/main.rs +++ b/check/src/main.rs @@ -1,8 +1,9 @@ // Copyright 2023-2024, Offchain Labs, Inc. // For licensing, see https://github.com/OffchainLabs/cargo-stylus/blob/main/licenses/COPYRIGHT.md -use clap::{ArgGroup, Args, Parser}; -use ethers::types::{H160, U256}; +use clap::{ArgGroup, Args, Parser, Subcommand}; +use constants::DEFAULT_ENDPOINT; +use ethers::types::H160; use eyre::{eyre, Context, Result}; use std::fmt; use std::path::PathBuf; @@ -60,8 +61,9 @@ enum Apis { /// Activate an already deployed contract. #[command(alias = "a")] Activate(ActivateConfig), + #[command(subcommand)] /// Cache a contract using the Stylus CacheManager for Arbitrum chains. - Cache(CacheConfig), + Cache(Cache), /// Check a contract. #[command(alias = "c")] Check(CheckConfig), @@ -76,7 +78,7 @@ enum Apis { #[derive(Args, Clone, Debug)] struct CommonConfig { /// Arbitrum RPC endpoint. - #[arg(short, long, default_value = "https://sepolia-rollup.arbitrum.io/rpc")] + #[arg(short, long, default_value = DEFAULT_ENDPOINT)] endpoint: String, /// Whether to print debug info. #[arg(long)] @@ -90,22 +92,59 @@ struct CommonConfig { source_files_for_project_hash: Vec, #[arg(long)] /// Optional max fee per gas in gwei units. - max_fee_per_gas_gwei: Option, + max_fee_per_gas_gwei: Option, +} + +#[derive(Subcommand, Clone, Debug)] +enum Cache { + /// Places a bid on a Stylus contract to cache it in the Arbitrum chain's wasm cache manager. + #[command(alias = "b")] + Bid(CacheBidConfig), + /// Checks the status of a Stylus contract in the Arbitrum chain's wasm cache manager. + #[command(alias = "s")] + Status(CacheStatusConfig), + /// Checks the status of a Stylus contract in the Arbitrum chain's wasm cache manager. + #[command()] + SuggestBid(CacheSuggestionsConfig), } #[derive(Args, Clone, Debug)] -pub struct CacheConfig { - #[command(flatten)] - common_cfg: CommonConfig, +pub struct CacheBidConfig { + /// Arbitrum RPC endpoint. + #[arg(short, long, default_value = DEFAULT_ENDPOINT)] + endpoint: String, + /// Whether to print debug info. + #[arg(long)] + verbose: bool, /// Wallet source to use. #[command(flatten)] auth: AuthOpts, /// Deployed and activated contract address to cache. + address: H160, + /// Bid, in wei, to place on the desired contract to cache. A value of 0 is a valid bid. + bid: u64, #[arg(long)] + /// Optional max fee per gas in gwei units. + max_fee_per_gas_gwei: Option, +} + +#[derive(Args, Clone, Debug)] +pub struct CacheStatusConfig { + /// Arbitrum RPC endpoint. + #[arg(short, long, default_value = DEFAULT_ENDPOINT)] + endpoint: String, + /// Stylus contract address to check status in the cache manager. + #[arg(long)] + address: Option, +} + +#[derive(Args, Clone, Debug)] +pub struct CacheSuggestionsConfig { + /// Arbitrum RPC endpoint. + #[arg(short, long, default_value = DEFAULT_ENDPOINT)] + endpoint: String, + /// Stylus contract address to suggest a minimum bid for in the cache manager. address: H160, - /// Bid, in wei, to place on the desired contract to cache - #[arg(short, long, hide(true))] - bid: Option, } #[derive(Args, Clone, Debug)] @@ -317,9 +356,26 @@ async fn main_impl(args: Opts) -> Result<()> { "stylus activate failed" ); } - Apis::Cache(config) => { - run!(cache::cache_contract(&config).await, "stylus cache failed"); - } + Apis::Cache(subcommand) => match subcommand { + Cache::Bid(config) => { + run!( + cache::place_bid(&config).await, + "stylus cache place bid failed" + ); + } + Cache::SuggestBid(config) => { + run!( + cache::suggest_bid(&config).await, + "stylus cache suggest-bid failed" + ); + } + Cache::Status(config) => { + run!( + cache::check_status(&config).await, + "stylus cache status failed" + ); + } + }, Apis::Check(config) => { run!(check::check(&config).await, "stylus checks failed"); } diff --git a/check/src/wallet.rs b/check/src/wallet.rs index adcda45..9a915d9 100644 --- a/check/src/wallet.rs +++ b/check/src/wallet.rs @@ -2,7 +2,11 @@ // For licensing, see https://github.com/OffchainLabs/cargo-stylus/blob/main/licenses/COPYRIGHT.md use crate::AuthOpts; -use cargo_stylus_util::text; +use alloy_primitives::FixedBytes; +use alloy_provider::network::EthereumWallet; +use alloy_signer::Signer; +use alloy_signer_local::PrivateKeySigner; +use cargo_stylus_util::text::{self, decode0x}; use ethers::signers::LocalWallet; use eyre::{eyre, Context, Result}; use std::fs; @@ -38,4 +42,35 @@ impl AuthOpts { LocalWallet::decrypt_keystore(keystore, password).wrap_err("could not decrypt keystore") } + + pub fn alloy_wallet(&self, chain_id: u64) -> Result { + if let Some(key) = &self.private_key { + if key.is_empty() { + return Err(eyre!("empty private key")); + } + let priv_key_bytes: FixedBytes<32> = FixedBytes::from_slice(decode0x(key)?.as_slice()); + let signer = + PrivateKeySigner::from_bytes(&priv_key_bytes)?.with_chain_id(Some(chain_id)); + return Ok(EthereumWallet::new(signer)); + } + + if let Some(file) = &self.private_key_path { + let key = fs::read_to_string(file).wrap_err("could not open private key file")?; + let priv_key_bytes: FixedBytes<32> = FixedBytes::from_slice(decode0x(key)?.as_slice()); + let signer = + PrivateKeySigner::from_bytes(&priv_key_bytes)?.with_chain_id(Some(chain_id)); + return Ok(EthereumWallet::new(signer)); + } + + let keystore = self.keystore_path.as_ref().ok_or(eyre!("no keystore"))?; + let password = self + .keystore_password_path + .as_ref() + .map(fs::read_to_string) + .unwrap_or(Ok("".into()))?; + + let signer = + PrivateKeySigner::decrypt_keystore(keystore, password)?.with_chain_id(Some(chain_id)); + return Ok(EthereumWallet::new(signer)); + } }