diff --git a/Cargo.lock b/Cargo.lock index dfba341dae..38e46c3378 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,15 +13,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -35,6 +26,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", + "getrandom 0.3.3", "once_cell", "version_check", "zerocopy", @@ -55,11 +47,34 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07655fedc35188f3c50ff8fc6ee45703ae14ef1bc7ae7d80e23a747012184e3" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-trie", +] + [[package]] name = "alloy-chains" -version = "0.2.4" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a9cc9d81ace3da457883b0bdf76776e55f1b84219a9e9d55c27ad308548d3f" +checksum = "35d744058a9daa51a8cf22a3009607498fcf82d3cf4c5444dd8056cdf651f471" dependencies = [ "alloy-primitives", "num_enum", @@ -68,9 +83,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bcb57295c4b632b6b3941a089ee82d00ff31ff9eb3eac801bf605ffddc81041" +checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" dependencies = [ "alloy-eips", "alloy-primitives", @@ -79,6 +94,7 @@ dependencies = [ "alloy-trie", "alloy-tx-macros", "auto_impl", + "borsh", "c-kzg", "derive_more", "either", @@ -87,15 +103,16 @@ dependencies = [ "rand 0.8.5", "secp256k1 0.30.0", "serde", + "serde_json", "serde_with", "thiserror", ] [[package]] name = "alloy-consensus-any" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab669be40024565acb719daf1b2a050e6dc065fc0bec6050d97a81cdb860bd7" +checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" dependencies = [ "alloy-consensus", "alloy-eips", @@ -105,6 +122,57 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-contract" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d39c80ffc806f27a76ed42f3351a455f3dc4f81d6ff92c8aad2cf36b7d3a34" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-core" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a651e1d9e50e6d0a78bd23cd08facb70459a94501c4036c7799a093e569a310" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d48a9101f4a67c22fae57489f1ddf3057b8ab4a368d8eac3be088b6e9d9c9d9" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "itoa", + "serde", + "serde_json", + "winnow", +] + [[package]] name = "alloy-eip2124" version = "0.2.0" @@ -120,23 +188,25 @@ dependencies = [ [[package]] name = "alloy-eip2930" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "serde", ] [[package]] name = "alloy-eip7702" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "k256", "serde", "thiserror", @@ -144,9 +214,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f853de9ca1819f54de80de5d03bfc1bb7c9fafcf092b480a654447141bc354d" +checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -155,18 +225,36 @@ dependencies = [ "alloy-rlp", "alloy-serde", "auto_impl", + "borsh", "c-kzg", "derive_more", "either", "serde", + "serde_with", "sha2 0.10.9", + "thiserror", +] + +[[package]] +name = "alloy-genesis" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba4b1be0988c11f0095a2380aa596e35533276b8fa6c9e06961bbfe0aebcac5" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "borsh", + "serde", + "serde_with", ] [[package]] name = "alloy-json-abi" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26fdd571915bafe857fccba4ee1a4f352965800e46a53e4a5f50187b7776fa" +checksum = "9914c147bb9b25f440eca68a31dc29f5c22298bfa7754aa802965695384122b0" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -176,9 +264,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4997a9873c8639d079490f218e50e5fa07e70f957e9fc187c0a0535977f482f" +checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -191,9 +279,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0306e8d148b7b94d988615d367443c1b9d6d2e9fecd2e1f187ac5153dce56f5" +checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -217,9 +305,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eef189583f4c53d231dd1297b28a675ff842b551fb34715f562868a1937431a" +checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" dependencies = [ "alloy-consensus", "alloy-eips", @@ -230,21 +318,20 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a326d47106039f38b811057215a92139f46eef7983a4b77b10930a0ea5685b1e" +checksum = "7db950a29746be9e2f2c6288c8bd7a6202a81f999ce109a2933d2379970ec0fa" dependencies = [ "alloy-rlp", "arbitrary", "bytes", "cfg-if", "const-hex", - "derive_arbitrary", "derive_more", - "foldhash", + "foldhash 0.2.0", "getrandom 0.3.3", - "hashbrown 0.15.4", - "indexmap 2.9.0", + "hashbrown 0.16.1", + "indexmap 2.12.1", "itoa", "k256", "keccak-asm", @@ -252,6 +339,7 @@ dependencies = [ "proptest", "proptest-derive", "rand 0.9.1", + "rapidhash", "ruint", "rustc-hash", "serde", @@ -261,9 +349,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea624ddcdad357c33652b86aa7df9bd21afd2080973389d3facf1a221c573948" +checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -285,7 +373,6 @@ dependencies = [ "either", "futures", "futures-utils-wasm", - "http", "lru", "parking_lot", "pin-project", @@ -323,15 +410,14 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e43d00b4de38432304c4e4b01ae6a3601490fd9824c852329d158763ec18663c" +checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" dependencies = [ "alloy-json-rpc", "alloy-primitives", "alloy-transport", "alloy-transport-http", - "async-stream", "futures", "pin-project", "reqwest", @@ -341,16 +427,27 @@ dependencies = [ "tokio-stream", "tower", "tracing", - "tracing-futures", "url", "wasmtimer", ] +[[package]] +name = "alloy-rpc-types" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cf1398cb33aacb139a960fa3d8cf8b1202079f320e77e952a0b95967bf7a9f" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + [[package]] name = "alloy-rpc-types-any" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5958f2310d69f4806e6f6b90ceb4f2b781cc5a843517a7afe2e7cfec6de3cfb9" +checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -359,9 +456,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1826285e4ffc2372a8c061d5cc145858e67a0be3309b768c5b77ddb6b9e6cbc7" +checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -374,14 +471,15 @@ dependencies = [ "itertools 0.14.0", "serde", "serde_json", + "serde_with", "thiserror", ] [[package]] name = "alloy-serde" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "906ce0190afeded19cb2e963cb8507c975a7862216b9e74f39bf91ddee6ae74b" +checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" dependencies = [ "alloy-primitives", "serde", @@ -390,9 +488,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89baab06195c4be9c5d66f15c55e948013d1aff3ec1cfb0ed469e1423313fce" +checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" dependencies = [ "alloy-primitives", "async-trait", @@ -405,9 +503,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a249a923e302ac6db932567c43945392f0b6832518aab3c4274858f58756774" +checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" dependencies = [ "alloy-consensus", "alloy-network", @@ -421,9 +519,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4be1ce1274ddd7fdfac86e5ece1b225e9bba1f2327e20fbb30ee6b9cc1423fe" +checksum = "a3b96d5f5890605ba9907ce1e2158e2701587631dc005bfa582cf92dd6f21147" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -435,14 +533,15 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e92f3708ea4e0d9139001c86c051c538af0146944a2a9c7181753bd944bf57" +checksum = "b8247b7cca5cde556e93f8b3882b01dbd272f527836049083d240c57bf7b4c15" dependencies = [ + "alloy-json-abi", "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.9.0", + "indexmap 2.12.1", "proc-macro-error2", "proc-macro2", "quote", @@ -453,25 +552,27 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afe1bd348a41f8c9b4b54dfb314886786d6201235b0b3f47198b9d910c86bb2" +checksum = "3cd54f38512ac7bae10bbc38480eefb1b9b398ca2ce25db9cc0c048c6411c4f1" dependencies = [ + "alloy-json-abi", "const-hex", "dunce", "heck", "macro-string", "proc-macro2", "quote", + "serde_json", "syn 2.0.103", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6195df2acd42df92a380a8db6205a5c7b41282d0ce3f4c665ecf7911ac292f1" +checksum = "444b09815b44899564566d4d56613d14fa9a274b1043a021f00468568752f449" dependencies = [ "serde", "winnow", @@ -479,9 +580,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6185e98a79cf19010722f48a74b5a65d153631d2f038cabd250f4b9e9813b8ad" +checksum = "dc1038284171df8bfd48befc0c7b78f667a7e2be162f45f07bd1c378078ebe58" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -491,12 +592,12 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1ae10b1bc77fde38161e242749e41e65e34000d05da0a3d3f631e03bfcb19e" +checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" dependencies = [ "alloy-json-rpc", - "alloy-primitives", + "auto_impl", "base64", "derive_more", "futures", @@ -514,9 +615,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b234272ee449e32c9f1afbbe4ee08ea7c4b52f14479518f95c844ab66163c545" +checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -529,9 +630,9 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" +checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -545,23 +646,16 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75ef8609ea2b31c799b0a56c724dca4c73105c5ccc205d9dfeb1d038df6a1da" +checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" dependencies = [ - "alloy-primitives", - "darling", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.103", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -577,6 +671,17 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "annotate-snippets" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96401ca08501972288ecbcde33902fce858bf73fbcbdf91dab8c3a9544e106bb" +dependencies = [ + "anstyle", + "memchr", + "unicode-width", +] + [[package]] name = "anstream" version = "0.6.19" @@ -638,6 +743,9 @@ name = "arbitrary" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "ark-bls12-381" @@ -1010,21 +1118,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -1168,6 +1261,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "borsh" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "boxcar" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e" + [[package]] name = "bumpalo" version = "3.18.1" @@ -1218,10 +1340,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.27" +version = "1.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" dependencies = [ + "find-msvc-tools", "shlex", ] @@ -1231,17 +1354,22 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -1375,7 +1503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1436,6 +1564,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +[[package]] +name = "convert_case" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1446,6 +1583,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1476,6 +1623,15 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + [[package]] name = "criterion-plot" version = "0.5.0" @@ -1566,8 +1722,18 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", ] [[package]] @@ -1584,13 +1750,39 @@ dependencies = [ "syn 2.0.103", ] +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "serde", + "strsim", + "syn 2.0.103", +] + [[package]] name = "darling_macro" version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", "quote", "syn 2.0.103", ] @@ -1640,6 +1832,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-getters" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + [[package]] name = "derive-where" version = "1.5.0" @@ -1677,6 +1880,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ + "convert_case", "proc-macro2", "quote", "syn 2.0.103", @@ -1704,6 +1908,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1822,7 +2047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1975,6 +2200,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -1988,8 +2219,19 @@ dependencies = [ ] [[package]] -name = "fnv" -version = "1.0.7" +name = "flate2" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +dependencies = [ + "crc32fast", + "miniz_oxide", + "zlib-rs", +] + +[[package]] +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" @@ -1999,6 +2241,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2023,6 +2271,98 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "foundry-compilers" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e639f98fe54d1cc0011a4bdb2eb1d838b379c9f004991ae7555a4cc09e8da32a" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "auto_impl", + "derive_more", + "dyn-clone", + "foundry-compilers-artifacts", + "foundry-compilers-core", + "itertools 0.14.0", + "path-slash", + "rayon", + "semver 1.0.26", + "serde", + "serde_json", + "solar-compiler", + "svm-rs", + "thiserror", + "tracing", + "winnow", + "yansi", +] + +[[package]] +name = "foundry-compilers-artifacts" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ec96df20055211f4e46b5a61fa479b2ea7d1ce0659818e0359afadfcded8d2" +dependencies = [ + "foundry-compilers-artifacts-solc", + "foundry-compilers-artifacts-vyper", +] + +[[package]] +name = "foundry-compilers-artifacts-solc" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a206e475b5dd1a77dc33cd917cde4846148f5136729a24edb3a16ab431b90a" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "foundry-compilers-core", + "memchr", + "path-slash", + "rayon", + "regex", + "semver 1.0.26", + "serde", + "serde_json", + "thiserror", + "tracing", + "yansi", +] + +[[package]] +name = "foundry-compilers-artifacts-vyper" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f74883db8036522fa21d0853c21ac318e165ec88e141f1ef1d6f7b4dfa841ff7" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "foundry-compilers-artifacts-solc", + "foundry-compilers-core", + "path-slash", + "semver 1.0.26", + "serde", +] + +[[package]] +name = "foundry-compilers-core" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab384daeaea5c33cad8c3c094a1eb6f98e70922e18380c660980c74c19e362b" +dependencies = [ + "alloy-primitives", + "cfg-if", + "dunce", + "path-slash", + "regex", + "semver 1.0.26", + "serde", + "serde_json", + "thiserror", + "walkdir", + "xxhash-rust", +] + [[package]] name = "funty" version = "2.0.0" @@ -2154,8 +2494,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -2165,17 +2507,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.2" @@ -2239,8 +2577,18 @@ checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", "serde", + "serde_core", ] [[package]] @@ -2341,6 +2689,24 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -2375,7 +2741,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -2538,6 +2904,12 @@ dependencies = [ "syn 2.0.103", ] +[[package]] +name = "index_vec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" + [[package]] name = "indexmap" version = "1.9.3" @@ -2551,14 +2923,15 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ "arbitrary", "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.16.1", "serde", + "serde_core", ] [[package]] @@ -2574,6 +2947,19 @@ dependencies = [ "web-time", ] +[[package]] +name = "inturn" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2efbe120e37f17bb33fcdc82bc1c65087242608be37ace3cf7ebf49f3164e37" +dependencies = [ + "boxcar", + "bumpalo", + "dashmap", + "hashbrown 0.14.5", + "thread_local", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -2598,7 +2984,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2727,6 +3113,16 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "libsecp256k1" version = "0.7.2" @@ -2810,6 +3206,12 @@ dependencies = [ "hashbrown 0.15.4", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "macro-string" version = "0.1.4" @@ -2834,6 +3236,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -2856,14 +3259,20 @@ dependencies = [ "libc", "log", "openssl", - "openssl-probe", + "openssl-probe 0.1.6", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] +[[package]] +name = "normalize-path" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5438dd2b2ff4c6df6e1ce22d825ed2fa93ee2922235cc45186991717f0a892d" + [[package]] name = "num" version = "0.4.3" @@ -2994,26 +3403,18 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "nybbles" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8983bb634df7248924ee0c4c3a749609b5abcb082c28fffe3254b3eb3602b307" +checksum = "bfa11e84403164a9f12982ab728f3c67c6fd4ab5b5f0254ffc217bdbd3b28ab0" dependencies = [ "alloy-rlp", - "const-hex", + "cfg-if", "proptest", + "ruint", "serde", "smallvec", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -3026,6 +3427,18 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +[[package]] +name = "once_map" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29eefd5038c9eee9e788d90966d6b5578dd3f88363a91edaec117a7ae0adc2d5" +dependencies = [ + "ahash", + "hashbrown 0.16.1", + "parking_lot", + "stable_deref_trait", +] + [[package]] name = "oorandom" version = "11.1.5" @@ -3084,6 +3497,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "openssl-sys" version = "0.9.109" @@ -3096,6 +3515,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "p256" version = "0.13.2" @@ -3277,7 +3702,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3286,6 +3711,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -3543,9 +3974,9 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" +checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" dependencies = [ "proc-macro2", "quote", @@ -3558,6 +3989,61 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.6.1", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.1", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.40" @@ -3650,11 +4136,21 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rapidhash" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e65c75143ce5d47c55b510297eeb1182f3c739b6043c537670e9fc18612dae" +dependencies = [ + "rand 0.9.1", + "rustversion", +] + [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -3662,9 +4158,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -3679,6 +4175,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror", +] + [[package]] name = "ref-cast" version = "1.0.24" @@ -3747,6 +4254,7 @@ dependencies = [ "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", "hyper-util", "js-sys", @@ -3754,6 +4262,9 @@ dependencies = [ "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -3761,6 +4272,7 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -3768,6 +4280,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", ] [[package]] @@ -3983,6 +4496,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "revm-supra-extension" +version = "0.1.0" +dependencies = [ + "alloy", + "alloy-consensus", + "alloy-contract", + "alloy-eips", + "alloy-serde", + "alloy-sol-types", + "anyhow", + "derive-getters", + "derive_more", + "foundry-compilers", + "revm-context", + "revm-primitives", + "serde", + "serde_json", + "thiserror", + "toml", +] + [[package]] name = "revme" version = "7.2.2" @@ -4023,6 +4558,20 @@ dependencies = [ "subtle", ] +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -4118,12 +4667,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" -[[package]] -name = "rustc-demangle" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -4167,26 +4710,64 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] -name = "rustls-pki-types" -version = "1.12.0" +name = "rustls" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", "zeroize", ] [[package]] -name = "rustversion" -version = "1.0.21" +name = "rustls-native-certs" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" - -[[package]] -name = "rusty-fork" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe 0.2.1", + "rustls-pki-types", + "schannel", + "security-framework 3.5.1", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "rusty-fork" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" @@ -4233,6 +4814,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -4302,7 +4889,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -4310,9 +4910,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -4332,6 +4932,9 @@ name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +dependencies = [ + "serde", +] [[package]] name = "semver-parser" @@ -4344,10 +4947,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -4360,11 +4964,20 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -4373,15 +4986,25 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.12.1", "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +dependencies = [ + "serde_core", ] [[package]] @@ -4406,7 +5029,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.9.0", + "indexmap 2.12.1", "schemars", "serde", "serde_derive", @@ -4421,7 +5044,7 @@ version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81679d9ed988d5e9a5e6531dc3f2c28efbd639cbd1dfb628df08edea6004da77" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", "syn 2.0.103", @@ -4507,6 +5130,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + [[package]] name = "siphasher" version = "1.0.1" @@ -4538,6 +5167,162 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "solar-ast" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6aaf98d032ba3be85dca5f969895ade113a9137bb5956f80c5faf14689de59" +dependencies = [ + "alloy-primitives", + "bumpalo", + "either", + "num-rational", + "semver 1.0.26", + "solar-data-structures", + "solar-interface", + "solar-macros", + "strum", +] + +[[package]] +name = "solar-compiler" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e792060bcbb007a6b9b060292945fb34ff854c7d93a9628f81b6c809eb4360" +dependencies = [ + "alloy-primitives", + "solar-ast", + "solar-config", + "solar-data-structures", + "solar-interface", + "solar-macros", + "solar-parse", + "solar-sema", +] + +[[package]] +name = "solar-config" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff16d692734c757edd339f5db142ba91b42772f8cbe1db1ce3c747f1e777185f" +dependencies = [ + "colorchoice", + "strum", +] + +[[package]] +name = "solar-data-structures" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dea34e58332c7d6a8cde1f1740186d31682b7be46e098b8cc16fcb7ffd98bf5" +dependencies = [ + "bumpalo", + "index_vec", + "indexmap 2.12.1", + "parking_lot", + "rayon", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "solar-interface" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6163af2e773f4d455212fa9ba2c0664506029dd26232eb406f5046092ac311" +dependencies = [ + "annotate-snippets", + "anstream", + "anstyle", + "derive_more", + "dunce", + "inturn", + "itertools 0.14.0", + "itoa", + "normalize-path", + "once_map", + "rayon", + "scoped-tls", + "serde", + "serde_json", + "solar-config", + "solar-data-structures", + "solar-macros", + "thiserror", + "tracing", + "unicode-width", +] + +[[package]] +name = "solar-macros" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44a98045888d75d17f52e7b76f6098844b76078b5742a450c3ebcdbdb02da124" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.103", +] + +[[package]] +name = "solar-parse" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b77a9cbb07948e4586cdcf64f0a483424197308816ebd57a4cf06130b68562" +dependencies = [ + "alloy-primitives", + "bitflags", + "bumpalo", + "itertools 0.14.0", + "memchr", + "num-bigint 0.4.6", + "num-rational", + "num-traits", + "ruint", + "smallvec", + "solar-ast", + "solar-data-structures", + "solar-interface", + "tracing", +] + +[[package]] +name = "solar-sema" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd033af43a38da316a04b25bbd20b121ce5d728b61e6988fd8fd6e2f1e68d0a1" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "bitflags", + "bumpalo", + "derive_more", + "either", + "once_map", + "paste", + "rayon", + "serde", + "serde_json", + "solar-ast", + "solar-data-structures", + "solar-interface", + "solar-macros", + "solar-parse", + "strum", + "thread_local", + "tracing", +] + [[package]] name = "sp1-lib" version = "5.0.5" @@ -4659,6 +5444,25 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "svm-rs" +version = "0.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "415b159b54c22d9810087f0991371fd6242a912673e982a7c4ca8ea122f7e00a" +dependencies = [ + "const-hex", + "dirs", + "reqwest", + "semver 1.0.26", + "serde", + "serde_json", + "sha2 0.10.9", + "tempfile", + "thiserror", + "url", + "zip", +] + [[package]] name = "syn" version = "1.0.109" @@ -4683,9 +5487,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.2.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c8c8f496c33dc6343dac05b4be8d9e0bca180a4caa81d7b8416b10cc2273cd" +checksum = "f6b1d2e2059056b66fec4a6bb2b79511d5e8d76196ef49c38996f4b48db7662f" dependencies = [ "paste", "proc-macro2", @@ -4729,29 +5533,38 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", "syn 2.0.103", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "threadpool" version = "1.8.1" @@ -4821,27 +5634,41 @@ dependencies = [ "serde_json", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" -version = "1.45.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", "libc", "mio", "pin-project-lite", - "socket2", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -4858,6 +5685,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.17" @@ -4883,23 +5720,62 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.9.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +dependencies = [ + "indexmap 2.12.1", + "serde_core", + "serde_spanned", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow", +] + [[package]] name = "toml_datetime" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.9.0", - "toml_datetime", + "indexmap 2.12.1", + "toml_datetime 0.6.11", "winnow", ] +[[package]] +name = "toml_parser" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" + [[package]] name = "tower" version = "0.5.2" @@ -4977,18 +5853,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "futures", - "futures-task", - "pin-project", - "tracing", -] - [[package]] name = "tracing-subscriber" version = "0.2.25" @@ -5050,11 +5914,17 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unicode-xid" @@ -5062,6 +5932,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "unty" version = "0.0.4" @@ -5093,9 +5969,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -5274,13 +6150,22 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5291,7 +6176,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -5324,13 +6209,19 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-result" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5339,7 +6230,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -5348,7 +6239,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5357,7 +6248,25 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", ] [[package]] @@ -5366,14 +6275,31 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -5382,53 +6308,101 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" -version = "0.7.11" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] @@ -5457,6 +6431,18 @@ dependencies = [ "tap", ] +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "yoke" version = "0.8.0" @@ -5574,3 +6560,41 @@ dependencies = [ "quote", "syn 2.0.103", ] + +[[package]] +name = "zip" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" +dependencies = [ + "arbitrary", + "crc32fast", + "flate2", + "indexmap 2.12.1", + "memchr", + "zopfli", +] + +[[package]] +name = "zlib-rs" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" + +[[package]] +name = "zmij" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" + +[[package]] +name = "zopfli" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] diff --git a/Cargo.toml b/Cargo.toml index dd4f8aaf67..7354ecfad1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ members = [ "crates/context", "crates/context/interface", "crates/handler", + # supra extensions + "crates/supra-extension", # variants "crates/op-revm", @@ -35,6 +37,7 @@ members = [ "examples/my_evm", "examples/custom_opcodes", "examples/custom_precompile_journal", + ] resolver = "2" default-members = ["crates/revm"] @@ -56,6 +59,7 @@ context-interface = { path = "crates/context/interface", package = "revm-context handler = { path = "crates/handler", package = "revm-handler", version = "10.0.0", default-features = false } op-revm = { path = "crates/op-revm", package = "op-revm", version = "10.0.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } +supra-extension = { path = "crates/supra-extension", package = "revm-supra-extension", version = "0.1.0", default-features = false } # alloy alloy-eip2930 = { version = "0.2.1", default-features = false } @@ -72,6 +76,18 @@ alloy-signer = { version = "1.0.12", default-features = false } alloy-signer-local = { version = "1.0.12", default-features = false } alloy-transport = { version = "1.0.12", default-features = false } +alloy-contract = { version = "1.0.19"} +alloy = { version = "1.0.19", features = ["sol-types", "contract"] } +alloy-serde = { version = "1.0.19" } + +# libraries required to build supra-contract bindings +# For more detaisl see crates/supra-extension/build.rs +#forge = { git = "https://github.com/foundry-rs/foundry.git", tag="v1.4.1"} +#alloy-chains = { version = "0.2.13" } +#shlex = { version = "1.3.0" } +foundry-compilers = "0.19.14" +toml = { version = "0.9.8"} + # precompiles ark-bls12-381 = { version = "0.5", default-features = false } ark-bn254 = { version = "0.5", default-features = false } @@ -103,7 +119,7 @@ criterion = { package = "codspeed-criterion-compat", version = "2.10" } # serde serde = { version = "1.0", default-features = false } -serde_json = { version = "1.0", default-features = false } +serde_json = { version = "1.0.149", default-features = false } # misc auto_impl = "1.3.0" @@ -113,6 +129,8 @@ derive-where = { version = "1.5.0", default-features = false } rand = "0.9" tokio = "1.45" either = { version = "1.15.0", default-features = false } +derive_more = { version = "2.0.1" } +derive-getters = { version = "0.5.0" } # dev-dependencies anyhow = "1.0.98" diff --git a/crates/context/interface/src/cfg.rs b/crates/context/interface/src/cfg.rs index 08886e2e78..725f19c656 100644 --- a/crates/context/interface/src/cfg.rs +++ b/crates/context/interface/src/cfg.rs @@ -4,6 +4,50 @@ use core::fmt::Debug; use core::hash::Hash; use primitives::{hardfork::SpecId, Address, TxKind, U256}; +/// Describes execution context of the transaction. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, Eq, PartialEq, Default)] +pub enum ExecutionMode { + #[default] + /// Executing user submitted transaction. + User, + /// Executing automated transaction. + Automated, + /// Executing governance sponsored automated transaction. + AutomatedGasless, + /// Executing governance native transaction. + System, + /// When transactions are executed in genesis mode. + Genesis, +} + +impl ExecutionMode { + /// Returns true if gas should be charged for execution. + pub fn charges_gas(&self) -> bool { + match self { + ExecutionMode::User | ExecutionMode::Automated => true, + ExecutionMode::AutomatedGasless | ExecutionMode::System | ExecutionMode::Genesis => { + false + } + } + } + + /// Returns true if nonce should be updated in case of successful execution. + pub fn updates_nonce(&self) -> bool { + matches!(self, ExecutionMode::User | ExecutionMode::Genesis) + } + + /// Returns true if the execution context is for governance native transaction + pub fn is_system(&self) -> bool { + matches!(self, ExecutionMode::System) + } + + /// Returns true if the execution context is for governance genesis transaction + pub fn is_genesis(&self) -> bool { + matches!(self, ExecutionMode::Genesis) + } +} + /// Configuration for the EVM. #[auto_impl(&, &mut, Box, Arc)] pub trait Cfg { @@ -60,7 +104,7 @@ pub trait Cfg { fn is_priority_fee_check_disabled(&self) -> bool; /// Returns whether the automation mode is enabled. - fn is_automation_mode(&self) -> bool; + fn execution_mode(&self) -> &ExecutionMode; } /// What bytecode analysis to perform diff --git a/crates/context/interface/src/lib.rs b/crates/context/interface/src/lib.rs index 0e66071368..499c0aba67 100644 --- a/crates/context/interface/src/lib.rs +++ b/crates/context/interface/src/lib.rs @@ -15,7 +15,7 @@ pub mod result; pub mod transaction; pub use block::Block; -pub use cfg::{Cfg, CreateScheme, TransactTo}; +pub use cfg::{Cfg, CreateScheme, ExecutionMode, TransactTo}; pub use context::{ContextError, ContextSetters, ContextTr}; pub use database_interface::{DBErrorMarker, Database}; pub use either; diff --git a/crates/context/src/cfg.rs b/crates/context/src/cfg.rs index 668ba69a84..fc457c1456 100644 --- a/crates/context/src/cfg.rs +++ b/crates/context/src/cfg.rs @@ -1,7 +1,8 @@ //! This module contains [`CfgEnv`] and implements [`Cfg`] trait for it. +use context_interface::cfg::ExecutionMode; pub use context_interface::Cfg; - use primitives::{eip170, eip3860, eip7825, hardfork::SpecId}; + /// EVM configuration #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, Eq, PartialEq)] @@ -104,8 +105,8 @@ pub struct CfgEnv { /// By default, it is set to `false`. #[cfg(feature = "optional_priority_fee_check")] pub disable_priority_fee_check: bool, - /// Whether to run the EVM in automation mode. - pub automation_mode: bool, + /// Execution mode the EVM is configured to run. + pub execution_mode: ExecutionMode, } impl CfgEnv { @@ -161,7 +162,7 @@ impl CfgEnv { disable_base_fee: false, #[cfg(feature = "optional_priority_fee_check")] disable_priority_fee_check: false, - automation_mode: false, + execution_mode: ExecutionMode::User, } } @@ -209,7 +210,7 @@ impl CfgEnv { disable_base_fee: self.disable_base_fee, #[cfg(feature = "optional_priority_fee_check")] disable_priority_fee_check: self.disable_priority_fee_check, - automation_mode: self.automation_mode, + execution_mode: self.execution_mode, } } @@ -349,8 +350,8 @@ impl + Copy> Cfg for CfgEnv { } } - fn is_automation_mode(&self) -> bool { - self.automation_mode + fn execution_mode(&self) -> &ExecutionMode { + &self.execution_mode } } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 6012dc41b2..65702d7996 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -27,7 +27,7 @@ use primitives::{ constants::CALL_STACK_LIMIT, hardfork::SpecId::{self, HOMESTEAD, LONDON, SPURIOUS_DRAGON}, }; -use primitives::{keccak256, Address, Bytes, B256, U256}; +use primitives::{keccak256, Address, Bytes, U256}; use state::Bytecode; use std::borrow::ToOwned; use std::boxed::Box; @@ -279,7 +279,7 @@ impl EthFrame { inputs: Box, ) -> Result, ERROR> { let spec = context.cfg().spec().into(); - let is_automation = context.cfg().is_automation_mode(); + let should_update_nonce = context.cfg().execution_mode().updates_nonce(); let return_error = |e| { Ok(ItemOrResult::Result(FrameResult::Create(CreateOutcome { result: InterpreterResult { @@ -310,7 +310,7 @@ impl EthFrame { return return_error(InstructionResult::OutOfFunds); } let old_nonce = caller_info.nonce; - if !is_automation { + if should_update_nonce { // Increase nonce of caller and check if it overflows let Some(new_nonce) = old_nonce.checked_add(1) else { return return_error(InstructionResult::Return); diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index ad0c73ba96..09f0c1eb5e 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -12,6 +12,7 @@ use context_interface::{ }; use interpreter::interpreter_action::FrameInit; use interpreter::{Gas, InitialAndFloorGas, SharedMemory}; +use primitives::supra_constants::{is_supra_reserved, is_vm_signer}; use primitives::U256; /// Trait for errors that can occur during EVM execution. @@ -153,13 +154,16 @@ pub trait Handler { self.execution_result(evm, exec_result) } - /// Validates the execution environment and transaction parameters. + /// Validates the execution environment, transaction parameters and caller address. + /// + /// The transaction caller is verified to not be one of the SUPRA reserved addresses for user transactions. /// /// Calculates initial and floor gas requirements and verifies they are covered by the gas limit. /// /// Validation against state is done later in pre-execution phase in deduct_caller function. #[inline] fn validate(&self, evm: &mut Self::Evm) -> Result { + self.validate_caller(evm)?; self.validate_env(evm)?; self.validate_initial_tx_gas(evm) } @@ -242,6 +246,30 @@ pub trait Handler { validation::validate_env(evm.ctx()) } + /// Validates caller, to reject user transactions having caller address matching any of + /// the SUPRA reserved addresses. + #[inline] + fn validate_caller(&self, evm: &Self::Evm) -> Result<(), Self::Error> { + let ctx = evm.ctx_ref(); + let execution_mode = ctx.cfg().execution_mode(); + let caller = ctx.tx().caller(); + // Supra reserved address is allowed either in system execution mode or in genesis + if is_supra_reserved(&caller) + && !(execution_mode.is_system() || execution_mode.is_genesis()) + { + Err(Self::Error::from_string(format!( + "Invalid caller: supra reserved address. TxnHash {}", + ctx.tx().tx_hash() + ))) + } else if !is_vm_signer(&caller) && execution_mode.is_system() { + Err(Self::Error::from_string(String::from( + "Invalid caller: Expected VM_SIGNER as caller for system transactions.", + ))) + } else { + Ok(()) + } + } + /// Calculates initial gas costs based on transaction type and input data. /// /// Includes additional costs for access list and authorization list. diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index b69e469c04..9a3ac75ad6 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -114,12 +114,13 @@ pub fn validate_against_state_and_deduct_caller< >( context: &mut CTX, ) -> Result<(), ERROR> { - let automation_mode = context.cfg().is_automation_mode(); + let should_update_nonce = context.cfg().execution_mode().updates_nonce(); let basefee = context.block().basefee() as u128; let blob_price = context.block().blob_gasprice().unwrap_or_default(); let is_balance_check_disabled = context.cfg().is_balance_check_disabled(); let is_eip3607_disabled = context.cfg().is_eip3607_disabled(); - let is_nonce_check_disabled = context.cfg().is_nonce_check_disabled(); + // nonce check will not be done if it is disabled, or execution mode does not assume nonce-change. + let is_nonce_check_disabled = context.cfg().is_nonce_check_disabled() || !should_update_nonce; let (tx, journal) = context.tx_journal_mut(); @@ -167,7 +168,7 @@ pub fn validate_against_state_and_deduct_caller< caller_account.mark_touch(); caller_account.info.balance = new_balance; - if !automation_mode { + if should_update_nonce { // Bump the nonce for calls. Nonce for CREATE will be bumped in `make_create_frame`. if tx.kind().is_call() { // Nonce is already checked diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index eb75bf6135..a2b90f5bcb 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -19,7 +19,7 @@ pub trait PrecompileProvider { /// Returned booling will determine if precompile addresses should be injected into the journal. fn set_spec(&mut self, spec: ::Spec) -> bool; - /// Run the precompile. + /// Run precompile. fn run( &mut self, context: &mut CTX, diff --git a/crates/primitives/src/supra_constants.rs b/crates/primitives/src/supra_constants.rs index 714f60f89d..8d31e47c35 100644 --- a/crates/primitives/src/supra_constants.rs +++ b/crates/primitives/src/supra_constants.rs @@ -1,5 +1,50 @@ -//! Global constants for Supra EVM -use alloy_primitives::{address, Address}; +//! Constants defined by SUPRA to facilitate execution flow extensions. +use alloy_primitives::Address; -/// Address of TX_HASH precompile -pub const TX_HASH_ADDRESS: Address = address!("0x0000000000000000000000000000000053555001"); +/// Converts [`u64`] to [`Address`] type. +pub const fn u64_to_address(x: u64) -> Address { + let x = x.to_be_bytes(); + Address::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], + ]) +} + +/// Supra Reserved address for VM SIGNER, +pub const VM_SIGNER: Address = u64_to_address(0x5355_5000); + +/// Supra Reserved address Precompile address to retrieve transaction hash +pub const TX_HASH_ADDRESS: Address = u64_to_address(0x5355_5001); + +/// [0x5355_5000, 0x53555_50FF] addresses are reserved as SUPRA special addresses. +const SUPRA_RESERVED_ADDRESSES_PREFIX_UPPER_BOUND: usize = 19; + +/// Checks whether specified input address is one of the SUPRA reserved ones. +pub fn is_supra_reserved(address: &Address) -> bool { + VM_SIGNER[..SUPRA_RESERVED_ADDRESSES_PREFIX_UPPER_BOUND] + .eq(&address[..SUPRA_RESERVED_ADDRESSES_PREFIX_UPPER_BOUND]) +} + +/// Checks whether specified input address is SUPRA reserved VM_SIGNER +pub fn is_vm_signer(address: &Address) -> bool { + VM_SIGNER.eq(address) +} + +#[cfg(test)] +mod tests { + use crate::supra_constants::{is_supra_reserved, TX_HASH_ADDRESS, VM_SIGNER}; + + #[test] + fn check_reserved_addresses() { + let addr5 = super::u64_to_address(0x5355_5005); + let last_reserved = super::u64_to_address(0x5355_50ff); + let any_low_address = super::u64_to_address(0x5355_4fff); + let any_up_address = super::u64_to_address(0x5355_5100); + let any_address = super::u64_to_address(0x1_5355_5000); + assert!(is_supra_reserved(&addr5)); + assert!(is_supra_reserved(&VM_SIGNER)); + assert!(is_supra_reserved(&TX_HASH_ADDRESS)); + assert!(!is_supra_reserved(&any_address)); + assert!(!is_supra_reserved(&any_low_address)); + assert!(!is_supra_reserved(&any_up_address)); + } +} diff --git a/crates/supra-extension/Cargo.toml b/crates/supra-extension/Cargo.toml new file mode 100644 index 0000000000..cb4af162f3 --- /dev/null +++ b/crates/supra-extension/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "revm-supra-extension" +version = "0.1.0" +license.workspace = true +authors.workspace = true +categories.workspace = true +keywords.workspace = true +repository.workspace = true +documentation.workspace = true +homepage.workspace = true +edition.workspace = true +rust-version.workspace = true + +[dependencies] +alloy-sol-types = { workspace = true } +alloy-contract = { workspace = true } +alloy-consensus = { workspace = true } +alloy-eips = { workspace = true } +serde = { workspace = true } +alloy = { workspace = true } +derive_more = { workspace = true, features = ["full"] } +derive-getters = { workspace = true } +thiserror = { workspace = true } +primitives = { workspace = true } +context = { workspace = true } +alloy-serde = {workspace = true, optional = true } +anyhow = { workspace = true } +foundry-compilers = { workspace = true } +serde_json = { workspace = true } + +[lints] +workspace = true + + +[build-dependencies] +#forge = { workspace = true } +#clap = { workspace = true } +#shlex = { workspace = true } +foundry-compilers = { workspace = true } +anyhow = { workspace = true } +toml = { workspace = true } +serde = {workspace = true } + +[features] +serde = ["alloy-serde"] diff --git a/crates/supra-extension/build.rs b/crates/supra-extension/build.rs new file mode 100644 index 0000000000..978e60d299 --- /dev/null +++ b/crates/supra-extension/build.rs @@ -0,0 +1,131 @@ +//! Prepares supra-extension by compiling smart-contracts and building rust bindings + +use anyhow::Result; +use foundry_compilers::artifacts::Remapping; +use foundry_compilers::multi::MultiCompilerSettings; +use foundry_compilers::solc::SolcSettings; +use foundry_compilers::{utils, Project, ProjectPathsConfig}; +use serde::{Deserialize, Serialize}; +use std::env; +use std::path::Path; +use std::path::PathBuf; + +const CURRENT_DIR: &str = env!("CARGO_MANIFEST_DIR"); + +fn rebuild_rust_bindings() { + // 1. Tell Cargo to rerun the script if the contracts directory changes + let cargo_dir = PathBuf::from(CURRENT_DIR); + println!( + "cargo:rerun-if-changed={}/../../solidity/supra_contracts/src/SupraContractsBindings.sol", + cargo_dir.display() + ); + + // smr-moonshot referencing this version of the REVM has dependency conflicts caused by syn library used by forge. + // So unless the issue is fixed, rust bindings on updates of the SupraContractsBindings.sol will be regenerated manually + // and committed. This code should remain commented out otherwise + // To do it: + // - uncomment below code + // - uncomment build dependencies in Cargo.toml file of this project + // - uncomment forge library reference in top level Cargo.toml file + // - build the project + + //// Determine the output directory for the generated bindings + //use clap::Parser; + //use forge::cmd::bind::BindArgs; + //let contracts_relative_path = PathBuf::from("../../solidity/supra_contracts"); + //let contracts_build_config = + // cargo_dir.join(contracts_relative_path.join(PathBuf::from("foundry.toml"))); + //let contract_names = "SupraContracts"; + + //let bindings_path = cargo_dir + // .join(PathBuf::from("src")) + // .join(PathBuf::from("supra_contract_bindings")); + + //// Ensure the output directory exists + //std::fs::create_dir_all(bindings_path.as_path()).expect("Failed to create bindings directory"); + //let command_inputs = format!( + // "bind --bindings-path {} --overwrite --module --select {} --alloy --config-path {}", + // bindings_path.display(), + // contract_names, + // contracts_build_config.display() + //); + //let parsed_inputs = shlex::split(&command_inputs).expect("Failed to parse command string"); + //let bind_cmd: BindArgs = + // BindArgs::try_parse_from(parsed_inputs).expect("Failed to parse command arguments"); + //bind_cmd.run().expect("Failed to execute bind command"); +} + +#[derive(Serialize, Deserialize, Debug)] +struct CompileConfig { + dapp_relative_path: PathBuf, + solc_settings: SolcSettings, + #[serde(default)] + remappings: Vec<(String, String)>, +} + +impl CompileConfig { + fn load() -> Result { + let path = Path::new(CURRENT_DIR).join("compile_config.toml"); + toml::from_str::(&std::fs::read_to_string(path)?) + .map_err(|e| e.into()) + .inspect_err(|e| println!("Error: {}", e)) + } + + fn dapp_path(&self) -> PathBuf { + utils::canonicalize(Path::new(CURRENT_DIR).join(&self.dapp_relative_path)) + .expect("failed to canonicalize dapp path") + } + + fn remappings(&self) -> Vec { + self.remappings + .iter() + .map(|(name, rel_path)| Remapping { + context: None, + name: name.clone(), + path: self + .dapp_path() + .join(rel_path) + .to_string_lossy() + .into_owned(), + }) + .collect() + } + + fn to_multi_compiler_settings(self) -> MultiCompilerSettings { + let mut settings = MultiCompilerSettings::default(); + settings.solc = self.solc_settings; + settings + } +} + +fn compile_contracts() -> Result<()> { + let config = CompileConfig::load()?; + + let mut paths = ProjectPathsConfig::dapptools(&config.dapp_path())?; + for (idx, value) in config.remappings().into_iter().enumerate() { + paths.remappings.insert(idx, value) + } + + let project = Project::builder() + .paths(paths) + .settings(config.to_multi_compiler_settings()) + .build(Default::default())?; + let output = project.compile()?; + let _ = output.succeeded(); + // Tell Cargo that if a source file changes, to rerun this build script. + project.rerun_if_sources_changed(); + println!("cargo:rerun-if-changed={}/compile_config.toml", CURRENT_DIR); + println!( + "cargo:rustc-env=COMPILED_CONTRACTS_DIR={}", + project.paths.artifacts.display() + ); + + Ok(()) +} + +fn main() { + rebuild_rust_bindings(); + compile_contracts() + .inspect_err(|e| panic!("{e:?}")) + .unwrap() +} diff --git a/crates/supra-extension/compile_config.toml b/crates/supra-extension/compile_config.toml new file mode 100644 index 0000000000..e43581cc69 --- /dev/null +++ b/crates/supra-extension/compile_config.toml @@ -0,0 +1,14 @@ +dapp_relative_path = "../../solidity/supra_contracts/" +remappings = [["@openzeppelin/contracts/", "lib/openzeppelin-contracts/contracts/"]] + +[solc_settings] +evmVersion = "prague" +viaIR = true + +[solc_settings.optimizer] +enabled = true +runs = 200 + +[solc_settings.outputSelection."*"] +"" = ["ast"] +"*" = ["abi", "evm.bytecode.object"] diff --git a/crates/supra-extension/src/contracts/configs.rs b/crates/supra-extension/src/contracts/configs.rs new file mode 100644 index 0000000000..58f6a4f5a6 --- /dev/null +++ b/crates/supra-extension/src/contracts/configs.rs @@ -0,0 +1,93 @@ +//! Configurations to generate genesis transactions + +use primitives::Address; + +/// Configuration parameters for Automation Registry contracts initialization +#[derive(Debug, Clone)] +pub struct AutomationRegistryConfigV1 { + /// Maximum allowable duration (in seconds) from the registration time that a user automation task can run. + pub task_duration_cap_secs: u64, + /// Maximum gas allocation for automation tasks per cycle. + pub registry_max_gas_cap: u128, + /// Base fee per second for the full capacity of the automation registry, measured in wei/sec. + pub automation_base_fee_wei_per_sec: u128, + /// Flat registration fee charged by default for each task. + pub flat_registration_fee_wei: u128, + /// Percentage representing the acceptable upper limit of committed gas amount relative to registry_max_gas_cap. + pub congestion_threshold_percentage: u8, + /// Base fee per second for the full capacity of the automation registry when the congestion threshold is exceeded. + pub congestion_base_fee_wei_per_sec: u128, + /// The congestion fee increases exponentially based on this value. + pub congestion_exponent: u8, + /// Maximum number of tasks that the registry can hold. + pub task_capacity: u16, + /// Automation cycle duration in seconds. + pub cycle_duration_secs: u64, + /// Maximum allowable duration (in seconds) from the registration time that a system automation task can run. + pub sys_task_duration_cap_secs: u64, + /// Maximum gas allocation for system automation tasks per cycle. + pub sys_registry_max_gas_cap: u128, + /// Maximum number of system tasks that the registry can hold. + pub sys_task_capacity: u16, + /// Indicates whether the automation feature is enabled at startup + pub enable_automation_feature: bool, +} + +impl Default for AutomationRegistryConfigV1 { + fn default() -> Self { + Self { + // 7 days + task_duration_cap_secs: 604800, + registry_max_gas_cap: 8_000_000, + // 0.004 SUPRA normalized based on the supra denominator between move and evm currency + automation_base_fee_wei_per_sec: 1_714_530_600_000, + // 0.05 SUPRA normalized based on the supra denominator between move and evm currency + flat_registration_fee_wei: 21_431_633_000_000, + congestion_threshold_percentage: 50, + // 0.004 SUPRA normalized based on the supra denominator between move and evm currency + congestion_base_fee_wei_per_sec: 1_714_530_600_000, + congestion_exponent: 6, + task_capacity: 400, + cycle_duration_secs: 600, + // ~1 month + sys_task_duration_cap_secs: 2626560, + sys_registry_max_gas_cap: 2_000_000, + sys_task_capacity: 100, + enable_automation_feature: true, + } + } +} + +/// Configuration parameters for Automation Registry contracts initialization +#[derive(Debug, Clone)] +pub enum AutomationRegistryConfig { + /// First version of the evm automation registry contract configurations + V1(AutomationRegistryConfigV1), +} + +impl AutomationRegistryConfig { + /// Returns [AutomationRegistryConfigV1] if the variant is [Self::V1] + pub fn v1(&self) -> Option<&AutomationRegistryConfigV1> { + let Self::V1(config) = self; + Some(config) + } +} + +impl From for AutomationRegistryConfig { + fn from(config: AutomationRegistryConfigV1) -> Self { + Self::V1(config) + } +} + +/// Genesis Transaction generator configuration details +#[derive(Debug, Clone)] +pub struct GenesisTransactionGeneratorConfig { + /// List of EOAs to set up multisig foundation wallet. + pub foundation_owners: Vec
, + /// Threshold of the foundation multisig wallet. + pub foundation_threshold: u64, + /// Flag indicating whether full set of genesis transaction should be generated or only mandatory once. + pub full_set: bool, + /// Automation configuration parameters (optional, uses defaults if None). + pub automation_config: Option, +} diff --git a/crates/supra-extension/src/contracts/generator.rs b/crates/supra-extension/src/contracts/generator.rs new file mode 100644 index 0000000000..60ce08f3f2 --- /dev/null +++ b/crates/supra-extension/src/contracts/generator.rs @@ -0,0 +1,635 @@ +//! Encloses transaction data generation logic based on the genesis contracts + +use crate::contracts::configs::{AutomationRegistryConfig, GenesisTransactionGeneratorConfig}; +use crate::contracts::transaction::{GenesisTransaction, GenesisTransactionTags}; +use alloy::primitives::Address; +use alloy_sol_types::{sol, SolCall, SolConstructor}; +use anyhow::{anyhow, Result}; +use foundry_compilers::artifacts::ContractBytecode; +use primitives::supra_constants::VM_SIGNER; +use primitives::{Bytes, U256}; +use std::collections::BTreeMap; +use std::fs::File; +use std::io::BufReader; +use std::path::Path; + +/// Output path of the compiled smart contracts, exported by build script. +const OUTPUT_PATH: &str = env!("COMPILED_CONTRACTS_DIR"); + +/////////////// Multi-Signature-Wallet related contracts and init APIs ///////////////////////////// +const MULTISIG_WALLET: &str = "MultiSignatureWallet"; +const MULTISIG_BEACON: &str = "MultisigBeacon"; +const BEACON_PROXY: &str = "BeaconProxy"; + +sol! { + contract MultiSignatureWallet { + function initialize(address[] memory _owners, uint256 _numConfirmationsRequired); + } +} + +sol! { + contract MultisigBeacon { + constructor(address _implementation, address _owner); + } +} + +sol! { + contract BeaconProxy { + constructor(address _beacon, bytes _data); + } +} + +///////////////////// ERC20Supra related contracts and init APIs ///////////////////////////// +const ERC20_SUPRA: &str = "ERC20Supra"; +sol! { + contract ERC20Supra { + constructor(address _initialOwner); + } +} + +///////////////////// Block Meta related contracts and init APIs ///////////////////////////// +const BLOCK_META: &str = "BlockMeta"; +sol! { + contract BlockMeta { + function initialize(address _initialOwner); + } +} + +const ERC1967PROXY: &str = "ERC1967Proxy"; + +sol! { + contract ERC1967Proxy { + constructor(address _impl, bytes _data); + } +} + +///////////////////// Automation related contracts and init APIs ///////////////////////////// + +const AUTOMATION_CORE: &str = "AutomationCore"; +const AUTOMATION_REGISTRY: &str = "AutomationRegistry"; +const AUTOMATION_CONTROLLER: &str = "AutomationController"; + +sol! { + /// Initialization parameters for AutomationCore contract. + struct InitializeParams { + uint64 taskDurationCapSecs; + uint128 registryMaxGasCap; + uint128 automationBaseFeeWeiPerSec; + uint128 flatRegistrationFeeWei; + uint8 congestionThresholdPercentage; + uint128 congestionBaseFeeWeiPerSec; + uint8 congestionExponent; + uint16 taskCapacity; + uint64 cycleDurationSecs; + uint64 sysTaskDurationCapSecs; + uint128 sysRegistryMaxGasCap; + uint16 sysTaskCapacity; + address vmSigner; + address erc20Supra; + address controller; + address registry; + address owner; + } + + /// AutomationCore is a UUPS upgradeable contract - constructor has no parameters. + /// Deployed behind ERC1967Proxy. + contract AutomationCore { + constructor(); + function initialize(InitializeParams calldata params); + } + + /// AutomationRegistry is a UUPS upgradeable contract - constructor has no parameters. + /// Deployed behind ERC1967Proxy. + contract AutomationRegistry { + constructor(); + function initialize(address _automationCore, address _automationController, address _owner); + } + + /// AutomationController is a UUPS upgradeable contract - constructor has no parameters. + /// Deployed behind ERC1967Proxy. + contract AutomationController { + constructor(); + function initialize(address _automationCore, address _registry, address _owner, bool _automationEnabled, uint64 _cycleDurationSecs); + } +} + +/// Genesis Transaction generator using configured address as transaction owner. +/// It provides means to generate minimal mandatory set of genesis transactions to set up evm state, +/// and conditionally generates non-mandatory set of transactions. +#[derive(Debug)] +pub struct GenesisTransactionGenerator { + nonce: u64, + address: Address, +} + +impl Default for GenesisTransactionGenerator { + fn default() -> Self { + Self::new(VM_SIGNER) + } +} + +impl GenesisTransactionGenerator { + fn new(address: Address) -> Self { + Self::new_with_nonce(address, 0) + } + + fn new_with_nonce(address: Address, nonce: u64) -> Self { + Self { nonce, address } + } + + /// Prepares genesis transactions based on the input configuration. + pub fn prepare_genesis_transactions( + &mut self, + config: GenesisTransactionGeneratorConfig, + ) -> Result> { + let GenesisTransactionGeneratorConfig { + foundation_owners, + foundation_threshold, + full_set, + automation_config, + } = config; + // First foundation multisig account setup should be done + let mut genesis_transactions = + self.setup_multisig_wallet(foundation_owners, foundation_threshold)?; + if full_set { + let multisig_address = *genesis_transactions + .get(&GenesisTransactionTags::FoundationWallet) + .expect("Foundation Wallet deployment transaction") + .deploy_address(); + let erc20_supra_txn = self.setup_erc20_supra(multisig_address)?; + let erc20_supra_address = *erc20_supra_txn.deploy_address(); + genesis_transactions.insert(GenesisTransactionTags::Erc20Supra, erc20_supra_txn); + genesis_transactions.extend(self.setup_block_metadata(multisig_address)?.into_iter()); + if let Some(config) = automation_config { + genesis_transactions.extend( + self.setup_automation_registry(multisig_address, erc20_supra_address, config)? + .into_iter(), + ); + } + }; + + Ok(genesis_transactions) + } + + /// Generates genesis transactions for foundation multisig wallet deployment. + /// Deployment order follows GenesisTransactionTags: + /// 1. MultisigWalletImpl (0) - MultiSignatureWallet implementation contract + /// 2. MultisigBeacon (1) - Beacon contract pointing to implementation + /// 3. FoundationWallet (2) - BeaconProxy with initialize(owners, threshold) + /// + /// The beacon pattern allows future upgrades by changing the implementation + /// address in the beacon contract. The foundation wallet (BeaconProxy) will + /// automatically use the new implementation. + fn setup_multisig_wallet( + &mut self, + owners: Vec
, + threshold: u64, + ) -> Result> { + // ------------------------------------------------------------------------- + // Pre-compute all deployment addresses + // nonce+0: MultiSignatureWallet implementation + // nonce+1: MultisigBeacon + // nonce+2: BeaconProxy (Foundation Wallet) + // ------------------------------------------------------------------------- + let multisig_impl_address = self.address.create(self.nonce); + let beacon_contract_address = self.address.create(self.nonce + 1); + let multisig_wallet_address = self.address.create(self.nonce + 2); + + // ------------------------------------------------------------------------- + // 1. Deploy MultiSignatureWallet implementation (no constructor args) + // ------------------------------------------------------------------------- + let multisig_impl_create_data = Self::load_contract_bytecode(MULTISIG_WALLET)?; + let multisig_txn = GenesisTransaction::new( + self.address.clone(), + multisig_impl_create_data, + self.nonce, + multisig_impl_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 2. Deploy MultisigBeacon + // Constructor args: implementation address, owner (the wallet itself) + // The beacon owner is set to the wallet address for self-governance + // ------------------------------------------------------------------------- + let multisig_beacon_create_data = Self::load_contract_bytecode(MULTISIG_BEACON)?; + let beacon_args = MultisigBeacon::constructorCall { + _implementation: multisig_impl_address, + _owner: multisig_wallet_address, + } + .abi_encode(); + let beacon_txn_data = [multisig_beacon_create_data, beacon_args].concat(); + let multisig_beacon_txn = GenesisTransaction::new( + self.address.clone(), + beacon_txn_data, + self.nonce, + beacon_contract_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 3. Deploy BeaconProxy (Foundation Wallet) + // Constructor args: beacon address, initialization data + // Initialization data: initialize(owners[], threshold) + // ------------------------------------------------------------------------- + let beacon_proxy_create_data = Self::load_contract_bytecode(BEACON_PROXY)?; + // Encode the initialize call data for MultiSignatureWallet + let multisig_init_data = MultiSignatureWallet::initializeCall { + _owners: owners, + _numConfirmationsRequired: U256::from(threshold), + } + .abi_encode(); + // Encode the BeaconProxy constructor args + let beacon_proxy_args = BeaconProxy::constructorCall { + _beacon: beacon_contract_address, + _data: Bytes::from(multisig_init_data), + } + .abi_encode(); + // Concatenate bytecode + constructor args for deployment + let beacon_proxy_txn_data = [beacon_proxy_create_data, beacon_proxy_args].concat(); + let beacon_proxy_txn = GenesisTransaction::new( + self.address.clone(), + beacon_proxy_txn_data, + self.nonce, + multisig_wallet_address, + ); + self.nonce += 1; + + Ok(BTreeMap::from([ + (GenesisTransactionTags::MultisigWalletImpl, multisig_txn), + (GenesisTransactionTags::MultisigBeacon, multisig_beacon_txn), + (GenesisTransactionTags::FoundationWallet, beacon_proxy_txn), + ])) + } + + /// Generates genesis transaction for ERC20Supra token contract deployment. + /// Deployment order follows GenesisTransactionTags: + /// 1. Erc20Supra (3) - ERC20 token contract with constructor(initialOwner) + /// + /// This is a non-upgradeable contract deployed directly (not behind a proxy). + /// The initial owner (typically the foundation multisig wallet) receives + /// administrative privileges over the token contract. + fn setup_erc20_supra(&mut self, initial_owner: Address) -> Result { + // ------------------------------------------------------------------------- + // Pre-compute deployment address + // ------------------------------------------------------------------------- + let contract_address = self.address.create(self.nonce); + + // ------------------------------------------------------------------------- + // Deploy ERC20Supra + // Constructor args: initial owner address + // ------------------------------------------------------------------------- + let erc20_contract_create_data = Self::load_contract_bytecode(ERC20_SUPRA)?; + // Encode the constructor args + let erc20_constructor_args = ERC20Supra::constructorCall { + _initialOwner: initial_owner, + } + .abi_encode(); + // Concatenate bytecode + constructor args for deployment + let erc20_txn_data = [erc20_contract_create_data, erc20_constructor_args].concat(); + let txn = + GenesisTransaction::new(self.address, erc20_txn_data, self.nonce, contract_address); + self.nonce += 1; + + Ok(txn) + } + + /// Generates genesis transactions for BlockMeta contract deployment. + /// Deployment order follows GenesisTransactionTags: + /// 1. BlockMetadataImpl (4) - BlockMeta implementation contract (UUPS upgradeable) + /// 2. BlockMetadata (5) - ERC1967Proxy with initialize(initialOwner) + /// + /// BlockMeta is a UUPS upgradeable contract deployed behind an ERC1967Proxy. + /// The proxy pattern allows future upgrades while maintaining the same address. + fn setup_block_metadata( + &mut self, + initial_owner: Address, + ) -> Result> { + // ------------------------------------------------------------------------- + // Pre-compute all deployment addresses + // nonce+0: BlockMeta implementation + // nonce+1: ERC1967Proxy (BlockMetadata) + // ------------------------------------------------------------------------- + let block_metadata_impl_address = self.address.create(self.nonce); + let block_metadata_proxy_address = self.address.create(self.nonce + 1); + + // ------------------------------------------------------------------------- + // 1. Deploy BlockMeta implementation (UUPS - no constructor args) + // ------------------------------------------------------------------------- + let block_metadata_impl = Self::load_contract_bytecode(BLOCK_META)?; + let block_metadata_impl_txn = GenesisTransaction::new( + self.address, + block_metadata_impl, + self.nonce, + block_metadata_impl_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 2. Deploy ERC1967Proxy (BlockMetadata) + // Constructor args: implementation address, initialization data + // Initialization data: initialize(initialOwner) + // ------------------------------------------------------------------------- + let proxy_impl_data = Self::load_contract_bytecode(ERC1967PROXY)?; + // Encode the initialize call data for BlockMeta + let block_metadata_initialize = BlockMeta::initializeCall { + _initialOwner: initial_owner, + } + .abi_encode(); + // Encode the ERC1967Proxy constructor args + let proxy_args = ERC1967Proxy::constructorCall { + _impl: block_metadata_impl_address, + _data: block_metadata_initialize.into(), + } + .abi_encode(); + // Concatenate bytecode + constructor args for deployment + let proxy_txn_data = [proxy_impl_data, proxy_args].concat(); + let block_metadata_proxy_txn = GenesisTransaction::new( + self.address, + proxy_txn_data, + self.nonce, + block_metadata_proxy_address, + ); + self.nonce += 1; + + Ok(BTreeMap::from([ + ( + GenesisTransactionTags::BlockMetadataImpl, + block_metadata_impl_txn, + ), + ( + GenesisTransactionTags::BlockMetadata, + block_metadata_proxy_txn, + ), + ])) + } + + /// Generates genesis transactions for automation contracts deployment. + /// Deployment order follows GenesisTransactionTags: + /// 1. AutomationControllerImpl - implementation contract + /// 2. AutomationController - ERC1967Proxy with initialize(automationCore, registry) + /// 3. AutomationCoreImpl - implementation contract + /// 4. AutomationCore - ERC1967Proxy with initialize(InitializeParams) + /// 5. AutomationRegistryImpl - implementation contract + /// 6. AutomationRegistry - ERC1967Proxy with initialize(automationCore, automationController) + /// + /// All proxy addresses are pre-computed before deployment to handle circular dependencies. + fn setup_automation_registry( + &mut self, + owner: Address, + erc20_supra_address: Address, + registry_config: AutomationRegistryConfig, + ) -> Result> { + let config = registry_config + .v1() + .ok_or_else(|| anyhow!("Unhandled configuration version"))?; + // Pre-compute all deployment addresses + // nonce+0: AutomationCoreImpl + // nonce+1: AutomationCore (proxy) + // nonce+2: AutomationRegistryImpl + // nonce+3: AutomationRegistry (proxy) + // nonce+4: AutomationControllerImpl + // nonce+5: AutomationController (proxy) + let core_impl_address = self.address.create(self.nonce); + let core_proxy_address = self.address.create(self.nonce + 1); + let registry_impl_address = self.address.create(self.nonce + 2); + let registry_proxy_address = self.address.create(self.nonce + 3); + let controller_impl_address = self.address.create(self.nonce + 4); + let controller_proxy_address = self.address.create(self.nonce + 5); + + let proxy_bytecode = Self::load_contract_bytecode(ERC1967PROXY)?; + + // ------------------------------------------------------------------------- + // 1. Deploy AutomationCoreImpl (UUPS - no constructor args) + // ------------------------------------------------------------------------- + let core_impl_bytecode = Self::load_contract_bytecode(AUTOMATION_CORE)?; + let core_impl_txn = GenesisTransaction::new( + self.address, + core_impl_bytecode, + self.nonce, + core_impl_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 2. Deploy AutomationCore proxy + // ------------------------------------------------------------------------- + let core_init_params = InitializeParams { + taskDurationCapSecs: config.task_duration_cap_secs, + registryMaxGasCap: config.registry_max_gas_cap, + automationBaseFeeWeiPerSec: config.automation_base_fee_wei_per_sec, + flatRegistrationFeeWei: config.flat_registration_fee_wei, + congestionThresholdPercentage: config.congestion_threshold_percentage, + congestionBaseFeeWeiPerSec: config.congestion_base_fee_wei_per_sec, + congestionExponent: config.congestion_exponent, + taskCapacity: config.task_capacity, + cycleDurationSecs: config.cycle_duration_secs, + sysTaskDurationCapSecs: config.sys_task_duration_cap_secs, + sysRegistryMaxGasCap: config.sys_registry_max_gas_cap, + sysTaskCapacity: config.sys_task_capacity, + vmSigner: VM_SIGNER, + erc20Supra: erc20_supra_address, + controller: controller_proxy_address, + registry: registry_proxy_address, + owner, + }; + let core_init_data = AutomationCore::initializeCall { + params: core_init_params, + } + .abi_encode(); + let core_proxy_args = ERC1967Proxy::constructorCall { + _impl: core_impl_address, + _data: Bytes::from(core_init_data), + } + .abi_encode(); + let core_proxy_txn_data = [proxy_bytecode.clone(), core_proxy_args].concat(); + let core_proxy_txn = GenesisTransaction::new( + self.address, + core_proxy_txn_data, + self.nonce, + core_proxy_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 3. Deploy AutomationRegistryImpl (UUPS - no constructor args) + // ------------------------------------------------------------------------- + let registry_impl_bytecode = Self::load_contract_bytecode(AUTOMATION_REGISTRY)?; + let registry_impl_txn = GenesisTransaction::new( + self.address, + registry_impl_bytecode, + self.nonce, + registry_impl_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 4. Deploy AutomationRegistry proxy + // ------------------------------------------------------------------------- + let registry_init_data = AutomationRegistry::initializeCall { + _automationCore: core_proxy_address, + _automationController: controller_proxy_address, + _owner: owner, + } + .abi_encode(); + let registry_proxy_args = ERC1967Proxy::constructorCall { + _impl: registry_impl_address, + _data: Bytes::from(registry_init_data), + } + .abi_encode(); + let registry_proxy_txn_data = [proxy_bytecode.clone(), registry_proxy_args].concat(); + let registry_proxy_txn = GenesisTransaction::new( + self.address, + registry_proxy_txn_data, + self.nonce, + registry_proxy_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 5. Deploy AutomationControllerImpl (UUPS - no constructor args) + // ------------------------------------------------------------------------- + let controller_impl_bytecode = Self::load_contract_bytecode(AUTOMATION_CONTROLLER)?; + let controller_impl_txn = GenesisTransaction::new( + self.address, + controller_impl_bytecode, + self.nonce, + controller_impl_address, + ); + self.nonce += 1; + + // ------------------------------------------------------------------------- + // 6. Deploy AutomationController proxy + // ------------------------------------------------------------------------- + let controller_init_data = AutomationController::initializeCall { + _automationCore: core_proxy_address, + _registry: registry_proxy_address, + _owner: owner, + _automationEnabled: config.enable_automation_feature, + _cycleDurationSecs: config.cycle_duration_secs, + } + .abi_encode(); + let controller_proxy_args = ERC1967Proxy::constructorCall { + _impl: controller_impl_address, + _data: Bytes::from(controller_init_data), + } + .abi_encode(); + let controller_proxy_txn_data = [proxy_bytecode, controller_proxy_args].concat(); + let controller_proxy_txn = GenesisTransaction::new( + self.address, + controller_proxy_txn_data, + self.nonce, + controller_proxy_address, + ); + self.nonce += 1; + + Ok(BTreeMap::from([ + ( + GenesisTransactionTags::AutomationControllerImpl, + controller_impl_txn, + ), + ( + GenesisTransactionTags::AutomationController, + controller_proxy_txn, + ), + (GenesisTransactionTags::AutomationCoreImpl, core_impl_txn), + (GenesisTransactionTags::AutomationCore, core_proxy_txn), + ( + GenesisTransactionTags::AutomationRegistryImpl, + registry_impl_txn, + ), + ( + GenesisTransactionTags::AutomationRegistry, + registry_proxy_txn, + ), + ])) + } + + fn load_contract_bytecode(name: &str) -> Result> { + let path = Path::new(OUTPUT_PATH) + .join(format!("{name}.sol")) + .join(format!("{name}.json")); + let file = File::open(&path)?; + let buf_reader = BufReader::new(file); + let contract: ContractBytecode = serde_json::from_reader(buf_reader)?; + contract + .bytecode + .and_then(|b| b.bytes().cloned()) + .map(|b| b.to_vec()) + .filter(|b| !b.is_empty()) + .ok_or_else(|| anyhow!("Failed to load bytecode for contract: {name}")) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::contracts::configs::AutomationRegistryConfigV1; + use primitives::supra_constants::u64_to_address; + + #[test] + fn check_multisig_setup() { + let mut generator = GenesisTransactionGenerator::default(); + let owners = vec![u64_to_address(1), u64_to_address(2), u64_to_address(3)]; + let mut config = GenesisTransactionGeneratorConfig { + foundation_owners: owners, + foundation_threshold: 2, + full_set: false, + automation_config: None, + }; + let result = generator + .prepare_genesis_transactions(config.clone()) + .unwrap(); + assert_eq!(result.len(), 3); + assert!(result.contains_key(&GenesisTransactionTags::MultisigWalletImpl)); + assert!(result.contains_key(&GenesisTransactionTags::MultisigBeacon)); + assert!(result.contains_key(&GenesisTransactionTags::FoundationWallet)); + + // Enable full set of contract generation without automation config + config.full_set = true; + let result = generator + .prepare_genesis_transactions(config) + .expect("Successful txn generation"); + assert!(result.contains_key(&GenesisTransactionTags::FoundationWallet)); + assert!(result.contains_key(&GenesisTransactionTags::BlockMetadata)); + assert!(result.contains_key(&GenesisTransactionTags::Erc20Supra)); + // Verify automation contracts are not deployed + assert!(!result.contains_key(&GenesisTransactionTags::AutomationControllerImpl)); + assert!(!result.contains_key(&GenesisTransactionTags::AutomationController)); + assert!(!result.contains_key(&GenesisTransactionTags::AutomationCoreImpl)); + assert!(!result.contains_key(&GenesisTransactionTags::AutomationCore)); + assert!(!result.contains_key(&GenesisTransactionTags::AutomationRegistryImpl)); + assert!(!result.contains_key(&GenesisTransactionTags::AutomationRegistry)); + println!("{result:#?}"); + } + + #[test] + fn check_automation_with_custom_config() { + let mut generator = GenesisTransactionGenerator::default(); + let owners = vec![u64_to_address(1), u64_to_address(2), u64_to_address(3)]; + let custom_config = AutomationRegistryConfigV1 { + task_duration_cap_secs: 7200, + registry_max_gas_cap: 20_000_000, + task_capacity: 1000, + ..Default::default() + }; + let config = GenesisTransactionGeneratorConfig { + foundation_owners: owners, + foundation_threshold: 2, + full_set: true, + automation_config: Some(custom_config.into()), + }; + let result = generator + .prepare_genesis_transactions(config) + .expect("Successful txn generation"); + + // Verify all automation contracts are deployed + assert!(result.contains_key(&GenesisTransactionTags::AutomationControllerImpl)); + assert!(result.contains_key(&GenesisTransactionTags::AutomationController)); + assert!(result.contains_key(&GenesisTransactionTags::AutomationCoreImpl)); + assert!(result.contains_key(&GenesisTransactionTags::AutomationCore)); + assert!(result.contains_key(&GenesisTransactionTags::AutomationRegistryImpl)); + assert!(result.contains_key(&GenesisTransactionTags::AutomationRegistry)); + println!("{result:#?}"); + } +} diff --git a/crates/supra-extension/src/contracts/mod.rs b/crates/supra-extension/src/contracts/mod.rs new file mode 100644 index 0000000000..d6e3624b3c --- /dev/null +++ b/crates/supra-extension/src/contracts/mod.rs @@ -0,0 +1,5 @@ +//! Provides means to generate data for genesis contract deployment transactions + +pub mod configs; +pub mod generator; +pub mod transaction; diff --git a/crates/supra-extension/src/contracts/transaction.rs b/crates/supra-extension/src/contracts/transaction.rs new file mode 100644 index 0000000000..9eb8111010 --- /dev/null +++ b/crates/supra-extension/src/contracts/transaction.rs @@ -0,0 +1,44 @@ +//! Encloses data representing genesis contracts. + +use derive_getters::{Dissolve, Getters}; +use derive_more::Constructor; +use primitives::Address; +use std::fmt::Debug; + +/// Represents data required to construct genesis contracts deployment transaction +#[derive(Clone, Getters, Dissolve, Constructor)] +pub struct GenesisTransaction { + sender: Address, + data: Vec, + nonce: u64, + deploy_address: Address, +} + +impl Debug for GenesisTransaction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("GenesisTransaction") + .field("sender", &self.sender) + .field("data", &self.data.len()) + .field("nonce", &self.nonce) + .field("deploy_address", &self.deploy_address) + .finish() + } +} + +/// Genesis transaction tags which also guide deployment/execution order +#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[allow(missing_docs)] +pub enum GenesisTransactionTags { + MultisigWalletImpl = 0, + MultisigBeacon = 1, + FoundationWallet = 2, + Erc20Supra = 3, + BlockMetadataImpl = 4, + BlockMetadata = 5, + AutomationCoreImpl = 6, + AutomationCore = 7, + AutomationRegistryImpl = 8, + AutomationRegistry = 9, + AutomationControllerImpl = 10, + AutomationController = 11, +} diff --git a/crates/supra-extension/src/errors.rs b/crates/supra-extension/src/errors.rs new file mode 100644 index 0000000000..96ad0216f3 --- /dev/null +++ b/crates/supra-extension/src/errors.rs @@ -0,0 +1,39 @@ +//! Errors reported in scope of supra-extension module. + +use thiserror::Error; + +/// Supra-extension error. +#[derive(Error, Debug)] +pub enum SupraExtensionError { + /// Reported when transaction builder misses mandatory value to build final transaction. + #[error("Missing mandatory value: {0}::{1}")] + MissingBuilderValue(String, String), + + /// Reported on failure of automation task inner payload decode. + #[error("Failed to decode payload: {0}")] + PayloadDecode(#[from] alloy_sol_types::Error), + + /// Reported on failure of task state conversion to counterpart in native layer. + #[error("Invalid automation task state value: {0}, expected [0, 1, 2]")] + InvalidAutomationTaskStateValue(u8), + + /// Reported when automated transaction builder is attempted to be built for inactive task. + #[error("Attempt to create automated transaction builder for non-active task")] + InvalidAutomationTaskStateForBuilder, +} + +/// Extracts value of the optional value or reports [`SupraExtensionError::MissingBuilderValue`]. +#[macro_export] +macro_rules! value_or_error { + ($tpy:ty, $name:literal, $value:expr) => { + match $value { + Some(v) => v, + None => { + return Err($crate::errors::SupraExtensionError::MissingBuilderValue( + std::any::type_name::<$tpy>().to_string(), + $name.to_string(), + )); + } + } + }; +} diff --git a/crates/supra-extension/src/lib.rs b/crates/supra-extension/src/lib.rs new file mode 100644 index 0000000000..8a6b3bdc9b --- /dev/null +++ b/crates/supra-extension/src/lib.rs @@ -0,0 +1,9 @@ +//! # revm-supra-extension +//! Supra extensions of the transactions to support automation feature and block based checks + +pub mod contracts; +pub mod errors; +#[allow(missing_docs, missing_debug_implementations)] +#[allow(elided_lifetimes_in_paths)] +pub mod supra_contract_bindings; +pub mod transactions; diff --git a/crates/supra-extension/src/supra_contract_bindings/mod.rs b/crates/supra-extension/src/supra_contract_bindings/mod.rs new file mode 100644 index 0000000000..f95e49cc7a --- /dev/null +++ b/crates/supra-extension/src/supra_contract_bindings/mod.rs @@ -0,0 +1,6 @@ +#![allow(unused_imports, unused_attributes, clippy::all, rustdoc::all)] +//! This module contains the sol! generated bindings for solidity contracts. +//! This is autogenerated code. +//! Do not manually edit these files. +//! These files may be overwritten by the codegen system at any time. +pub mod r#supra_contracts_bindings; diff --git a/crates/supra-extension/src/supra_contract_bindings/supra_contracts_bindings.rs b/crates/supra-extension/src/supra_contract_bindings/supra_contracts_bindings.rs new file mode 100644 index 0000000000..58ecb64fb5 --- /dev/null +++ b/crates/supra-extension/src/supra_contract_bindings/supra_contracts_bindings.rs @@ -0,0 +1,3257 @@ +///Module containing a contract's types and functions. +/** + +```solidity +library CommonUtils { + type CycleState is uint8; + type TaskState is uint8; + struct TaskDetails { uint128 maxGasAmount; uint128 gasPriceCap; uint128 automationFeeCapForCycle; uint128 lockedFeeForNextCycle; bytes32 txHash; uint64 taskIndex; uint64 registrationTime; uint64 expiryTime; address owner; TaskState state; bytes payloadTx; bytes[] auxData; } +} +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod CommonUtils { + use super::*; + use alloy::sol_types as alloy_sol_types; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct CycleState(u8); + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for u8 { + #[inline] + fn stv_to_tokens( + &self, + ) -> as alloy_sol_types::SolType>::Token<'_> + { + alloy_sol_types::private::SolTypeValue::< + alloy::sol_types::sol_data::Uint<8>, + >::stv_to_tokens(self) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + as alloy_sol_types::SolType>::tokenize(self).0 + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + as alloy_sol_types::SolType>::abi_encode_packed_to(self, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + as alloy_sol_types::SolType>::abi_encoded_size( + self, + ) + } + } + impl CycleState { + /// The Solidity type name. + pub const NAME: &'static str = stringify!(@ name); + /// Convert from the underlying value type. + #[inline] + pub const fn from_underlying(value: u8) -> Self { + Self(value) + } + /// Return the underlying value. + #[inline] + pub const fn into_underlying(self) -> u8 { + self.0 + } + /// Return the single encoding of this value, delegating to the + /// underlying type. + #[inline] + pub fn abi_encode(&self) -> alloy_sol_types::private::Vec { + ::abi_encode(&self.0) + } + /// Return the packed encoding of this value, delegating to the + /// underlying type. + #[inline] + pub fn abi_encode_packed(&self) -> alloy_sol_types::private::Vec { + ::abi_encode_packed(&self.0) + } + } + #[automatically_derived] + impl From for CycleState { + fn from(value: u8) -> Self { + Self::from_underlying(value) + } + } + #[automatically_derived] + impl From for u8 { + fn from(value: CycleState) -> Self { + value.into_underlying() + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for CycleState { + type RustType = u8; + type Token<'a> = + as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = Self::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + Self::type_check(token).is_ok() + } + #[inline] + fn type_check(token: &Self::Token<'_>) -> alloy_sol_types::Result<()> { + as alloy_sol_types::SolType>::type_check(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + as alloy_sol_types::SolType>::detokenize(token) + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for CycleState { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + as alloy_sol_types::EventTopic>::topic_preimage_length(rust) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + as alloy_sol_types::EventTopic>::encode_topic_preimage(rust, out) + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + as alloy_sol_types::EventTopic>::encode_topic( + rust, + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct TaskState(u8); + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for u8 { + #[inline] + fn stv_to_tokens( + &self, + ) -> as alloy_sol_types::SolType>::Token<'_> + { + alloy_sol_types::private::SolTypeValue::< + alloy::sol_types::sol_data::Uint<8>, + >::stv_to_tokens(self) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + as alloy_sol_types::SolType>::tokenize(self).0 + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + as alloy_sol_types::SolType>::abi_encode_packed_to(self, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + as alloy_sol_types::SolType>::abi_encoded_size( + self, + ) + } + } + impl TaskState { + /// The Solidity type name. + pub const NAME: &'static str = stringify!(@ name); + /// Convert from the underlying value type. + #[inline] + pub const fn from_underlying(value: u8) -> Self { + Self(value) + } + /// Return the underlying value. + #[inline] + pub const fn into_underlying(self) -> u8 { + self.0 + } + /// Return the single encoding of this value, delegating to the + /// underlying type. + #[inline] + pub fn abi_encode(&self) -> alloy_sol_types::private::Vec { + ::abi_encode(&self.0) + } + /// Return the packed encoding of this value, delegating to the + /// underlying type. + #[inline] + pub fn abi_encode_packed(&self) -> alloy_sol_types::private::Vec { + ::abi_encode_packed(&self.0) + } + } + #[automatically_derived] + impl From for TaskState { + fn from(value: u8) -> Self { + Self::from_underlying(value) + } + } + #[automatically_derived] + impl From for u8 { + fn from(value: TaskState) -> Self { + value.into_underlying() + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for TaskState { + type RustType = u8; + type Token<'a> = + as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = Self::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + Self::type_check(token).is_ok() + } + #[inline] + fn type_check(token: &Self::Token<'_>) -> alloy_sol_types::Result<()> { + as alloy_sol_types::SolType>::type_check(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + as alloy_sol_types::SolType>::detokenize(token) + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for TaskState { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + as alloy_sol_types::EventTopic>::topic_preimage_length(rust) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + as alloy_sol_types::EventTopic>::encode_topic_preimage(rust, out) + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + as alloy_sol_types::EventTopic>::encode_topic( + rust, + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**```solidity + struct TaskDetails { uint128 maxGasAmount; uint128 gasPriceCap; uint128 automationFeeCapForCycle; uint128 lockedFeeForNextCycle; bytes32 txHash; uint64 taskIndex; uint64 registrationTime; uint64 expiryTime; address owner; TaskState state; bytes payloadTx; bytes[] auxData; } + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct TaskDetails { + #[allow(missing_docs)] + pub maxGasAmount: u128, + #[allow(missing_docs)] + pub gasPriceCap: u128, + #[allow(missing_docs)] + pub automationFeeCapForCycle: u128, + #[allow(missing_docs)] + pub lockedFeeForNextCycle: u128, + #[allow(missing_docs)] + pub txHash: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub taskIndex: u64, + #[allow(missing_docs)] + pub registrationTime: u64, + #[allow(missing_docs)] + pub expiryTime: u64, + #[allow(missing_docs)] + pub owner: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub state: ::RustType, + #[allow(missing_docs)] + pub payloadTx: alloy::sol_types::private::Bytes, + #[allow(missing_docs)] + pub auxData: alloy::sol_types::private::Vec, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<128>, + alloy::sol_types::sol_data::Uint<128>, + alloy::sol_types::sol_data::Uint<128>, + alloy::sol_types::sol_data::Uint<128>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Address, + TaskState, + alloy::sol_types::sol_data::Bytes, + alloy::sol_types::sol_data::Array, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + u128, + u128, + u128, + u128, + alloy::sol_types::private::FixedBytes<32>, + u64, + u64, + u64, + alloy::sol_types::private::Address, + ::RustType, + alloy::sol_types::private::Bytes, + alloy::sol_types::private::Vec, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: TaskDetails) -> Self { + ( + value.maxGasAmount, + value.gasPriceCap, + value.automationFeeCapForCycle, + value.lockedFeeForNextCycle, + value.txHash, + value.taskIndex, + value.registrationTime, + value.expiryTime, + value.owner, + value.state, + value.payloadTx, + value.auxData, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for TaskDetails { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + maxGasAmount: tuple.0, + gasPriceCap: tuple.1, + automationFeeCapForCycle: tuple.2, + lockedFeeForNextCycle: tuple.3, + txHash: tuple.4, + taskIndex: tuple.5, + registrationTime: tuple.6, + expiryTime: tuple.7, + owner: tuple.8, + state: tuple.9, + payloadTx: tuple.10, + auxData: tuple.11, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for TaskDetails { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for TaskDetails { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.maxGasAmount), + as alloy_sol_types::SolType>::tokenize(&self.gasPriceCap), + as alloy_sol_types::SolType>::tokenize( + &self.automationFeeCapForCycle, + ), + as alloy_sol_types::SolType>::tokenize( + &self.lockedFeeForNextCycle, + ), + as alloy_sol_types::SolType>::tokenize(&self.txHash), + as alloy_sol_types::SolType>::tokenize(&self.taskIndex), + as alloy_sol_types::SolType>::tokenize(&self.registrationTime), + as alloy_sol_types::SolType>::tokenize(&self.expiryTime), + ::tokenize( + &self.owner, + ), + ::tokenize(&self.state), + ::tokenize( + &self.payloadTx, + ), + as alloy_sol_types::SolType>::tokenize(&self.auxData), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to(&self, out: &mut alloy_sol_types::private::Vec) { + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to( + &tuple, out, + ) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = + as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size( + &tuple, + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for TaskDetails { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = + as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for TaskDetails { + const NAME: &'static str = "TaskDetails"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "TaskDetails(uint128 maxGasAmount,uint128 gasPriceCap,uint128 automationFeeCapForCycle,uint128 lockedFeeForNextCycle,bytes32 txHash,uint64 taskIndex,uint64 registrationTime,uint64 expiryTime,address owner,uint8 state,bytes payloadTx,bytes[] auxData)", + ) + } + #[inline] + fn eip712_components( + ) -> alloy_sol_types::private::Vec> + { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.maxGasAmount) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.gasPriceCap) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.automationFeeCapForCycle, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.lockedFeeForNextCycle, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.txHash) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.taskIndex) + .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.registrationTime, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.expiryTime) + .0, + ::eip712_data_word( + &self.owner, + ) + .0, + ::eip712_data_word( + &self.state, + ) + .0, + ::eip712_data_word( + &self.payloadTx, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.auxData) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for TaskDetails { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.maxGasAmount, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.gasPriceCap, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.automationFeeCapForCycle, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.lockedFeeForNextCycle, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.txHash, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.taskIndex, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.registrationTime, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.expiryTime, + ) + + ::topic_preimage_length( + &rust.owner, + ) + + ::topic_preimage_length( + &rust.state, + ) + + ::topic_preimage_length( + &rust.payloadTx, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.auxData, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve(::topic_preimage_length(rust)); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.maxGasAmount, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.gasPriceCap, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.automationFeeCapForCycle, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.lockedFeeForNextCycle, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.txHash, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.taskIndex, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.registrationTime, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.expiryTime, + out, + ); + ::encode_topic_preimage( + &rust.owner, + out, + ); + ::encode_topic_preimage(&rust.state, out); + ::encode_topic_preimage( + &rust.payloadTx, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.auxData, + out, + ); + } + #[inline] + fn encode_topic(rust: &Self::RustType) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage(rust, &mut out); + alloy_sol_types::abi::token::WordToken(alloy_sol_types::private::keccak256(out)) + } + } + }; + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`CommonUtils`](self) contract instance. + + See the [wrapper's documentation](`CommonUtilsInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + __provider: P, + ) -> CommonUtilsInstance { + CommonUtilsInstance::::new(address, __provider) + } + /**A [`CommonUtils`](self) instance. + + Contains type-safe methods for interacting with an on-chain instance of the + [`CommonUtils`](self) contract located at a given `address`, using a given + provider `P`. + + If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) + documentation on how to provide it), the `deploy` and `deploy_builder` methods can + be used to deploy a new instance of the contract. + + See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct CommonUtilsInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for CommonUtilsInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("CommonUtilsInstance") + .field(&self.address) + .finish() + } + } + /// Instantiation and getters/setters. + impl, N: alloy_contract::private::Network> + CommonUtilsInstance + { + /**Creates a new wrapper around an on-chain [`CommonUtils`](self) contract instance. + + See the [wrapper's documentation](`CommonUtilsInstance`) for more details.*/ + #[inline] + pub const fn new(address: alloy_sol_types::private::Address, __provider: P) -> Self { + Self { + address, + provider: __provider, + _network: ::core::marker::PhantomData, + } + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl CommonUtilsInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> CommonUtilsInstance { + CommonUtilsInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + impl, N: alloy_contract::private::Network> + CommonUtilsInstance + { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + } + /// Event filters. + impl, N: alloy_contract::private::Network> + CommonUtilsInstance + { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} +/** + +Generated by the following Solidity interface... +```solidity +library CommonUtils { + type CycleState is uint8; + type TaskState is uint8; + struct TaskDetails { + uint128 maxGasAmount; + uint128 gasPriceCap; + uint128 automationFeeCapForCycle; + uint128 lockedFeeForNextCycle; + bytes32 txHash; + uint64 taskIndex; + uint64 registrationTime; + uint64 expiryTime; + address owner; + TaskState state; + bytes payloadTx; + bytes[] auxData; + } +} + +interface SupraContractsBindings { + function blockPrologue() external; + function getAllActiveTaskIds() external view returns (uint256[] memory); + function getCycleInfo() external view returns (uint64, uint64, uint64, CommonUtils.CycleState); + function getTaskDetails(uint64 _taskIndex) external view returns (CommonUtils.TaskDetails memory); + function getTaskDetailsBulk(uint64[] memory _taskIndexes) external view returns (CommonUtils.TaskDetails[] memory); + function getTaskIdList() external view returns (uint256[] memory); + function getTransitionInfo() external view returns (uint64, uint128); + function ifTaskExists(uint64 _taskIndex) external view returns (bool); + function isAutomationEnabled() external view returns (bool); + function processTasks(uint64 _cycleIndex, uint64[] memory _taskIndexes) external; +} +``` + +...which was generated by the following JSON ABI: +```json +[ + { + "type": "function", + "name": "blockPrologue", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getAllActiveTaskIds", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getCycleInfo", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "", + "type": "uint8", + "internalType": "enum CommonUtils.CycleState" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTaskDetails", + "inputs": [ + { + "name": "_taskIndex", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct CommonUtils.TaskDetails", + "components": [ + { + "name": "maxGasAmount", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "gasPriceCap", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "automationFeeCapForCycle", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "lockedFeeForNextCycle", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "txHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "taskIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "registrationTime", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "expiryTime", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "state", + "type": "uint8", + "internalType": "enum CommonUtils.TaskState" + }, + { + "name": "payloadTx", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "auxData", + "type": "bytes[]", + "internalType": "bytes[]" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTaskDetailsBulk", + "inputs": [ + { + "name": "_taskIndexes", + "type": "uint64[]", + "internalType": "uint64[]" + } + ], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "internalType": "struct CommonUtils.TaskDetails[]", + "components": [ + { + "name": "maxGasAmount", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "gasPriceCap", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "automationFeeCapForCycle", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "lockedFeeForNextCycle", + "type": "uint128", + "internalType": "uint128" + }, + { + "name": "txHash", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "taskIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "registrationTime", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "expiryTime", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "state", + "type": "uint8", + "internalType": "enum CommonUtils.TaskState" + }, + { + "name": "payloadTx", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "auxData", + "type": "bytes[]", + "internalType": "bytes[]" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTaskIdList", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256[]", + "internalType": "uint256[]" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getTransitionInfo", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "", + "type": "uint128", + "internalType": "uint128" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "ifTaskExists", + "inputs": [ + { + "name": "_taskIndex", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isAutomationEnabled", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "processTasks", + "inputs": [ + { + "name": "_cycleIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "_taskIndexes", + "type": "uint64[]", + "internalType": "uint64[]" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + } +] +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod SupraContractsBindings { + use super::*; + use alloy::sol_types as alloy_sol_types; + /// The creation / init bytecode of the contract. + /// + /// ```text + ///0x + /// ``` + #[rustfmt::skip] + #[allow(clippy::all)] + pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( + b"", + ); + /// The runtime bytecode of the contract, as deployed on the network. + /// + /// ```text + ///0x + /// ``` + #[rustfmt::skip] + #[allow(clippy::all)] + pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( + b"", + ); + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `blockPrologue()` and selector `0x7ded091b`. + ```solidity + function blockPrologue() external; + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct blockPrologueCall; + ///Container type for the return parameters of the [`blockPrologue()`](blockPrologueCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct blockPrologueReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: blockPrologueCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for blockPrologueCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: blockPrologueReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for blockPrologueReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl blockPrologueReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for blockPrologueCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = blockPrologueReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "blockPrologue()"; + const SELECTOR: [u8; 4] = [125u8, 237u8, 9u8, 27u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + blockPrologueReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getAllActiveTaskIds()` and selector `0xc5dcf6ac`. + ```solidity + function getAllActiveTaskIds() external view returns (uint256[] memory); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getAllActiveTaskIdsCall; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`getAllActiveTaskIds()`](getAllActiveTaskIdsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getAllActiveTaskIdsReturn { + #[allow(missing_docs)] + pub _0: + alloy::sol_types::private::Vec, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getAllActiveTaskIdsCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getAllActiveTaskIdsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = + (alloy::sol_types::sol_data::Array>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getAllActiveTaskIdsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getAllActiveTaskIdsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getAllActiveTaskIdsCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >; + type ReturnTuple<'a> = + (alloy::sol_types::sol_data::Array>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getAllActiveTaskIds()"; + const SELECTOR: [u8; 4] = [197u8, 220u8, 246u8, 172u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (, + > as alloy_sol_types::SolType>::tokenize(ret),) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: getAllActiveTaskIdsReturn = r.into(); + r._0 + }, + ) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: getAllActiveTaskIdsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getCycleInfo()` and selector `0x873dc71d`. + ```solidity + function getCycleInfo() external view returns (uint64, uint64, uint64, CommonUtils.CycleState); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getCycleInfoCall; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`getCycleInfo()`](getCycleInfoCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getCycleInfoReturn { + #[allow(missing_docs)] + pub _0: u64, + #[allow(missing_docs)] + pub _1: u64, + #[allow(missing_docs)] + pub _2: u64, + #[allow(missing_docs)] + pub _3: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getCycleInfoCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getCycleInfoCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<64>, + CommonUtils::CycleState, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + u64, + u64, + u64, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getCycleInfoReturn) -> Self { + (value._0, value._1, value._2, value._3) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getCycleInfoReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _0: tuple.0, + _1: tuple.1, + _2: tuple.2, + _3: tuple.3, + } + } + } + } + impl getCycleInfoReturn { + fn _tokenize(&self) -> ::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self._0, + ), + as alloy_sol_types::SolType>::tokenize( + &self._1, + ), + as alloy_sol_types::SolType>::tokenize( + &self._2, + ), + ::tokenize(&self._3), + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getCycleInfoCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = getCycleInfoReturn; + type ReturnTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<64>, + CommonUtils::CycleState, + ); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getCycleInfo()"; + const SELECTOR: [u8; 4] = [135u8, 61u8, 199u8, 29u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + getCycleInfoReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getTaskDetails(uint64)` and selector `0xb2ef6896`. + ```solidity + function getTaskDetails(uint64 _taskIndex) external view returns (CommonUtils.TaskDetails memory); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTaskDetailsCall { + #[allow(missing_docs)] + pub _taskIndex: u64, + } + #[derive(serde::Serialize, serde::Deserialize)] + ///Container type for the return parameters of the [`getTaskDetails(uint64)`](getTaskDetailsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTaskDetailsReturn { + #[allow(missing_docs)] + pub _0: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<64>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u64,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTaskDetailsCall) -> Self { + (value._taskIndex,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTaskDetailsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _taskIndex: tuple.0, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (CommonUtils::TaskDetails,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = + (::RustType,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTaskDetailsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTaskDetailsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getTaskDetailsCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<64>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = ::RustType; + type ReturnTuple<'a> = (CommonUtils::TaskDetails,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getTaskDetails(uint64)"; + const SELECTOR: [u8; 4] = [178u8, 239u8, 104u8, 150u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self._taskIndex, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: getTaskDetailsReturn = r.into(); + r._0 + }, + ) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: getTaskDetailsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getTaskDetailsBulk(uint64[])` and selector `0x12f72cf4`. + ```solidity + function getTaskDetailsBulk(uint64[] memory _taskIndexes) external view returns (CommonUtils.TaskDetails[] memory); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTaskDetailsBulkCall { + #[allow(missing_docs)] + pub _taskIndexes: alloy::sol_types::private::Vec, + } + #[derive(serde::Serialize, serde::Deserialize)] + ///Container type for the return parameters of the [`getTaskDetailsBulk(uint64[])`](getTaskDetailsBulkCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTaskDetailsBulkReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Vec< + ::RustType, + >, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = + (alloy::sol_types::sol_data::Array>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Vec,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTaskDetailsBulkCall) -> Self { + (value._taskIndexes,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTaskDetailsBulkCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _taskIndexes: tuple.0, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = + (alloy::sol_types::sol_data::Array,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec< + ::RustType, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTaskDetailsBulkReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTaskDetailsBulkReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getTaskDetailsBulkCall { + type Parameters<'a> = + (alloy::sol_types::sol_data::Array>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Vec< + ::RustType, + >; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Array,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getTaskDetailsBulk(uint64[])"; + const SELECTOR: [u8; 4] = [18u8, 247u8, 44u8, 244u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + (, + > as alloy_sol_types::SolType>::tokenize( + &self._taskIndexes + ),) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: getTaskDetailsBulkReturn = r.into(); + r._0 + }, + ) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: getTaskDetailsBulkReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getTaskIdList()` and selector `0xec82b429`. + ```solidity + function getTaskIdList() external view returns (uint256[] memory); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTaskIdListCall; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`getTaskIdList()`](getTaskIdListCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTaskIdListReturn { + #[allow(missing_docs)] + pub _0: + alloy::sol_types::private::Vec, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTaskIdListCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTaskIdListCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = + (alloy::sol_types::sol_data::Array>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTaskIdListReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTaskIdListReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getTaskIdListCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >; + type ReturnTuple<'a> = + (alloy::sol_types::sol_data::Array>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getTaskIdList()"; + const SELECTOR: [u8; 4] = [236u8, 130u8, 180u8, 41u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (, + > as alloy_sol_types::SolType>::tokenize(ret),) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: getTaskIdListReturn = r.into(); + r._0 + }, + ) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: getTaskIdListReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getTransitionInfo()` and selector `0xf5c1249f`. + ```solidity + function getTransitionInfo() external view returns (uint64, uint128); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTransitionInfoCall; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`getTransitionInfo()`](getTransitionInfoCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getTransitionInfoReturn { + #[allow(missing_docs)] + pub _0: u64, + #[allow(missing_docs)] + pub _1: u128, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTransitionInfoCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTransitionInfoCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<128>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u64, u128); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getTransitionInfoReturn) -> Self { + (value._0, value._1) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getTransitionInfoReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _0: tuple.0, + _1: tuple.1, + } + } + } + } + impl getTransitionInfoReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self._0, + ), + as alloy_sol_types::SolType>::tokenize( + &self._1, + ), + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getTransitionInfoCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = getTransitionInfoReturn; + type ReturnTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Uint<128>, + ); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getTransitionInfo()"; + const SELECTOR: [u8; 4] = [245u8, 193u8, 36u8, 159u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + getTransitionInfoReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `ifTaskExists(uint64)` and selector `0x8aaa404e`. + ```solidity + function ifTaskExists(uint64 _taskIndex) external view returns (bool); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ifTaskExistsCall { + #[allow(missing_docs)] + pub _taskIndex: u64, + } + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`ifTaskExists(uint64)`](ifTaskExistsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ifTaskExistsReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<64>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u64,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ifTaskExistsCall) -> Self { + (value._taskIndex,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ifTaskExistsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _taskIndex: tuple.0, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ifTaskExistsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ifTaskExistsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for ifTaskExistsCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<64>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ifTaskExists(uint64)"; + const SELECTOR: [u8; 4] = [138u8, 170u8, 64u8, 78u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize( + &self._taskIndex, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: ifTaskExistsReturn = r.into(); + r._0 + }, + ) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: ifTaskExistsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `isAutomationEnabled()` and selector `0xe48e0e98`. + ```solidity + function isAutomationEnabled() external view returns (bool); + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct isAutomationEnabledCall; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`isAutomationEnabled()`](isAutomationEnabledCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct isAutomationEnabledReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: isAutomationEnabledCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for isAutomationEnabledCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: isAutomationEnabledReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for isAutomationEnabledReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for isAutomationEnabledCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "isAutomationEnabled()"; + const SELECTOR: [u8; 4] = [228u8, 142u8, 14u8, 152u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + (::tokenize(ret),) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data).map( + |r| { + let r: isAutomationEnabledReturn = r.into(); + r._0 + }, + ) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(|r| { + let r: isAutomationEnabledReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize, Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `processTasks(uint64,uint64[])` and selector `0x7f69c35c`. + ```solidity + function processTasks(uint64 _cycleIndex, uint64[] memory _taskIndexes) external; + ```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct processTasksCall { + #[allow(missing_docs)] + pub _cycleIndex: u64, + #[allow(missing_docs)] + pub _taskIndexes: alloy::sol_types::private::Vec, + } + ///Container type for the return parameters of the [`processTasks(uint64,uint64[])`](processTasksCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct processTasksReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Array>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u64, alloy::sol_types::private::Vec); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: processTasksCall) -> Self { + (value._cycleIndex, value._taskIndexes) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for processTasksCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _cycleIndex: tuple.0, + _taskIndexes: tuple.1, + } + } + } + } + { + #[doc(hidden)] + #[allow(dead_code)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion(_t: alloy_sol_types::private::AssertTypeEq) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: processTasksReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for processTasksReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl processTasksReturn { + fn _tokenize(&self) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for processTasksCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Uint<64>, + alloy::sol_types::sol_data::Array>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = processTasksReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "processTasks(uint64,uint64[])"; + const SELECTOR: [u8; 4] = [127u8, 105u8, 195u8, 92u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self._cycleIndex), + , + > as alloy_sol_types::SolType>::tokenize(&self._taskIndexes), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + processTasksReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate( + data, + ) + .map(Into::into) + } + } + }; + ///Container for all the [`SupraContractsBindings`](self) function calls. + #[derive(Clone, serde::Serialize, serde::Deserialize)] + pub enum SupraContractsBindingsCalls { + #[allow(missing_docs)] + blockPrologue(blockPrologueCall), + #[allow(missing_docs)] + getAllActiveTaskIds(getAllActiveTaskIdsCall), + #[allow(missing_docs)] + getCycleInfo(getCycleInfoCall), + #[allow(missing_docs)] + getTaskDetails(getTaskDetailsCall), + #[allow(missing_docs)] + getTaskDetailsBulk(getTaskDetailsBulkCall), + #[allow(missing_docs)] + getTaskIdList(getTaskIdListCall), + #[allow(missing_docs)] + getTransitionInfo(getTransitionInfoCall), + #[allow(missing_docs)] + ifTaskExists(ifTaskExistsCall), + #[allow(missing_docs)] + isAutomationEnabled(isAutomationEnabledCall), + #[allow(missing_docs)] + processTasks(processTasksCall), + } + impl SupraContractsBindingsCalls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [18u8, 247u8, 44u8, 244u8], + [125u8, 237u8, 9u8, 27u8], + [127u8, 105u8, 195u8, 92u8], + [135u8, 61u8, 199u8, 29u8], + [138u8, 170u8, 64u8, 78u8], + [178u8, 239u8, 104u8, 150u8], + [197u8, 220u8, 246u8, 172u8], + [228u8, 142u8, 14u8, 152u8], + [236u8, 130u8, 180u8, 41u8], + [245u8, 193u8, 36u8, 159u8], + ]; + /// The names of the variants in the same order as `SELECTORS`. + pub const VARIANT_NAMES: &'static [&'static str] = &[ + ::core::stringify!(getTaskDetailsBulk), + ::core::stringify!(blockPrologue), + ::core::stringify!(processTasks), + ::core::stringify!(getCycleInfo), + ::core::stringify!(ifTaskExists), + ::core::stringify!(getTaskDetails), + ::core::stringify!(getAllActiveTaskIds), + ::core::stringify!(isAutomationEnabled), + ::core::stringify!(getTaskIdList), + ::core::stringify!(getTransitionInfo), + ]; + /// The signatures in the same order as `SELECTORS`. + pub const SIGNATURES: &'static [&'static str] = &[ + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ::SIGNATURE, + ]; + /// Returns the signature for the given selector, if known. + #[inline] + pub fn signature_by_selector( + selector: [u8; 4usize], + ) -> ::core::option::Option<&'static str> { + match Self::SELECTORS.binary_search(&selector) { + ::core::result::Result::Ok(idx) => { + ::core::option::Option::Some(Self::SIGNATURES[idx]) + } + ::core::result::Result::Err(_) => ::core::option::Option::None, + } + } + /// Returns the enum variant name for the given selector, if known. + #[inline] + pub fn name_by_selector(selector: [u8; 4usize]) -> ::core::option::Option<&'static str> { + let sig = Self::signature_by_selector(selector)?; + sig.split_once('(').map(|(name, _)| name) + } + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for SupraContractsBindingsCalls { + const NAME: &'static str = "SupraContractsBindingsCalls"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 10usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::blockPrologue(_) => ::SELECTOR, + Self::getAllActiveTaskIds(_) => { + ::SELECTOR + } + Self::getCycleInfo(_) => ::SELECTOR, + Self::getTaskDetails(_) => { + ::SELECTOR + } + Self::getTaskDetailsBulk(_) => { + ::SELECTOR + } + Self::getTaskIdList(_) => ::SELECTOR, + Self::getTransitionInfo(_) => { + ::SELECTOR + } + Self::ifTaskExists(_) => ::SELECTOR, + Self::isAutomationEnabled(_) => { + ::SELECTOR + } + Self::processTasks(_) => ::SELECTOR, + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw(selector: [u8; 4], data: &[u8]) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) + -> alloy_sol_types::Result] = &[ + { + fn getTaskDetailsBulk( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::getTaskDetailsBulk) + } + getTaskDetailsBulk + }, + { + fn blockPrologue( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::blockPrologue) + } + blockPrologue + }, + { + fn processTasks( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::processTasks) + } + processTasks + }, + { + fn getCycleInfo( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::getCycleInfo) + } + getCycleInfo + }, + { + fn ifTaskExists( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::ifTaskExists) + } + ifTaskExists + }, + { + fn getTaskDetails( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::getTaskDetails) + } + getTaskDetails + }, + { + fn getAllActiveTaskIds( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::getAllActiveTaskIds) + } + getAllActiveTaskIds + }, + { + fn isAutomationEnabled( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::isAutomationEnabled) + } + isAutomationEnabled + }, + { + fn getTaskIdList( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::getTaskIdList) + } + getTaskIdList + }, + { + fn getTransitionInfo( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(SupraContractsBindingsCalls::getTransitionInfo) + } + getTransitionInfo + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); + }; + DECODE_SHIMS[idx](data) + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result< + SupraContractsBindingsCalls, + >] = &[ + { + fn getTaskDetailsBulk( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::getTaskDetailsBulk) + } + getTaskDetailsBulk + }, + { + fn blockPrologue( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::blockPrologue) + } + blockPrologue + }, + { + fn processTasks( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::processTasks) + } + processTasks + }, + { + fn getCycleInfo( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::getCycleInfo) + } + getCycleInfo + }, + { + fn ifTaskExists( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::ifTaskExists) + } + ifTaskExists + }, + { + fn getTaskDetails( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::getTaskDetails) + } + getTaskDetails + }, + { + fn getAllActiveTaskIds( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::getAllActiveTaskIds) + } + getAllActiveTaskIds + }, + { + fn isAutomationEnabled( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::isAutomationEnabled) + } + isAutomationEnabled + }, + { + fn getTaskIdList( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::getTaskIdList) + } + getTaskIdList + }, + { + fn getTransitionInfo( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(SupraContractsBindingsCalls::getTransitionInfo) + } + getTransitionInfo + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err(alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + )); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::blockPrologue(inner) => { + ::abi_encoded_size(inner) + } + Self::getAllActiveTaskIds(inner) => { + ::abi_encoded_size(inner) + } + Self::getCycleInfo(inner) => { + ::abi_encoded_size(inner) + } + Self::getTaskDetails(inner) => { + ::abi_encoded_size(inner) + } + Self::getTaskDetailsBulk(inner) => { + ::abi_encoded_size(inner) + } + Self::getTaskIdList(inner) => { + ::abi_encoded_size(inner) + } + Self::getTransitionInfo(inner) => { + ::abi_encoded_size(inner) + } + Self::ifTaskExists(inner) => { + ::abi_encoded_size(inner) + } + Self::isAutomationEnabled(inner) => { + ::abi_encoded_size(inner) + } + Self::processTasks(inner) => { + ::abi_encoded_size(inner) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::blockPrologue(inner) => { + ::abi_encode_raw(inner, out) + } + Self::getAllActiveTaskIds(inner) => { + ::abi_encode_raw( + inner, out, + ) + } + Self::getCycleInfo(inner) => { + ::abi_encode_raw(inner, out) + } + Self::getTaskDetails(inner) => { + ::abi_encode_raw(inner, out) + } + Self::getTaskDetailsBulk(inner) => { + ::abi_encode_raw(inner, out) + } + Self::getTaskIdList(inner) => { + ::abi_encode_raw(inner, out) + } + Self::getTransitionInfo(inner) => { + ::abi_encode_raw(inner, out) + } + Self::ifTaskExists(inner) => { + ::abi_encode_raw(inner, out) + } + Self::isAutomationEnabled(inner) => { + ::abi_encode_raw( + inner, out, + ) + } + Self::processTasks(inner) => { + ::abi_encode_raw(inner, out) + } + } + } + } + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`SupraContractsBindings`](self) contract instance. + + See the [wrapper's documentation](`SupraContractsBindingsInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + __provider: P, + ) -> SupraContractsBindingsInstance { + SupraContractsBindingsInstance::::new(address, __provider) + } + /**Deploys this contract using the given `provider` and constructor arguments, if any. + + Returns a new instance of the contract, if the deployment was successful. + + For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub fn deploy, N: alloy_contract::private::Network>( + __provider: P, + ) -> impl ::core::future::Future>> + { + SupraContractsBindingsInstance::::deploy(__provider) + } + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` + and constructor arguments, if any. + + This is a simple wrapper around creating a `RawCallBuilder` with the data set to + the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + __provider: P, + ) -> alloy_contract::RawCallBuilder { + SupraContractsBindingsInstance::::deploy_builder(__provider) + } + /**A [`SupraContractsBindings`](self) instance. + + Contains type-safe methods for interacting with an on-chain instance of the + [`SupraContractsBindings`](self) contract located at a given `address`, using a given + provider `P`. + + If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) + documentation on how to provide it), the `deploy` and `deploy_builder` methods can + be used to deploy a new instance of the contract. + + See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct SupraContractsBindingsInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for SupraContractsBindingsInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("SupraContractsBindingsInstance") + .field(&self.address) + .finish() + } + } + /// Instantiation and getters/setters. + impl, N: alloy_contract::private::Network> + SupraContractsBindingsInstance + { + /**Creates a new wrapper around an on-chain [`SupraContractsBindings`](self) contract instance. + + See the [wrapper's documentation](`SupraContractsBindingsInstance`) for more details.*/ + #[inline] + pub const fn new(address: alloy_sol_types::private::Address, __provider: P) -> Self { + Self { + address, + provider: __provider, + _network: ::core::marker::PhantomData, + } + } + /**Deploys this contract using the given `provider` and constructor arguments, if any. + + Returns a new instance of the contract, if the deployment was successful. + + For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub async fn deploy( + __provider: P, + ) -> alloy_contract::Result> { + let call_builder = Self::deploy_builder(__provider); + let contract_address = call_builder.deploy().await?; + Ok(Self::new(contract_address, call_builder.provider)) + } + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` + and constructor arguments, if any. + + This is a simple wrapper around creating a `RawCallBuilder` with the data set to + the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder(__provider: P) -> alloy_contract::RawCallBuilder { + alloy_contract::RawCallBuilder::new_raw_deploy( + __provider, + ::core::clone::Clone::clone(&BYTECODE), + ) + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl SupraContractsBindingsInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> SupraContractsBindingsInstance { + SupraContractsBindingsInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + impl, N: alloy_contract::private::Network> + SupraContractsBindingsInstance + { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + ///Creates a new call builder for the [`blockPrologue`] function. + pub fn blockPrologue(&self) -> alloy_contract::SolCallBuilder<&P, blockPrologueCall, N> { + self.call_builder(&blockPrologueCall) + } + ///Creates a new call builder for the [`getAllActiveTaskIds`] function. + pub fn getAllActiveTaskIds( + &self, + ) -> alloy_contract::SolCallBuilder<&P, getAllActiveTaskIdsCall, N> { + self.call_builder(&getAllActiveTaskIdsCall) + } + ///Creates a new call builder for the [`getCycleInfo`] function. + pub fn getCycleInfo(&self) -> alloy_contract::SolCallBuilder<&P, getCycleInfoCall, N> { + self.call_builder(&getCycleInfoCall) + } + ///Creates a new call builder for the [`getTaskDetails`] function. + pub fn getTaskDetails( + &self, + _taskIndex: u64, + ) -> alloy_contract::SolCallBuilder<&P, getTaskDetailsCall, N> { + self.call_builder(&getTaskDetailsCall { _taskIndex }) + } + ///Creates a new call builder for the [`getTaskDetailsBulk`] function. + pub fn getTaskDetailsBulk( + &self, + _taskIndexes: alloy::sol_types::private::Vec, + ) -> alloy_contract::SolCallBuilder<&P, getTaskDetailsBulkCall, N> { + self.call_builder(&getTaskDetailsBulkCall { _taskIndexes }) + } + ///Creates a new call builder for the [`getTaskIdList`] function. + pub fn getTaskIdList(&self) -> alloy_contract::SolCallBuilder<&P, getTaskIdListCall, N> { + self.call_builder(&getTaskIdListCall) + } + ///Creates a new call builder for the [`getTransitionInfo`] function. + pub fn getTransitionInfo( + &self, + ) -> alloy_contract::SolCallBuilder<&P, getTransitionInfoCall, N> { + self.call_builder(&getTransitionInfoCall) + } + ///Creates a new call builder for the [`ifTaskExists`] function. + pub fn ifTaskExists( + &self, + _taskIndex: u64, + ) -> alloy_contract::SolCallBuilder<&P, ifTaskExistsCall, N> { + self.call_builder(&ifTaskExistsCall { _taskIndex }) + } + ///Creates a new call builder for the [`isAutomationEnabled`] function. + pub fn isAutomationEnabled( + &self, + ) -> alloy_contract::SolCallBuilder<&P, isAutomationEnabledCall, N> { + self.call_builder(&isAutomationEnabledCall) + } + ///Creates a new call builder for the [`processTasks`] function. + pub fn processTasks( + &self, + _cycleIndex: u64, + _taskIndexes: alloy::sol_types::private::Vec, + ) -> alloy_contract::SolCallBuilder<&P, processTasksCall, N> { + self.call_builder(&processTasksCall { + _cycleIndex, + _taskIndexes, + }) + } + } + /// Event filters. + impl, N: alloy_contract::private::Network> + SupraContractsBindingsInstance + { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} diff --git a/crates/supra-extension/src/transactions/automated_transaction.rs b/crates/supra-extension/src/transactions/automated_transaction.rs new file mode 100644 index 0000000000..8e9615699c --- /dev/null +++ b/crates/supra-extension/src/transactions/automated_transaction.rs @@ -0,0 +1,496 @@ +//! AutomatedTransaction generated based on the registered active automation task. + +use crate::errors::SupraExtensionError; +use crate::supra_contract_bindings::supra_contracts_bindings::CommonUtils::TaskDetails; +use crate::value_or_error; +use alloy::eips::eip2930::AccessList; +use alloy::primitives::{Address, Bytes, ChainId, B256, U256}; +use alloy_consensus::transaction::Transaction; +use alloy_eips::eip2718::Typed2718; +use alloy_sol_types::SolType; +use context::transaction::{AccessListItem, SignedAuthorization}; +use context::TransactionType; +use primitives::TxKind; + +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +#[repr(u8)] +/// Automated transaction type corresponding automation task type. +pub enum AutomatedTransactionType { + /// User submitted automation task based + #[default] + UST, + /// Governance submitted/authorized automation task based. Will be gasless transaction + GST, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +/// Automated transaction generated by node runtime based on the registered active automation task. +pub struct AutomatedTransaction { + /// Height of the block in scope of which this transaction is being executed. + pub block_height: u64, + /// Hash of the transaction which registered an automation task based on which this transaction is created. + pub registration_hash: B256, + /// Owner address of the automation task, the source of this transaction. + pub sender: Address, + /// Type of the automated transaction. + pub txn_type: AutomatedTransactionType, + /// Chain id. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + pub chain_id: ChainId, + /// A scalar value equal to the automation task index based on which this transaction is created. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + pub nonce: u64, + /// A scalar value equal to the maximum + /// amount of gas that should be used in executing + /// this transaction. This is paid up-front, before any + /// computation is done and may not be increased + /// later; formally Tg. + #[cfg_attr( + feature = "serde", + serde(with = "alloy_serde::quantity", rename = "gas", alias = "gasLimit") + )] + pub gas_limit: u64, + /// A scalar value equal to the maximum + /// amount of gas that should be used in executing + /// this transaction. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + pub max_fee_per_gas: u128, + /// The 160-bit address of the message call’s recipient or, for a contract creation + /// transaction, ∅, used here to denote the only member of B0 ; formally Tt. + #[cfg_attr(feature = "serde", serde(default))] + pub to: Address, + /// A scalar value equal to the number of Wei to + /// be transferred to the message call’s recipient or, + /// in the case of contract creation, as an endowment + /// to the newly created account; formally Tv. + pub value: U256, + /// The accessList specifies a list of addresses and storage keys; + /// these addresses and storage keys are added into the `accessed_addresses` + /// and `accessed_storage_keys` global sets (introduced in EIP-2929). + /// A gas cost is charged, though at a discount relative to the cost of + /// accessing outside the list. + // Deserialize with `alloy_serde::null_as_default` to also accept a `null` value + // instead of an (empty) array. This is due to certain RPC providers (e.g., Filecoin's) + // sometimes returning `null` instead of an empty array `[]`. + // More details in . + #[cfg_attr( + feature = "serde", + serde(deserialize_with = "alloy_serde::null_as_default") + )] + pub access_list: AccessList, + /// Input has two uses depending if `to` field is Create or Call. + /// pub init: An unlimited size byte array specifying the + /// EVM-code for the account initialisation procedure CREATE, + /// data: An unlimited size byte array specifying the + /// input data of the message call, formally Td. + pub input: Bytes, +} + +impl Transaction for AutomatedTransaction { + #[inline] + fn chain_id(&self) -> Option { + Some(self.chain_id) + } + + #[inline] + fn nonce(&self) -> u64 { + self.nonce + } + + #[inline] + fn gas_limit(&self) -> u64 { + self.gas_limit + } + + #[inline] + fn gas_price(&self) -> Option { + None + } + + #[inline] + fn max_fee_per_gas(&self) -> u128 { + self.max_fee_per_gas + } + + #[inline] + fn max_priority_fee_per_gas(&self) -> Option { + Some(0) + } + + #[inline] + fn max_fee_per_blob_gas(&self) -> Option { + None + } + + #[inline] + fn priority_fee_or_price(&self) -> u128 { + 0 + } + + fn effective_gas_price(&self, base_fee: Option) -> u128 { + alloy_eips::eip1559::calc_effective_gas_price(self.max_fee_per_gas, 0, base_fee) + } + + #[inline] + fn is_dynamic_fee(&self) -> bool { + true + } + + #[inline] + fn kind(&self) -> TxKind { + TxKind::Call(self.to) + } + + #[inline] + fn is_create(&self) -> bool { + false + } + + #[inline] + fn value(&self) -> U256 { + self.value + } + + #[inline] + fn input(&self) -> &Bytes { + &self.input + } + + #[inline] + fn access_list(&self) -> Option<&AccessList> { + Some(&self.access_list) + } + + #[inline] + fn blob_versioned_hashes(&self) -> Option<&[B256]> { + None + } + + #[inline] + fn authorization_list(&self) -> Option<&[SignedAuthorization]> { + None + } +} + +impl Typed2718 for AutomatedTransaction { + fn ty(&self) -> u8 { + TransactionType::Custom as u8 + } +} + +impl AutomatedTransaction { + /// Returns true if automated transaction is gas-less, otherwise false. + /// GST type transactions are considered as gas-less. + pub fn is_gasless(&self) -> bool { + matches!(self.txn_type, AutomatedTransactionType::GST) + } +} + +/// Evm automated transaction with priority to be scheduled for execution. +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +pub struct AutomatedTransactionDetails { + /// Transaction details + pub txn: AutomatedTransaction, + /// Priority of the automated transaction to be scheduled. + /// The low value indicates higher priority. + pub priority: u64, +} + +type AccessListItemTy = ( + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Array>, +); +type AccessListTy = alloy_sol_types::sol_data::Array; +type ExpandedPayloadTy = ( + alloy_sol_types::sol_data::Uint<256>, + alloy_sol_types::sol_data::Address, + alloy_sol_types::sol_data::Bytes, + AccessListTy, +); + +/// Automation task state in native layer +#[derive(Clone, Debug, PartialEq, Eq)] +#[repr(u8)] +enum AutomationTaskState { + Pending = 0, + Active = 1, + Cancelled = 2, +} + +impl TryFrom for AutomationTaskState { + type Error = SupraExtensionError; + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::Pending), + 1 => Ok(Self::Active), + 2 => Ok(Self::Cancelled), + _ => Err(SupraExtensionError::InvalidAutomationTaskStateValue(value)), + } + } +} + +/// [`AutomatedTransactionBuilder`] result +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum BuildResult { + /// Success result wrapping [`AutomatedTransactionDetails`] + Success(AutomatedTransactionDetails), + /// Build failure due to gas-price limit surpass. + GasPriceLimitExceeded { + /// Gas price specified for the transaction + gas_price: u128, + /// Gas price threshold specified for the automation task during registration. + gas_price_cap: u128, + }, +} + +/// Builder for [`AutomatedTransactionDetails`] +/// All properties are mandatory to be set for successful automated transaction build. +/// The following values fall back to agreed defaults if not specified: +/// - priority - defaults to task-index +/// - access_list - default to empty access-list +/// - value - defaults to 0 +#[derive(Clone, Debug)] +pub struct AutomatedTransactionBuilder { + block_height: Option, + chain_id: Option, + gas_limit: Option, + gas_price: Option, + gas_price_cap: u128, + registration_hash: Option, + task_index: Option, + expiry_timestamp: Option, + owner: Option
, + tpy: Option, + priority: Option, + + to: Option
, + value: Option, + access_list: Option, + input: Option, +} + +#[allow(missing_docs)] +impl AutomatedTransactionBuilder { + pub fn new(gas_price_cap: u128) -> Self { + Self { + block_height: None, + chain_id: None, + gas_limit: None, + gas_price: None, + gas_price_cap, + registration_hash: None, + task_index: None, + expiry_timestamp: None, + owner: None, + tpy: None, + priority: None, + to: None, + value: Some(U256::from(0)), + access_list: Some(AccessList::default()), + input: None, + } + } + + pub fn block_height(mut self, block_height: u64) -> Self { + self.block_height = Some(block_height); + self + } + + pub fn chain_id(mut self, chain_id: ChainId) -> Self { + self.chain_id = Some(chain_id); + self + } + + pub fn gas_limit(mut self, gas_limit: u64) -> Self { + self.gas_limit = Some(gas_limit); + self + } + pub fn gas_price(mut self, gas_price: u128) -> Self { + self.gas_price = Some(gas_price); + self + } + pub fn gas_price_cap(mut self, gas_price_cap: u128) -> Self { + self.gas_price_cap = gas_price_cap; + self + } + pub fn registration_hash(mut self, registration_hash: B256) -> Self { + self.registration_hash = Some(registration_hash); + self + } + pub fn task_index(mut self, task_index: u64) -> Self { + self.task_index = Some(task_index); + self + } + pub fn expiry_timestamp(mut self, expiry_timestamp: u64) -> Self { + self.expiry_timestamp = Some(expiry_timestamp); + self + } + pub fn owner(mut self, owner: Address) -> Self { + self.owner = Some(owner); + self + } + pub fn tpy(mut self, tpy: AutomatedTransactionType) -> Self { + self.tpy = Some(tpy); + self + } + pub fn priority(mut self, priority: u64) -> Self { + self.priority = Some(priority); + self + } + pub fn to(mut self, to: Address) -> Self { + self.to = Some(to); + self + } + pub fn value(mut self, value: U256) -> Self { + self.value = Some(value); + self + } + pub fn access_list(mut self, access_list: AccessList) -> Self { + self.access_list = Some(access_list); + self + } + pub fn input(mut self, input: Bytes) -> Self { + self.input = Some(input); + self + } + pub fn build(self) -> Result { + let Self { + block_height, + chain_id, + gas_limit, + gas_price, + gas_price_cap, + registration_hash, + task_index, + expiry_timestamp: _, + owner, + tpy, + priority, + to, + value, + access_list, + input, + } = self; + let block_height = + value_or_error!(AutomatedTransactionBuilder, "block_height", block_height); + let chain_id = value_or_error!(AutomatedTransactionBuilder, "chain_id", chain_id); + let gas_limit = value_or_error!(AutomatedTransactionBuilder, "gas_limit", gas_limit); + let gas_price = value_or_error!(AutomatedTransactionBuilder, "gasPrice", gas_price); + let registration_hash = value_or_error!( + AutomatedTransactionBuilder, + "registration_hash", + registration_hash + ); + let task_index = value_or_error!(AutomatedTransactionBuilder, "task_index", task_index); + let owner = value_or_error!(AutomatedTransactionBuilder, "owner", owner); + let tpy = value_or_error!(AutomatedTransactionBuilder, "type", tpy); + let priority = priority.unwrap_or(task_index); + let to = value_or_error!(AutomatedTransactionBuilder, "to", to); + let value = value_or_error!(AutomatedTransactionBuilder, "value", value); + let access_list = value_or_error!(AutomatedTransactionBuilder, "access_list", access_list); + let input = value_or_error!(AutomatedTransactionBuilder, "input", input); + if gas_price_cap < gas_price { + return Ok(BuildResult::GasPriceLimitExceeded { + gas_price, + gas_price_cap, + }); + } + let txn = AutomatedTransaction { + block_height, + registration_hash, + sender: owner, + txn_type: tpy, + chain_id, + nonce: task_index, + gas_limit, + max_fee_per_gas: gas_price, + to, + value, + access_list, + input, + }; + Ok(BuildResult::Success(AutomatedTransactionDetails { + txn, + priority, + })) + } + + /// Checks whether the task/transaction can be considered as expired compared to the input + /// timestamp threshold value + /// If no expiry timestamp is specified, the potential underlying task is not considered as expired. + pub fn is_expired(&self, threshold: u64) -> bool { + self.expiry_timestamp + .map(|t| t < threshold) + .unwrap_or(false) + } +} + +/// Constructs [`AutomatedTransactionBuilder`] from automation task details loaded from chain state. +/// Fails if: +/// - inner payload cannot be deserialized based on the [`ExpandedPayloadTy`] schema +/// - Loaded task is not in active state (Active | Cancelled) +impl TryFrom for AutomatedTransactionBuilder { + type Error = SupraExtensionError; + + fn try_from(value: TaskDetails) -> Result { + let TaskDetails { + maxGasAmount, + gasPriceCap, + automationFeeCapForCycle: _, + lockedFeeForNextCycle: _, + txHash, + taskIndex, + registrationTime: _, + expiryTime, + owner, + state, + payloadTx, + auxData: _, + } = value; + + if AutomationTaskState::try_from(state)? == AutomationTaskState::Pending { + return Err(SupraExtensionError::InvalidAutomationTaskStateForBuilder); + } + + let (value, to, input, access_list) = ExpandedPayloadTy::abi_decode(payloadTx.as_ref())?; + let access_items = access_list + .into_iter() + .map(|(address, storage_keys)| AccessListItem { + address, + storage_keys, + }) + .collect(); + let builder = Self::new(gasPriceCap) + .gas_limit(maxGasAmount as u64) + .gas_price_cap(gasPriceCap) + .registration_hash(txHash) + .task_index(taskIndex) + .expiry_timestamp(expiryTime) + .owner(owner) + .to(to) + .value(value) + .input(input) + .access_list(AccessList(access_items)); + Ok(builder) + } +} + +#[cfg(test)] +mod test { + use crate::transactions::automated_transaction::ExpandedPayloadTy; + use alloy::hex; + use alloy_sol_types::SolType; + #[test] + fn check_decode() { + let encoded = hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b182f1488e8efeb2eb298155ed5bd7ff8a14042000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000242e1a7d4d0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000022220000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); + let (value, to, input, access_list) = ExpandedPayloadTy::abi_decode(&encoded).unwrap(); + println!("to: {:?}", to); + println!("value: {:?}", value); + println!("access_list: {:?}", access_list); + println!("input: {:?}", input); + } +} diff --git a/crates/supra-extension/src/transactions/automation_record.rs b/crates/supra-extension/src/transactions/automation_record.rs new file mode 100644 index 0000000000..e0d693584a --- /dev/null +++ b/crates/supra-extension/src/transactions/automation_record.rs @@ -0,0 +1,232 @@ +//! Automation registry transaction record definition to assist automation bookkeeping. +use crate::errors::SupraExtensionError; +use crate::supra_contract_bindings::supra_contracts_bindings::SupraContractsBindings::processTasksCall; +use crate::value_or_error; +use alloy::eips::eip2930::AccessList; +use alloy::primitives::{Address, Bytes, ChainId, TxKind, B256, U256}; +use alloy_consensus::transaction::Transaction; +use alloy_eips::eip2718::Typed2718; +use alloy_sol_types::SolCall; +use context::transaction::SignedAuthorization; +use context::TransactionType; +use primitives::supra_constants::VM_SIGNER; + +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +/// Transaction representing automation transaction record which will trigger automation task processing +/// during cycle transitions assisting automation bookkeeping flow. +pub struct AutomationRegistryRecord { + /// Address of the transaction sender. By default it will be `@evm_vm_signer` reserved addressed by supra. + pub sender: Address, + /// Height of the block in scope of which this transaction is being executed. + pub block_height: u64, + /// Chain id. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + pub chain_id: ChainId, + /// Index of the automation record being executed in scope of the block. + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + pub nonce: u64, + /// A scalar value equal to the maximum + /// amount of gas that should be used in executing + /// this transaction. Automation record execution will be gas-less, but it still will be guarded + /// by gas limit. + #[cfg_attr( + feature = "serde", + serde(with = "alloy_serde::quantity", rename = "gas", alias = "gasLimit") + )] + pub gas_limit: u64, + /// The 160-bit address of the message call’s recipient. + /// It will correspond to the address of the automation-registry/automation-controller SC deployed + /// by governance. + #[cfg_attr(feature = "serde", serde(default))] + pub to: Address, + /// Expected input data of the transaction + /// - Selector of automation registry record executor + /// - Index of the cycle for which automation registry record is scheduled for execution. + /// - List of the task indexes to be processed + pub input: Bytes, +} + +impl Transaction for AutomationRegistryRecord { + #[inline] + fn chain_id(&self) -> Option { + Some(self.chain_id) + } + + #[inline] + fn nonce(&self) -> u64 { + self.nonce + } + + #[inline] + fn gas_limit(&self) -> u64 { + self.gas_limit + } + + #[inline] + fn gas_price(&self) -> Option { + None + } + + #[inline] + fn max_fee_per_gas(&self) -> u128 { + 0 + } + + #[inline] + fn max_priority_fee_per_gas(&self) -> Option { + Some(0) + } + + #[inline] + fn max_fee_per_blob_gas(&self) -> Option { + None + } + + #[inline] + fn priority_fee_or_price(&self) -> u128 { + 0 + } + + fn effective_gas_price(&self, _base_fee: Option) -> u128 { + 0 + } + + #[inline] + fn is_dynamic_fee(&self) -> bool { + false + } + + #[inline] + fn kind(&self) -> TxKind { + TxKind::Call(self.to) + } + + #[inline] + fn is_create(&self) -> bool { + false + } + + #[inline] + fn value(&self) -> U256 { + U256::from(0) + } + + #[inline] + fn input(&self) -> &Bytes { + &self.input + } + + #[inline] + fn access_list(&self) -> Option<&AccessList> { + None + } + + #[inline] + fn blob_versioned_hashes(&self) -> Option<&[B256]> { + None + } + + #[inline] + fn authorization_list(&self) -> Option<&[SignedAuthorization]> { + None + } +} + +impl Typed2718 for AutomationRegistryRecord { + fn ty(&self) -> u8 { + TransactionType::Custom as u8 + } +} + +/// Builder for [`AutomationRegistryRecord`] +#[derive(Clone, Debug)] +pub struct AutomationRecordBuilder { + to: Address, + chain_id: Option, + block_height: Option, + nonce: Option, + gas_limit: Option, + task_indexes: Option>, + cycle_index: Option, +} + +#[allow(missing_docs)] +impl AutomationRecordBuilder { + /// New builder with the target address as input. + pub fn new(to: Address) -> Self { + Self { + to, + chain_id: None, + block_height: None, + nonce: None, + gas_limit: None, + task_indexes: None, + cycle_index: None, + } + } + pub fn block_height(mut self, block_height: u64) -> Self { + self.block_height = Some(block_height); + self + } + pub fn nonce(mut self, nonce: u64) -> Self { + self.nonce = Some(nonce); + self + } + + pub fn gas_limit(mut self, gas_limit: u64) -> Self { + self.gas_limit = Some(gas_limit); + self + } + pub fn task_indexes(mut self, task_indexes: Vec) -> Self { + self.task_indexes = Some(task_indexes); + self + } + + pub fn cycle_index(mut self, cycle_index: u64) -> Self { + self.cycle_index = Some(cycle_index); + self + } + + pub fn chain_id(mut self, chain_id: ChainId) -> Self { + self.chain_id = Some(chain_id); + self + } + + pub fn build(self) -> Result { + let Self { + to, + chain_id, + block_height, + nonce, + gas_limit, + task_indexes, + cycle_index, + } = self; + let block_height = value_or_error!(AutomationRecordBuilder, "block_height", block_height); + let nonce = value_or_error!(AutomationRecordBuilder, "nonce", nonce); + let task_indexes = value_or_error!(AutomationRecordBuilder, "task_indexes", task_indexes); + let gas_limit = value_or_error!(AutomationRecordBuilder, "gas_limit", gas_limit); + let cycle_index = value_or_error!(AutomationRecordBuilder, "cycle_index", cycle_index); + let chain_id = value_or_error!(AutomationRecordBuilder, "chain_id", chain_id); + + Ok(AutomationRegistryRecord { + sender: VM_SIGNER, + chain_id, + block_height, + nonce, + gas_limit, + to, + input: Self::get_process_tasks_payload(cycle_index, task_indexes), + }) + } + + fn get_process_tasks_payload(_cycle_index: u64, _task_indexes: Vec) -> Bytes { + let process_task_call = processTasksCall { + _cycleIndex: _cycle_index, + _taskIndexes: _task_indexes, + }; + Bytes::from(process_task_call.abi_encode()) + } +} diff --git a/crates/supra-extension/src/transactions/block_metadata.rs b/crates/supra-extension/src/transactions/block_metadata.rs new file mode 100644 index 0000000000..c9223d1297 --- /dev/null +++ b/crates/supra-extension/src/transactions/block_metadata.rs @@ -0,0 +1,203 @@ +//! Definition of the block metadata transaction which will be executed for every block +//! to aid block based checks to assist chain regular operations + +use crate::errors::SupraExtensionError; +use crate::supra_contract_bindings::supra_contracts_bindings::SupraContractsBindings::blockPrologueCall; +use crate::value_or_error; +use alloy::primitives::{Address, Bytes, ChainId, B256, U256}; +use alloy_consensus::transaction::Transaction; +use alloy_eips::eip2718::Typed2718; +use alloy_sol_types::SolCall; +use context::transaction::{AccessList, SignedAuthorization}; +use context::TransactionType; +use primitives::eip7825::TX_GAS_LIMIT_CAP; +use primitives::supra_constants::VM_SIGNER; +use primitives::TxKind; + +/// EVM system transaction generated based on the block sent for execution. +/// Will trigger `BlockMeta::block_prologue` supra-evm SC API execution to meat +/// other `supra-evm` SC checks requiring per-block execution. +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] +pub struct BlockMetadata { + /// Id of the chain in scope of which block is being executed + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + pub chain_id: ChainId, + /// Sender of the transaction. By default, will be agreed @evm_vm_signer + pub sender: Address, + /// A height of the block based on which this transaction is created + #[cfg_attr(feature = "serde", serde(with = "alloy_serde::quantity"))] + pub height: u64, + /// Hash of the block being executed + pub block_hash: B256, + /// Block creation timestamp in seconds + pub timestamp: U256, + /// The 160-bit address of the message call’s recipient + #[cfg_attr(feature = "serde", serde(default))] + pub to: Address, + /// An unlimited size byte array specifying the + /// input data of the message call. + pub input: Bytes, +} + +impl Transaction for BlockMetadata { + #[inline] + fn chain_id(&self) -> Option { + Some(self.chain_id) + } + + #[inline] + fn nonce(&self) -> u64 { + self.height + } + + #[inline] + fn gas_limit(&self) -> u64 { + TX_GAS_LIMIT_CAP + } + + #[inline] + fn gas_price(&self) -> Option { + None + } + + #[inline] + fn max_fee_per_gas(&self) -> u128 { + 0 + } + + #[inline] + fn max_priority_fee_per_gas(&self) -> Option { + Some(0) + } + + #[inline] + fn max_fee_per_blob_gas(&self) -> Option { + None + } + + #[inline] + fn priority_fee_or_price(&self) -> u128 { + 0 + } + + fn effective_gas_price(&self, _base_fee: Option) -> u128 { + 0 + } + + #[inline] + fn is_dynamic_fee(&self) -> bool { + false + } + + #[inline] + fn kind(&self) -> TxKind { + TxKind::Call(self.to) + } + + #[inline] + fn is_create(&self) -> bool { + false + } + + #[inline] + fn value(&self) -> U256 { + U256::from(0) + } + + #[inline] + fn input(&self) -> &Bytes { + &self.input + } + + #[inline] + fn access_list(&self) -> Option<&AccessList> { + None + } + + #[inline] + fn blob_versioned_hashes(&self) -> Option<&[B256]> { + None + } + + #[inline] + fn authorization_list(&self) -> Option<&[SignedAuthorization]> { + None + } +} +impl Typed2718 for BlockMetadata { + fn ty(&self) -> u8 { + TransactionType::Custom as u8 + } +} + +/// Builder for [`BlockMetadata`] transaction. +/// All properties are mandatory. +#[derive(Clone, Debug)] +pub struct BlockMetadataBuilder { + to: Address, + height: Option, + block_hash: Option, + timestamp: Option, + chain_id: Option, +} + +#[allow(missing_docs)] +impl BlockMetadataBuilder { + pub fn new(to: Address) -> Self { + Self { + to, + height: None, + block_hash: None, + timestamp: None, + chain_id: None, + } + } + pub fn height(mut self, height: u64) -> Self { + self.height = Some(height); + self + } + + pub fn block_hash(mut self, block_hash: B256) -> Self { + self.block_hash = Some(block_hash); + self + } + pub fn chain_id(mut self, chain_id: u64) -> Self { + self.chain_id = Some(chain_id); + self + } + + pub fn timestamp(mut self, timestamp: U256) -> Self { + self.timestamp = Some(timestamp); + self + } + + pub fn build(self) -> Result { + let Self { + to, + height, + block_hash, + timestamp, + chain_id, + } = self; + let height = value_or_error!(BlockMetadataBuilder, "height", height); + let block_hash = value_or_error!(BlockMetadataBuilder, "block_hash", block_hash); + let timestamp = value_or_error!(BlockMetadataBuilder, "timestamp", timestamp); + let chain_id = value_or_error!(BlockMetadataBuilder, "chain_id", chain_id); + + Ok(BlockMetadata { + chain_id, + sender: VM_SIGNER, + height, + block_hash, + timestamp, + to, + input: Self::get_block_prologue(), + }) + } + + fn get_block_prologue() -> Bytes { + Bytes::from(blockPrologueCall.abi_encode()) + } +} diff --git a/crates/supra-extension/src/transactions/mod.rs b/crates/supra-extension/src/transactions/mod.rs new file mode 100644 index 0000000000..ef7b8c51d4 --- /dev/null +++ b/crates/supra-extension/src/transactions/mod.rs @@ -0,0 +1,4 @@ +//! Set of transactions introduced as part of the supra extension +pub mod automated_transaction; +pub mod automation_record; +pub mod block_metadata; diff --git a/solidity/supra_contracts/foundry.toml b/solidity/supra_contracts/foundry.toml index eb22be94ce..b1b1fa7da9 100644 --- a/solidity/supra_contracts/foundry.toml +++ b/solidity/supra_contracts/foundry.toml @@ -4,5 +4,9 @@ out = "out" libs = ["lib"] via_ir = true optimizer = true +# Uncomment when running agains supra chain +# eth_rpc_url = "http://localhost:27000/rpc/v1/eth/wallet_integration" # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options + + diff --git a/solidity/supra_contracts/lib/forge-std b/solidity/supra_contracts/lib/forge-std index aeb45e9f32..27ba11c86a 160000 --- a/solidity/supra_contracts/lib/forge-std +++ b/solidity/supra_contracts/lib/forge-std @@ -1 +1 @@ -Subproject commit aeb45e9f32ef8ca78f0aeda17596e9c46374da41 +Subproject commit 27ba11c86ac93d8d4a50437ae26621468fe63c20 diff --git a/solidity/supra_contracts/lib/openzeppelin-contracts b/solidity/supra_contracts/lib/openzeppelin-contracts index 8614ef7a24..fcbae5394a 160000 --- a/solidity/supra_contracts/lib/openzeppelin-contracts +++ b/solidity/supra_contracts/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 8614ef7a24d476e37db66054e5237faaf7f43717 +Subproject commit fcbae5394ae8ad52d8e580a3477db99814b9d565 diff --git a/solidity/supra_contracts/lib/openzeppelin-contracts-upgradeable b/solidity/supra_contracts/lib/openzeppelin-contracts-upgradeable index a73231f64c..aa677e9d28 160000 --- a/solidity/supra_contracts/lib/openzeppelin-contracts-upgradeable +++ b/solidity/supra_contracts/lib/openzeppelin-contracts-upgradeable @@ -1 +1 @@ -Subproject commit a73231f64c2a4ab1c0bceb43ba8333be45d2df0a +Subproject commit aa677e9d28ed78fc427ec47ba2baef2030c58e7c diff --git a/solidity/supra_contracts/script/DeployAutomationRegistry.s.sol b/solidity/supra_contracts/script/DeployAutomationRegistry.s.sol index 5955c1bcc7..5a50b30559 100644 --- a/solidity/supra_contracts/script/DeployAutomationRegistry.s.sol +++ b/solidity/supra_contracts/script/DeployAutomationRegistry.s.sol @@ -5,6 +5,7 @@ import {Script, console} from "forge-std/Script.sol"; import {AutomationCore} from "../src/AutomationCore.sol"; import {AutomationController} from "../src/AutomationController.sol"; import {AutomationRegistry} from "../src/AutomationRegistry.sol"; +import {LibConfig} from "../src/LibConfig.sol"; import {ERC1967Proxy} from "../lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract DeployAutomationRegistry is Script { @@ -52,45 +53,68 @@ contract DeployAutomationRegistry is Script { ERC1967Proxy registryProxy; // AutomationRegistry proxy contract AutomationRegistry registry; // Instance of AutomationRegistry at proxy address - AutomationController controllerImpl; // AutomationController implementation contract + AutomationController controllerImpl; // AutomationController implementation contract ERC1967Proxy controllerProxy; // AutomationController proxy contract - AutomationController controller; // Instance of AutomationController at proxy address + + + // --------------------------------------------------------------------- + // Pre-compute proxy addresses for all contracts + // --------------------------------------------------------------------- + uint256 currentNonce = vm.getNonce(msg.sender); + // nonce+0: AutomationCore impl + // nonce+1: AutomationCore proxy + // nonce+2: AutomationRegistry impl + // nonce+3: AutomationRegistry proxy + // nonce+4: AutomationController impl + // nonce+5: AutomationController proxy + address coreProxyAddr = computeCreateAddress(msg.sender, currentNonce + 1); + address registryProxyAddr = computeCreateAddress(msg.sender, currentNonce + 3); + address controllerProxyAddr = computeCreateAddress(msg.sender, currentNonce + 5); + + console.log("Pre-computed AutomationCore proxy address: ", coreProxyAddr); + console.log("Pre-computed AutomationRegistry proxy address: ", registryProxyAddr); + console.log("Pre-computed AutomationController proxy address: ", controllerProxyAddr); // --------------------------------------------------------------------- // Deploy AutomationCore // --------------------------------------------------------------------- coreImpl = new AutomationCore(); console.log("AutomationCore implementation deployed at: ", address(coreImpl)); - bytes memory coreInitData = abi.encodeCall( - AutomationCore.initialize, - ( - taskDurationCapSecs, // taskDurationCapSecs - registryMaxGasCap, // registryMaxGasCap - automationBaseFeeWeiPerSec, // automationBaseFeeWeiPerSec - flatRegistrationFeeWei, // flatRegistrationFeeWei - congestionThresholdPercentage, // congestionThresholdPercentage - congestionBaseFeeWeiPerSec, // congestionBaseFeeWeiPerSec - congestionExponent, // congestionExponent - taskCapacity, // taskCapacity - cycleDurationSecs, // cycleDurationSecs - sysTaskDurationCapSecs, // sysTaskDurationCapSecs - sysRegistryMaxGasCap, // sysRegistryMaxGasCap - sysTaskCapacity, // sysTaskCapacity - vmSigner, // VM Signer address - erc20Supra // ERC20Supra address - ) - ); + + LibConfig.InitializeParams memory coreParams = LibConfig.InitializeParams({ + taskDurationCapSecs: taskDurationCapSecs, + registryMaxGasCap: registryMaxGasCap, + automationBaseFeeWeiPerSec: automationBaseFeeWeiPerSec, + flatRegistrationFeeWei: flatRegistrationFeeWei, + congestionThresholdPercentage: congestionThresholdPercentage, + congestionBaseFeeWeiPerSec: congestionBaseFeeWeiPerSec, + congestionExponent: congestionExponent, + taskCapacity: taskCapacity, + cycleDurationSecs: cycleDurationSecs, + sysTaskDurationCapSecs: sysTaskDurationCapSecs, + sysRegistryMaxGasCap: sysRegistryMaxGasCap, + sysTaskCapacity: sysTaskCapacity, + vmSigner: vmSigner, + erc20Supra: erc20Supra, + controller: controllerProxyAddr, + registry: registryProxyAddr, + owner: msg.sender + }); + + bytes memory coreInitData = abi.encodeCall(AutomationCore.initialize, (coreParams)); coreProxy = new ERC1967Proxy(address(coreImpl), coreInitData); console.log("AutomationCore proxy deployed at: ", address(coreProxy)); - automationCore = AutomationCore(address(coreProxy)); // --------------------------------------------------------------------- // Deploy AutomationRegistry // --------------------------------------------------------------------- registryImpl = new AutomationRegistry(); console.log("AutomationRegistry implementation deployed at: ", address(registryImpl)); - - bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore))); + + bytes memory registryInitData = abi.encodeCall( + AutomationRegistry.initialize, + (coreProxyAddr, controllerProxyAddr, msg.sender) + ); registryProxy = new ERC1967Proxy(address(registryImpl), registryInitData); console.log("AutomationRegistry proxy deployed at: ", address(registryProxy)); registry = AutomationRegistry(address(registryProxy)); @@ -100,29 +124,13 @@ contract DeployAutomationRegistry is Script { // --------------------------------------------------------------------- controllerImpl = new AutomationController(); console.log("AutomationController implementation deployed at: ", address(controllerImpl)); - + bytes memory controllerInitData = abi.encodeCall( AutomationController.initialize, - ( - address(automationCore), - address(registry), - true - ) + (coreProxyAddr, registryProxyAddr, msg.sender, true, cycleDurationSecs) ); controllerProxy = new ERC1967Proxy(address(controllerImpl), controllerInitData); console.log("AutomationController proxy deployed at: ", address(controllerProxy)); - controller = AutomationController(address(controllerProxy)); - - // -------------------------------------------------------------------------- - // Set AutomationRegistry and AutomationController address in AutomationCore - // -------------------------------------------------------------------------- - automationCore.setAutomationRegistry(address(registry)); - automationCore.setAutomationController(address(controller)); - - // -------------------------------------------------------------------------- - // Set AutomationController address in AutomationRegistry - // -------------------------------------------------------------------------- - registry.setAutomationController(address(controller)); vm.stopBroadcast(); } diff --git a/solidity/supra_contracts/script/DeployBlockMeta.s.sol b/solidity/supra_contracts/script/DeployBlockMeta.s.sol index 54ede968a9..0505e25841 100644 --- a/solidity/supra_contracts/script/DeployBlockMeta.s.sol +++ b/solidity/supra_contracts/script/DeployBlockMeta.s.sol @@ -8,10 +8,12 @@ import {ERC1967Proxy} from "../lib/openzeppelin-contracts/contracts/proxy/ERC196 contract DeployBlockMeta is Script { address automationController; bytes4 selector; + address owner; function setUp() public { automationController = vm.envAddress("AUTOMATION_CONTROLLER"); - selector = bytes4(keccak256("monitorCycleEnd()")); + selector = bytes4(keccak256("monitorCycleEnd()")); + owner = vm.envAddress("OWNER"); } function run() public { @@ -23,7 +25,7 @@ contract DeployBlockMeta is Script { // Deploy BlockMeta proxy - bytes memory initData = abi.encodeCall(BlockMeta.initialize, ()); + bytes memory initData = abi.encodeCall(BlockMeta.initialize, owner); ERC1967Proxy proxy = new ERC1967Proxy(address(impl), initData); console.log("BlockMeta proxy deployed at: ", address(proxy)); diff --git a/solidity/supra_contracts/script/MintErc20Supra.s.sol b/solidity/supra_contracts/script/MintErc20Supra.s.sol new file mode 100644 index 0000000000..22336c7ca2 --- /dev/null +++ b/solidity/supra_contracts/script/MintErc20Supra.s.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import {Script, console} from "forge-std/Script.sol"; +import {ERC20Supra} from "../src/ERC20Supra.sol"; + +contract MintErc20Supra is Script { + uint64 value; + uint64 allowance; + address payable erc20supra; + address authority; + + // Config values loaded from .env file + function setUp() public { + value = uint64(vm.envUint("VALUE")); + allowance = uint64(vm.envUint("ALLOWANCE")); + erc20supra = payable(vm.envAddress("ERC20SUPRA")); + authority = vm.envAddress("AUTOMATION_CORE"); + } + + function run() public { + vm.startBroadcast(); + + ERC20Supra erc20supraImpl = ERC20Supra(erc20supra); + console.log("Sender ", msg.sender); + console.log("Token balance ", erc20supraImpl.balanceOf(msg.sender)); + + erc20supraImpl.nativeToErc20SupraWithAllowance{value: value}(authority, uint256(allowance)); + + console.log("Sender ", msg.sender); + console.log("Token balance ", erc20supraImpl.balanceOf(msg.sender)); + + vm.stopBroadcast(); + } + +} diff --git a/solidity/supra_contracts/script/RegisterAutomationTask.s.sol b/solidity/supra_contracts/script/RegisterAutomationTask.s.sol new file mode 100644 index 0000000000..03dfed8fd0 --- /dev/null +++ b/solidity/supra_contracts/script/RegisterAutomationTask.s.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import {Script, console} from "forge-std/Script.sol"; +import {IAutomationRegistry} from "../src/IAutomationRegistry.sol"; +import {CommonUtils} from "../src/CommonUtils.sol"; +import {IERC20} from "../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {LibConfig} from "../src/LibConfig.sol"; +import {TxHashPrecompile} from "./TxHashPrecompile.sol"; + +contract RegisterAutomationTask is Script { + uint64 taskDurationSecs; + uint64 automationFeeCap; + uint128 taskMaxGas; + uint128 taskGasPriceCap; + address registry; + address erc20supra; + address target; + + address public constant TX_HASH_PRECOMPILE = 0x0000000000000000000000000000000053555001; + // Config values loaded from .env file + function setUp() public { + taskDurationSecs = uint64(vm.envUint("TASK_DURATION_SEC")); + taskMaxGas = uint128(vm.envUint("TASK_MAX_GAS")); + taskGasPriceCap = uint128(vm.envUint("TASK_GAS_PRICE_CAP")); + registry = vm.envAddress("REGISTRY"); + erc20supra = vm.envAddress("ERC20SUPRA"); + target = vm.envAddress("TARGET"); + automationFeeCap = uint64(vm.envUint("TASK_AUTOMATION_FEE_CAP")); + + // Deploy TxHashPrecompile and etch its runtime code at the precompile address + // Helps with precompilation but not with simulation, so one need to run the script with --skip-simualation flag + TxHashPrecompile deployed = new TxHashPrecompile(); + vm.etch(TX_HASH_PRECOMPILE, address(deployed).code); + } + + function run() public { + vm.startBroadcast(); + IAutomationRegistry registryImpl = IAutomationRegistry(registry); + bytes[] memory auxData; + uint64 taskIdx = registryImpl.getNextTaskIndex(); + console.log("Next task index ", taskIdx); + + bytes memory payload = createPayload(0, target, erc20supra); + + registryImpl.register( + payload, + uint64(block.timestamp + taskDurationSecs), // Task expires before next cycle + taskMaxGas, + taskGasPriceCap, + automationFeeCap, + 0, + auxData + ); + + vm.stopBroadcast(); + } + + function createPayload(uint128 _value, address recipient, address cAddress) private pure returns (bytes memory) { + LibConfig.AccessListEntry[] memory accessList = new LibConfig.AccessListEntry[](0); + bytes memory callData = abi.encodeCall(IERC20.transfer, (recipient, 100)); + bytes memory payload = abi.encode(_value, cAddress, callData, accessList); + + return payload; + } + +} diff --git a/solidity/supra_contracts/script/TxHashPrecompile.sol b/solidity/supra_contracts/script/TxHashPrecompile.sol new file mode 100644 index 0000000000..cd56ff74e1 --- /dev/null +++ b/solidity/supra_contracts/script/TxHashPrecompile.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + + +contract TxHashPrecompile { + fallback(bytes calldata input) external returns (bytes memory) { + bytes32 output = keccak256("txn_hash"); + return abi.encode( output); + } +} diff --git a/solidity/supra_contracts/src/AutomationController.sol b/solidity/supra_contracts/src/AutomationController.sol index 5f035786ff..e2f5ba6914 100644 --- a/solidity/supra_contracts/src/AutomationController.sol +++ b/solidity/supra_contracts/src/AutomationController.sol @@ -90,12 +90,15 @@ contract AutomationController is IAutomationController, Ownable2StepUpgradeable, /// @notice Initializes the configuration parameters of the contract, can only be called once. /// @param _automationCore Address of the AutomationCore smart contract. /// @param _registry Address of the AutomationRegistry smart contract. + /// @param _owner Address of the contract owner. /// @param _automationEnabled Bool to set automation enabled status. - function initialize(address _automationCore, address _registry, bool _automationEnabled) public initializer { - _automationCore.validateContractAddress(); - _registry.validateContractAddress(); + /// @param _cycleDurationSecs uint64 to set automation cycle duration + function initialize(address _automationCore, address _registry, address _owner, bool _automationEnabled, uint64 _cycleDurationSecs) public initializer { + _automationCore.validateAddress(); + _registry.validateAddress(); + _owner.validateAddress(); - automationCore = _automationCore; + automationCore = _automationCore; registry = _registry; (CommonUtils.CycleState state, uint64 cycleId) = _automationEnabled ? (CommonUtils.CycleState.STARTED, 1) : (CommonUtils.CycleState.READY, 0); @@ -103,13 +106,13 @@ contract AutomationController is IAutomationController, Ownable2StepUpgradeable, cycleInfo.initializeCycle( cycleId, uint64(block.timestamp), - IAutomationCore(_automationCore).cycleDurationSecs(), + _cycleDurationSecs, state, _automationEnabled - ); + ); __Ownable2Step_init(); - __Ownable_init(msg.sender); + __Ownable_init(_owner); } /// @notice Called by the VM Signer on `AutomationBookkeepingAction::Process` action emitted by native layer ahead of the cycle transition. diff --git a/solidity/supra_contracts/src/AutomationCore.sol b/solidity/supra_contracts/src/AutomationCore.sol index 313e34d109..ea44a3b2c5 100644 --- a/solidity/supra_contracts/src/AutomationCore.sol +++ b/solidity/supra_contracts/src/AutomationCore.sol @@ -98,78 +98,71 @@ contract AutomationCore is IAutomationCore, Ownable2StepUpgradeable, UUPSUpgrade } /// @notice Initializes the configuration parameters of the registry, can only be called once. - /// @param _taskDurationCapSecs Maximum allowable duration (in seconds) from the registration time that a user automation task can run. - /// @param _registryMaxGasCap Maximum gas allocation for automation tasks per cycle. - /// @param _automationBaseFeeWeiPerSec Base fee per second for the full capacity of the automation registry, measured in wei/sec. - /// @param _flatRegistrationFeeWei Flat registration fee charged by default for each task. - /// @param _congestionThresholdPercentage Percentage representing the acceptable upper limit of committed gas amount relative to registry_max_gas_cap. - /// Beyond this threshold, congestion fees apply. - /// @param _congestionBaseFeeWeiPerSec Base fee per second for the full capacity of the automation registry when the congestion threshold is exceeded. - /// @param _congestionExponent The congestion fee increases exponentially based on this value, ensuring higher fees as the registry approaches full capacity. - /// @param _taskCapacity Maximum number of tasks that the registry can hold. - /// @param _cycleDurationSecs Automation cycle duration in seconds. - /// @param _sysTaskDurationCapSecs Maximum allowable duration (in seconds) from the registration time that a system automation task can run. - /// @param _sysRegistryMaxGasCap Maximum gas allocation for system automation tasks per cycle. - /// @param _sysTaskCapacity Maximum number of system tasks that the registry can hold. - /// @param _vmSigner Address for the VM Signer. - /// @param _erc20Supra Address of the ERC20Supra contract. - function initialize( - uint64 _taskDurationCapSecs, - uint128 _registryMaxGasCap, - uint128 _automationBaseFeeWeiPerSec, - uint128 _flatRegistrationFeeWei, - uint8 _congestionThresholdPercentage, - uint128 _congestionBaseFeeWeiPerSec, - uint8 _congestionExponent, - uint16 _taskCapacity, - uint64 _cycleDurationSecs, - uint64 _sysTaskDurationCapSecs, - uint128 _sysRegistryMaxGasCap, - uint16 _sysTaskCapacity, - address _vmSigner, - address _erc20Supra - ) public initializer { + /// @param params Struct containing all initialization parameters: + /// - taskDurationCapSecs: Maximum allowable duration (in seconds) from the registration time that a user automation task can run. + /// - registryMaxGasCap: Maximum gas allocation for automation tasks per cycle. + /// - automationBaseFeeWeiPerSec: Base fee per second for the full capacity of the automation registry, measured in wei/sec. + /// - flatRegistrationFeeWei: Flat registration fee charged by default for each task. + /// - congestionThresholdPercentage: Percentage representing the acceptable upper limit of committed gas amount relative to registry_max_gas_cap. + /// Beyond this threshold, congestion fees apply. + /// - congestionBaseFeeWeiPerSec: Base fee per second for the full capacity of the automation registry when the congestion threshold is exceeded. + /// - congestionExponent: The congestion fee increases exponentially based on this value, ensuring higher fees as the registry approaches full capacity. + /// - taskCapacity: Maximum number of tasks that the registry can hold. + /// - cycleDurationSecs: Automation cycle duration in seconds. + /// - sysTaskDurationCapSecs: Maximum allowable duration (in seconds) from the registration time that a system automation task can run. + /// - sysRegistryMaxGasCap: Maximum gas allocation for system automation tasks per cycle. + /// - sysTaskCapacity: Maximum number of system tasks that the registry can hold. + /// - vmSigner: Address for the VM Signer. + /// - erc20Supra: Address of the ERC20Supra contract. + /// - controller: Address of the AutomationController contract. + /// - registry: Address of the AutomationRegistry contract. + /// - owner: Address of the contract owner. + function initialize(LibConfig.InitializeParams calldata params) public initializer { validateConfigParameters( - _taskDurationCapSecs, - _registryMaxGasCap, - _congestionThresholdPercentage, - _congestionExponent, - _taskCapacity, - _cycleDurationSecs, - _sysTaskDurationCapSecs, - _sysRegistryMaxGasCap, - _sysTaskCapacity + params.taskDurationCapSecs, + params.registryMaxGasCap, + params.congestionThresholdPercentage, + params.congestionExponent, + params.taskCapacity, + params.cycleDurationSecs, + params.sysTaskDurationCapSecs, + params.sysRegistryMaxGasCap, + params.sysTaskCapacity ); - if(_vmSigner == address(0)) revert AddressCannotBeZero(); - _erc20Supra.validateContractAddress(); - + params.vmSigner.validateAddress(); + params.owner.validateAddress(); + params.erc20Supra.validateContractAddress(); + params.controller.validateAddress(); + params.registry.validateAddress(); LibConfig.Config memory config = LibConfig.createConfig( - _registryMaxGasCap, - _sysRegistryMaxGasCap, - _automationBaseFeeWeiPerSec, - _flatRegistrationFeeWei, - _congestionBaseFeeWeiPerSec, - _taskDurationCapSecs, - _sysTaskDurationCapSecs, - _cycleDurationSecs, - _taskCapacity, - _sysTaskCapacity, - _congestionThresholdPercentage, - _congestionExponent + params.registryMaxGasCap, + params.sysRegistryMaxGasCap, + params.automationBaseFeeWeiPerSec, + params.flatRegistrationFeeWei, + params.congestionBaseFeeWeiPerSec, + params.taskDurationCapSecs, + params.sysTaskDurationCapSecs, + params.cycleDurationSecs, + params.taskCapacity, + params.sysTaskCapacity, + params.congestionThresholdPercentage, + params.congestionExponent ); - + regConfig = LibConfig.createRegistryConfig( - _registryMaxGasCap, - _sysRegistryMaxGasCap, + params.registryMaxGasCap, + params.sysRegistryMaxGasCap, true, - _vmSigner, - _erc20Supra, - config + params.vmSigner, + params.erc20Supra, + config ); + regConfig.setAutomationController(params.controller); + regConfig.registry = params.registry; __Ownable2Step_init(); - __Ownable_init(msg.sender); + __Ownable_init(params.owner); } // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: HELPER FUNCTIONS :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @@ -534,7 +527,7 @@ contract AutomationCore is IAutomationCore, Ownable2StepUpgradeable, UUPSUpgrade return _safeUnlockLockedDeposit(_taskIndex, _lockedDeposit); } - /// @notice Refunds the deposit fee and any autoamtion fees of the task. + /// @notice Refunds the deposit fee and any automation fees of the task. function refundTaskFees( uint64 _currentTime, uint64 _refundDuration, @@ -644,7 +637,7 @@ contract AutomationCore is IAutomationCore, Ownable2StepUpgradeable, UUPSUpgrade gasCommittedForNextCycle = regConfig.gasCommittedForNextCycle(); uint128 estimatedAutomationFeeForCycle = estimateAutomationFeeWithCommittedOccupancyInternal(_maxGasAmount, gasCommittedForNextCycle); - if(_automationFeeCapForCycle < estimatedAutomationFeeForCycle) { revert InsufficientFeeCapForCycle(); } + if(_automationFeeCapForCycle < estimatedAutomationFeeForCycle) { revert InsufficientFeeCapForCycle(uint64(estimatedAutomationFeeForCycle)); } taskDurationCap = regConfig.taskDurationCapSecs(); nextCycleRegistryMaxGasCap = regConfig.nextCycleRegistryMaxGasCap(); diff --git a/solidity/supra_contracts/src/AutomationRegistry.sol b/solidity/supra_contracts/src/AutomationRegistry.sol index cbd6071532..a8e7df2c36 100644 --- a/solidity/supra_contracts/src/AutomationRegistry.sol +++ b/solidity/supra_contracts/src/AutomationRegistry.sol @@ -82,13 +82,18 @@ contract AutomationRegistry is IAutomationRegistry, Ownable2StepUpgradeable, UUP /// @notice Initializes the owner and AutomationCore contract address, can only be called once. /// @param _automationCore Address of the AutomationCore contract. - function initialize(address _automationCore) public initializer { - _automationCore.validateContractAddress(); - + /// @param _automationController Address of the AutomationController contract. + /// @param _owner Address of the contract owner. + function initialize(address _automationCore, address _automationController, address _owner) public initializer { + _automationCore.validateAddress(); + _automationController.validateAddress(); + if(_owner == address(0)) revert CommonUtils.AddressCannotBeZero(); + automationCore = _automationCore; + automationController = _automationController; __Ownable2Step_init(); - __Ownable_init(msg.sender); + __Ownable_init(_owner); } // ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: TASKS RELATED FUNCTIONS ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @@ -111,7 +116,14 @@ contract AutomationRegistry is IAutomationRegistry, Ownable2StepUpgradeable, UUP bytes[] memory _auxData ) external { uint64 regTime = uint64(block.timestamp); - + + + (bool ok, bytes memory out) = TX_HASH_PRECOMPILE.staticcall(""); + require(ok, "txhash precompile call failed"); + + if (out.length != 32) { revert TxnHashLengthShouldBe32(uint64 (out.length)); } + bytes32 _txHash = bytes32(out); + IAutomationCore core = IAutomationCore(automationCore); core.updateStateForValidRegistration( totalTasks(), diff --git a/solidity/supra_contracts/src/BlockMeta.sol b/solidity/supra_contracts/src/BlockMeta.sol index 5f839debb3..a7756e2444 100644 --- a/solidity/supra_contracts/src/BlockMeta.sol +++ b/solidity/supra_contracts/src/BlockMeta.sol @@ -75,8 +75,8 @@ contract BlockMeta is OwnableUpgradeable, UUPSUpgradeable { } /// @notice Initializes the owner of the contract. - function initialize() public initializer { - __Ownable_init(msg.sender); + function initialize(address initial_owner) public initializer { + __Ownable_init(initial_owner); } /** diff --git a/solidity/supra_contracts/src/CommonUtils.sol b/solidity/supra_contracts/src/CommonUtils.sol index 14215de15a..a43d8528ce 100644 --- a/solidity/supra_contracts/src/CommonUtils.sol +++ b/solidity/supra_contracts/src/CommonUtils.sol @@ -115,6 +115,11 @@ library CommonUtils { if (!isContract(_contractAddr)) { revert AddressCannotBeEOA(); } } + /// @notice Validates a contract address. + function validateAddress(address _contractAddr) internal view { + if (_contractAddr == address(0)) { revert AddressCannotBeZero(); } + } + /// @notice Checks if an address is VM Signer. /// @param _addr Address to check. /// @return bool If it is VM Signer. diff --git a/solidity/supra_contracts/src/IAutomationCore.sol b/solidity/supra_contracts/src/IAutomationCore.sol index 1fc8a80b6f..0a5ca472f2 100644 --- a/solidity/supra_contracts/src/IAutomationCore.sol +++ b/solidity/supra_contracts/src/IAutomationCore.sol @@ -21,7 +21,7 @@ interface IAutomationCore { error GasCommittedExceedsMaxGasCap(); error GasCommittedValueUnderflow(); error InsufficientBalance(); - error InsufficientFeeCapForCycle(); + error InsufficientFeeCapForCycle(uint64 expected); error InsufficientBalanceForRefund(); error InvalidCongestionExponent(); error InvalidCongestionThreshold(); diff --git a/solidity/supra_contracts/src/IAutomationRegistry.sol b/solidity/supra_contracts/src/IAutomationRegistry.sol index 8c0462a0cb..3916a576ee 100644 --- a/solidity/supra_contracts/src/IAutomationRegistry.sol +++ b/solidity/supra_contracts/src/IAutomationRegistry.sol @@ -31,6 +31,7 @@ interface IAutomationRegistry { function getTaskIdList() external view returns (uint256[] memory); function getTotalActiveTasks() external view returns (uint256); function totalTasks() external view returns (uint256); + function getNextTaskIndex() external view returns (uint64); // State updating functions function removeTask(uint64 _taskIndex, bool _removeFromSysReg) external; @@ -42,4 +43,14 @@ interface IAutomationRegistry { uint128 _refundableDeposit, uint128 _lockedDeposit ) external; + + function register( + bytes memory _payloadTx, + uint64 _expiryTime, + uint128 _maxGasAmount, + uint128 _gasPriceCap, + uint128 _automationFeeCapForCycle, + uint64 _priority, + bytes[] memory _auxData + ) external; } diff --git a/solidity/supra_contracts/src/LibConfig.sol b/solidity/supra_contracts/src/LibConfig.sol index ec86fa22c1..4ef0d16683 100644 --- a/solidity/supra_contracts/src/LibConfig.sol +++ b/solidity/supra_contracts/src/LibConfig.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT + // SPDX-License-Identifier: MIT pragma solidity 0.8.27; // Helper library used by AutomationConfig. @@ -341,6 +341,27 @@ library LibConfig { uint8 congestionExponent; } + /// @notice Struct representing initialization parameters for AutomationCore. + struct InitializeParams { + uint64 taskDurationCapSecs; + uint128 registryMaxGasCap; + uint128 automationBaseFeeWeiPerSec; + uint128 flatRegistrationFeeWei; + uint8 congestionThresholdPercentage; + uint128 congestionBaseFeeWeiPerSec; + uint8 congestionExponent; + uint16 taskCapacity; + uint64 cycleDurationSecs; + uint64 sysTaskDurationCapSecs; + uint128 sysRegistryMaxGasCap; + uint16 sysTaskCapacity; + address vmSigner; + address erc20Supra; + address controller; + address registry; + address owner; + } + function getConfig(Config memory cfg) internal pure returns (ConfigDetails memory config) { // ------------------------------------------------------------- // 1. registryMaxGasCap (high 128) | sysRegistryMaxGasCap (low 128) diff --git a/solidity/supra_contracts/src/SupraContractsBindings.sol b/solidity/supra_contracts/src/SupraContractsBindings.sol new file mode 100644 index 0000000000..23039776a1 --- /dev/null +++ b/solidity/supra_contracts/src/SupraContractsBindings.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.27; + +import {CommonUtils} from "./CommonUtils.sol"; + +interface SupraContractsBindings { + + // View functions of AutomationRegistry + function ifTaskExists(uint64 _taskIndex) external view returns (bool); + function getAllActiveTaskIds() external view returns (uint256[] memory); + function getTaskIdList() external view returns (uint256[] memory); + function isAutomationEnabled() external view returns (bool); + + function getTaskDetails(uint64 _taskIndex) external view returns (CommonUtils.TaskDetails memory); + function getTaskDetailsBulk(uint64[] memory _taskIndexes) external view returns (CommonUtils.TaskDetails[] memory); + + // View functions of AutomationController + function getCycleInfo() external view returns(uint64, uint64, uint64, CommonUtils.CycleState); + function getTransitionInfo() external view returns (uint64, uint128); + + // Entry function to be called by node runtime for bookkeeping + function processTasks(uint64 _cycleIndex, uint64[] memory _taskIndexes) external; + + // Entry function of the BlockMeta for block metadata transaction + function blockPrologue() external; +} diff --git a/solidity/supra_contracts/test/AutomationController.t.sol b/solidity/supra_contracts/test/AutomationController.t.sol index 21c4db7ddb..8939c62aba 100644 --- a/solidity/supra_contracts/test/AutomationController.t.sol +++ b/solidity/supra_contracts/test/AutomationController.t.sol @@ -27,6 +27,27 @@ contract AutomationControllerTest is Test { address alice = address(0x123); address bob = address(0x456); + function defaultInitParams(address _controller, address _registry, address _owner) internal view returns (LibConfig.InitializeParams memory) { + return LibConfig.InitializeParams({ + taskDurationCapSecs: 3600, + registryMaxGasCap: 10_000_000, + automationBaseFeeWeiPerSec: 0.001 ether, + flatRegistrationFeeWei: 0.002 ether, + congestionThresholdPercentage: 50, + congestionBaseFeeWeiPerSec: 0.002 ether, + congestionExponent: 2, + taskCapacity: 500, + cycleDurationSecs: 2000, + sysTaskDurationCapSecs: 3600, + sysRegistryMaxGasCap: 5_000_000, + sysTaskCapacity: 500, + vmSigner: vmSigner, + erc20Supra: address(erc20Supra), + controller: _controller, + registry: _registry, + owner: _owner + }); + } /// @dev Sets up initial state for testing. /// @dev Sets balance of 'alice' to 100 ether. /// @dev Deploys and initializes all contracts with required parameters. @@ -36,43 +57,30 @@ contract AutomationControllerTest is Test { vm.startPrank(admin); erc20Supra = new ERC20Supra(msg.sender); + uint256 currentNonce = vm.getNonce(admin); + address coreProxyAddr = computeCreateAddress(admin, currentNonce + 1); + address registryProxyAddr = computeCreateAddress(admin, currentNonce + 3); + address controllerProxyAddr = computeCreateAddress(admin, currentNonce + 5); + + AutomationCore automationCoreImpl = new AutomationCore(); + LibConfig.InitializeParams memory initParams = defaultInitParams(controllerProxyAddr, registryProxyAddr, admin); bytes memory automationCoreInitData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, // taskDurationCapSecs - 10_000_000, // registryMaxGasCap - 0.001 ether, // automationBaseFeeWeiPerSec - 0.002 ether, // flatRegistrationFeeWei - 50, // congestionThresholdPercentage - 0.002 ether, // congestionBaseFeeWeiPerSec - 2, // congestionExponent - 500, // taskCapacity - 2000, // cycleDurationSecs - 3600, // sysTaskDurationCapSecs - 5_000_000, // sysRegistryMaxGasCap - 500, // sysTaskCapacity - vmSigner, // VM Signer address - address(erc20Supra) // ERC20Supra address - ) + AutomationCore.initialize, initParams ); ERC1967Proxy automationCoreProxy = new ERC1967Proxy(address(automationCoreImpl), automationCoreInitData); automationCore = AutomationCore(address(automationCoreProxy)); AutomationRegistry registryImpl = new AutomationRegistry(); - bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore))); + bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore), controllerProxyAddr, admin)); ERC1967Proxy registryProxy = new ERC1967Proxy(address(registryImpl), registryInitData); registry = AutomationRegistry(address(registryProxy)); AutomationController controllerImpl = new AutomationController(); - bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), true)); + bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), admin, true, initParams.cycleDurationSecs)); ERC1967Proxy controllerProxy = new ERC1967Proxy(address(controllerImpl), controllerInitData); controller = AutomationController(address(controllerProxy)); - automationCore.setAutomationRegistry(address(registry)); - automationCore.setAutomationController(address(controller)); - registry.setAutomationController(address(controller)); - vm.stopPrank(); vm.mockCall( @@ -95,44 +103,44 @@ contract AutomationControllerTest is Test { vm.expectRevert(Initializable.InvalidInitialization.selector); vm.prank(admin); - controller.initialize(address(automationCore), address(registry), true); + controller.initialize(address(automationCore), address(registry), admin, true, 1000); } /// @dev Test to ensure initialize reverts if AutomationCore address is zero. function testInitializeRevertsIfAutomationCoreAddressZero() public { AutomationController impl = new AutomationController(); - bytes memory initData = abi.encodeCall(AutomationController.initialize, (address(0), address(registry), true)); + bytes memory initData = abi.encodeCall(AutomationController.initialize, (address(0), address(registry), admin, true, 1000)); vm.expectRevert(CommonUtils.AddressCannotBeZero.selector); new ERC1967Proxy(address(impl), initData); } - /// @dev Test to ensure initialize reverts if AutomationCore address is EOA. - function testInitializeRevertsIfAutomationCoreEoa() public { - AutomationController impl = new AutomationController(); - bytes memory initData = abi.encodeCall(AutomationController.initialize, (alice, address(registry), true)); - - vm.expectRevert(CommonUtils.AddressCannotBeEOA.selector); - new ERC1967Proxy(address(impl), initData); - } - +// /// @dev Test to ensure initialize reverts if AutomationCore address is EOA. +// function testInitializeRevertsIfAutomationCoreEoa() public { +// AutomationController impl = new AutomationController(); +// bytes memory initData = abi.encodeCall(AutomationController.initialize, (alice, address(registry), admin, true, 1000)); +// +// vm.expectRevert(CommonUtils.AddressCannotBeEOA.selector); +// new ERC1967Proxy(address(impl), initData); +// } +// /// @dev Test to ensure initialize reverts if AutomationRegistry address is zero. function testInitializeRevertsIfRegistryZero() public { AutomationController impl = new AutomationController(); - bytes memory initData = abi.encodeCall(AutomationController.initialize, (address(automationCore), address(0), true)); + bytes memory initData = abi.encodeCall(AutomationController.initialize, (address(automationCore), address(0), admin, true, 1000)); vm.expectRevert(CommonUtils.AddressCannotBeZero.selector); new ERC1967Proxy(address(impl), initData); } - /// @dev Test to ensure initialize reverts if AutomationRegistry address is EOA. - function testInitializeRevertsIfRegistryEoa() public { - AutomationController impl = new AutomationController(); - bytes memory initData = abi.encodeCall(AutomationController.initialize, (address(automationCore), alice, true)); - - vm.expectRevert(CommonUtils.AddressCannotBeEOA.selector); - new ERC1967Proxy(address(impl), initData); - } +// /// @dev Test to ensure initialize reverts if AutomationRegistry address is EOA. +// function testInitializeRevertsIfRegistryEoa() public { +// AutomationController impl = new AutomationController(); +// bytes memory initData = abi.encodeCall(AutomationController.initialize, (address(automationCore), alice, admin, true, 1000)); +// +// vm.expectRevert(CommonUtils.AddressCannotBeEOA.selector); +// new ERC1967Proxy(address(impl), initData); +// } /// @dev Test to ensure 'setAutomationRegistry' reverts if caller is not owner. function testSetAutomationRegistryRevertsIfNotOwner() public { @@ -190,7 +198,7 @@ contract AutomationControllerTest is Test { vm.prank(alice); controller.setAutomationCore(address(automationCoreImpl)); } - + /// @dev Test to ensure 'setAutomationCore' reverts if address is zero. function testSetAutomationCoreRevertsIfAddressZero() public { vm.expectRevert(CommonUtils.AddressCannotBeZero.selector); @@ -283,10 +291,10 @@ contract AutomationControllerTest is Test { (uint64 indexBefore, uint64 startBefore, uint64 durationBefore, CommonUtils.CycleState stateBefore) = controller.getCycleInfo(); vm.warp(startBefore + durationBefore); - + vm.expectEmit(true, true, false, true); emit AutomationController.AutomationCycleEvent( - indexBefore, + indexBefore, CommonUtils.CycleState.READY, startBefore, durationBefore, @@ -313,9 +321,9 @@ contract AutomationControllerTest is Test { vm.expectEmit(true, true, false, true); emit AutomationController.AutomationCycleEvent( indexBefore + 1, - CommonUtils.CycleState.STARTED, - uint64(block.timestamp), - durationBefore, + CommonUtils.CycleState.STARTED, + uint64(block.timestamp), + durationBefore, stateBefore ); @@ -376,7 +384,7 @@ contract AutomationControllerTest is Test { function testProcessTasksRevertsIfInvalidState() public { uint64[] memory tasks = new uint64[](1); tasks[0] = 0; - + vm.expectRevert(IAutomationController.InvalidRegistryState.selector); vm.prank(vmSigner, vmSigner); @@ -428,13 +436,13 @@ contract AutomationControllerTest is Test { ( , uint64 startTime, uint64 duration, ) = controller.getCycleInfo(); vm.warp(startTime + duration); - + vm.prank(vmSigner, vmSigner); controller.monitorCycleEnd(); (uint64 index, , , CommonUtils.CycleState state) = controller.getCycleInfo(); assertEq(uint8(state), uint8(CommonUtils.CycleState.FINISHED)); - + uint64[] memory tasks = new uint64[](1); tasks[0] = 0; @@ -450,7 +458,7 @@ contract AutomationControllerTest is Test { ( , uint64 start, uint64 duration, ) = controller.getCycleInfo(); vm.warp(start + duration); - + // Moves state to FINISHED vm.prank(vmSigner, vmSigner); controller.monitorCycleEnd(); @@ -477,7 +485,7 @@ contract AutomationControllerTest is Test { ( , , , CommonUtils.CycleState newState) = controller.getCycleInfo(); assertEq(uint8(newState), uint8(CommonUtils.CycleState.READY)); assertFalse(registry.ifTaskExists(tasks[0])); - } + } /// @dev Test to ensure 'processTasks' works correctly when cycle state is SUSPENDED and automation is enabled. function testProcessTasksWhenCycleStateSuspendedAutomationEnabled() public { @@ -485,7 +493,7 @@ contract AutomationControllerTest is Test { ( , uint64 start, uint64 duration, ) = controller.getCycleInfo(); vm.warp(start + duration); - + // Moves state to FINISHED vm.prank(vmSigner, vmSigner); controller.monitorCycleEnd(); @@ -546,13 +554,13 @@ contract AutomationControllerTest is Test { tasks[0] = 0; vm.expectRevert(IAutomationController.InvalidInputCycleIndex.selector); - + vm.prank(vmSigner, vmSigner); controller.processTasks(indexAfter + 1, tasks); } // :::::::::::::::::::::::::::::::::::::::::::::::::::::: Tests related to 'disableAutomation' :::::::::::::::::::::::::::::::::::::::::::::::::::::: - + /// @dev Test to ensure 'disableAutomation' disables the automation. function testDisableAutomation() public { // Already enabled in initialize() @@ -637,8 +645,8 @@ contract AutomationControllerTest is Test { /// @dev Helper function to register a UST. function registerTask() private { bytes[] memory auxData; - bytes memory payload = createPayload(0, address(erc20Supra)); - + bytes memory payload = createPayload(0, address(erc20Supra)); + vm.startPrank(alice); erc20Supra.nativeToErc20Supra{value: 5 ether}(); erc20Supra.approve(address(automationCore), type(uint256).max); @@ -660,8 +668,8 @@ contract AutomationControllerTest is Test { /// @param _target Address of destination smart contract. function createPayload(uint128 _value, address _target) private pure returns (bytes memory) { LibConfig.AccessListEntry[] memory accessList = new LibConfig.AccessListEntry[](2); - - bytes32[] memory keys = new bytes32[](2); + + bytes32[] memory keys = new bytes32[](2); keys[0] = bytes32(uint256(0)); keys[1] = bytes32(uint256(1)); @@ -678,6 +686,6 @@ contract AutomationControllerTest is Test { bytes memory callData = abi.encodeCall(ERC20Supra.erc20SupraToNative, 100); bytes memory payload = abi.encode(_value, _target, callData, accessList); - return payload; + return payload; } -} \ No newline at end of file +} diff --git a/solidity/supra_contracts/test/AutomationCore.t.sol b/solidity/supra_contracts/test/AutomationCore.t.sol index 2350735502..328bdc8dd8 100644 --- a/solidity/supra_contracts/test/AutomationCore.t.sol +++ b/solidity/supra_contracts/test/AutomationCore.t.sol @@ -27,52 +27,79 @@ contract AutomationCoreTest is Test { address alice = address(0x123); address bob = address(0x456); + /// @dev Helper function that returns default initialization parameters. + function defaultInitParams(address _controller, address _registry, address _owner) internal view returns (LibConfig.InitializeParams memory) { + return LibConfig.InitializeParams({ + taskDurationCapSecs: 3600, + registryMaxGasCap: 10_000_000, + automationBaseFeeWeiPerSec: 0.001 ether, + flatRegistrationFeeWei: 0.002 ether, + congestionThresholdPercentage: 50, + congestionBaseFeeWeiPerSec: 0.002 ether, + congestionExponent: 2, + taskCapacity: 500, + cycleDurationSecs: 2000, + sysTaskDurationCapSecs: 3600, + sysRegistryMaxGasCap: 5_000_000, + sysTaskCapacity: 500, + vmSigner: vmSigner, + erc20Supra: address(erc20Supra), + controller: _controller, + registry: _registry, + owner: _owner + }); + } + + /// @dev Helper function that returns default initialization parameters using deployed contracts. + function defaultInitParams() internal view returns (LibConfig.InitializeParams memory) { + return defaultInitParams(address(automationController), address(registry), admin); + } + /// @dev Sets up initial state for testing. /// @dev Sets balance of 'alice' to 100 ether. - /// @dev Deploys and initializes all contracts with required parameters. + /// @dev Deploys and initializes all contracts with required parameters. function setUp() public { vm.deal(alice, 100 ether); vm.startPrank(admin); erc20Supra = new ERC20Supra(msg.sender); - + + // Get current nonce for admin (after ERC20Supra deployment) + uint256 currentNonce = vm.getNonce(admin); + + // Pre-compute proxy addresses: + // nonce+0: AutomationCore impl + // nonce+1: AutomationCore proxy + // nonce+2: AutomationRegistry impl + // nonce+3: AutomationRegistry proxy + // nonce+4: AutomationController impl + // nonce+5: AutomationController proxy + address coreProxyAddr = computeCreateAddress(admin, currentNonce + 1); + address registryProxyAddr = computeCreateAddress(admin, currentNonce + 3); + address controllerProxyAddr = computeCreateAddress(admin, currentNonce + 5); + + // Deploy AutomationCore AutomationCore automationCoreImpl = new AutomationCore(); + LibConfig.InitializeParams memory initParams = defaultInitParams(controllerProxyAddr, registryProxyAddr, admin); bytes memory automationCoreInitData = abi.encodeCall( AutomationCore.initialize, - ( - 3600, // taskDurationCapSecs - 10_000_000, // registryMaxGasCap - 0.001 ether, // automationBaseFeeWeiPerSec - 0.002 ether, // flatRegistrationFeeWei - 50, // congestionThresholdPercentage - 0.002 ether, // congestionBaseFeeWeiPerSec - 2, // congestionExponent - 500, // taskCapacity - 2000, // cycleDurationSecs - 3600, // sysTaskDurationCapSecs - 5_000_000, // sysRegistryMaxGasCap - 500, // sysTaskCapacity - vmSigner, // VM Signer address - address(erc20Supra) // ERC20Supra address - ) + (initParams) ); ERC1967Proxy automationCoreProxy = new ERC1967Proxy(address(automationCoreImpl), automationCoreInitData); automationCore = AutomationCore(address(automationCoreProxy)); + // Deploy AutomationRegistry AutomationRegistry registryImpl = new AutomationRegistry(); - bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore))); + bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore), controllerProxyAddr, admin)); ERC1967Proxy registryProxy = new ERC1967Proxy(address(registryImpl), registryInitData); registry = AutomationRegistry(address(registryProxy)); + // Deploy AutomationController AutomationController controllerImpl = new AutomationController(); - bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), true)); + bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize, (address(automationCore), address(registry), admin, true, initParams.cycleDurationSecs)); ERC1967Proxy controllerProxy = new ERC1967Proxy(address(controllerImpl), controllerInitData); automationController = AutomationController(address(controllerProxy)); - automationCore.setAutomationRegistry(address(registry)); - automationCore.setAutomationController(address(automationController)); - registry.setAutomationController(address(automationController)); - vm.stopPrank(); vm.mockCall( @@ -119,27 +146,19 @@ contract AutomationCoreTest is Test { /// @dev Test to ensure reinitialization fails. function testInitializeRevertsIfReinitialized() public { vm.expectRevert(Initializable.InvalidInitialization.selector); - - vm.prank(admin); - automationCore.initialize( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, 2, - 500, 2000, 3600, 5_000_000, 500, vmSigner, address(erc20Supra) - ); + + vm.prank(admin); + automationCore.initialize(defaultInitParams()); } /// @dev Test to ensure initialization fails if zero address is passed as VM Signer. function testInitializeRevertsIfVmSignerZero() public { AutomationCore implementation = new AutomationCore(); - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, - 2, 500, 2000, 3600, 5_000_000, 500, - address(0), // VM Signer as zero - address(erc20Supra) - ) - ); + LibConfig.InitializeParams memory params = defaultInitParams(); + params.vmSigner = address(0); + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.AddressCannotBeZero.selector); new ERC1967Proxy(address(implementation), initData); @@ -148,15 +167,11 @@ contract AutomationCoreTest is Test { /// @dev Test to ensure initialization fails if ERC20Supra address is zero. function testInitializeRevertsIfErc20SupraIsZero() public { AutomationCore implementation = new AutomationCore(); - - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, - 2, 500, 2000, 3600, 5_000_000, 500, vmSigner, - address(0) // address(0) as ERC20Supra - ) - ); + + LibConfig.InitializeParams memory params = defaultInitParams(); + params.erc20Supra = address(0); + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.AddressCannotBeZero.selector); new ERC1967Proxy(address(implementation), initData); @@ -166,14 +181,10 @@ contract AutomationCoreTest is Test { function testInitializeRevertsIfErc20SupraIsEoa() public { AutomationCore implementation = new AutomationCore(); - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, - 2, 500, 2000, 3600, 5_000_000, 500, vmSigner, - admin // EOA address as ERC20Supra - ) - ); + LibConfig.InitializeParams memory params = defaultInitParams(); + params.erc20Supra = admin; // EOA address as ERC20Supra + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(CommonUtils.AddressCannotBeEOA.selector); new ERC1967Proxy(address(implementation), initData); @@ -182,16 +193,11 @@ contract AutomationCoreTest is Test { /// @dev Test to ensure initialization fails if task duration is <= cycle duration. function testInitializeRevertsIfInvalidTaskDuration() public { AutomationCore implementation = new AutomationCore(); - - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 2000, // task duration - 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, 2, 500, - 2000, // cycle duration - 3600, 5_000_000, 500, vmSigner, address(erc20Supra) - ) - ); + + LibConfig.InitializeParams memory params = defaultInitParams(); + params.taskDurationCapSecs = 2000; // task duration == cycle duration + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidTaskDuration.selector); new ERC1967Proxy(address(implementation), initData); @@ -200,17 +206,12 @@ contract AutomationCoreTest is Test { /// @dev Test to ensure initialization fails if registry max gas cap is zero. function testInitializeRevertsIfRegistryMaxGasCapZero() public { AutomationCore implementation = new AutomationCore(); - - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, - 0, // registry max gas cap - 0.001 ether, 0.002 ether, 50, 0.002 ether, 2, 500, - 2000, 3600, 5_000_000, 500, vmSigner, address(erc20Supra) - ) - ); - + + LibConfig.InitializeParams memory params = defaultInitParams(); + params.registryMaxGasCap = 0; + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); + vm.expectRevert(IAutomationCore.InvalidRegistryMaxGasCap.selector); new ERC1967Proxy(address(implementation), initData); } @@ -218,15 +219,11 @@ contract AutomationCoreTest is Test { /// @dev Test to ensure initialization fails if congestion threshold percentage is > 100. function testInitializeRevertsIfInvalidCongestionThreshold() public { AutomationCore implementation = new AutomationCore(); - - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, - 101, // congestion threshold percentage > 100 - 0.002 ether, 2, 500, 2000, 3600, 5_000_000, 500, vmSigner, address(erc20Supra) - ) - ); + + LibConfig.InitializeParams memory params = defaultInitParams(); + params.congestionThresholdPercentage = 101; // > 100 + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidCongestionThreshold.selector); new ERC1967Proxy(address(implementation), initData); @@ -235,32 +232,24 @@ contract AutomationCoreTest is Test { /// @dev Test to ensure initialization fails if congestion exponent is 0. function testInitializeRevertsIfCongestionExponentZero() public { AutomationCore implementation = new AutomationCore(); - - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, - 0, // congestion exponent - 500, 2000, 3600, 5_000_000, 500, vmSigner, address(erc20Supra) - ) - ); + + LibConfig.InitializeParams memory params = defaultInitParams(); + params.congestionExponent = 0; + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidCongestionExponent.selector); - new ERC1967Proxy(address(implementation), initData); + new ERC1967Proxy(address(implementation), initData); } /// @dev Test to ensure initialization fails if task capacity is 0. function testInitializeRevertsIfTaskCapacityZero() public { AutomationCore implementation = new AutomationCore(); - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, 2, - 0, // 0 as task capacity - 2000, 3600, 5_000_000, 500, vmSigner, address(erc20Supra) - ) - ); + LibConfig.InitializeParams memory params = defaultInitParams(); + params.taskCapacity = 0; + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidTaskCapacity.selector); new ERC1967Proxy(address(implementation), initData); @@ -269,15 +258,11 @@ contract AutomationCoreTest is Test { /// @dev Test to ensure initialization fails if cycle duration is 0. function testInitializeRevertsIfCycleDurationZero() public { AutomationCore implementation = new AutomationCore(); - - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, 2, 500, - 0, // cycle duration - 3600, 5_000_000, 500, vmSigner, address(erc20Supra) - ) - ); + + LibConfig.InitializeParams memory params = defaultInitParams(); + params.cycleDurationSecs = 0; + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidCycleDuration.selector); new ERC1967Proxy(address(implementation), initData); @@ -287,15 +272,10 @@ contract AutomationCoreTest is Test { function testInitializeRevertsIfInvalidSysTaskDuration() public { AutomationCore implementation = new AutomationCore(); - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, 2, 500, - 2000, // cycle duration - 2000, // system task duration - 5_000_000, 500, vmSigner, address(erc20Supra) - ) - ); + LibConfig.InitializeParams memory params = defaultInitParams(); + params.sysTaskDurationCapSecs = 2000; // == cycle duration + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidSysTaskDuration.selector); new ERC1967Proxy(address(implementation), initData); @@ -305,14 +285,10 @@ contract AutomationCoreTest is Test { function testInitializeRevertsIfSysRegistryMaxGasCapZero() public { AutomationCore implementation = new AutomationCore(); - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, 2, 500, 2000, 3600, - 0, // system registry max gas cap - 500, vmSigner, address(erc20Supra) - ) - ); + LibConfig.InitializeParams memory params = defaultInitParams(); + params.sysRegistryMaxGasCap = 0; + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidSysRegistryMaxGasCap.selector); new ERC1967Proxy(address(implementation), initData); @@ -322,15 +298,10 @@ contract AutomationCoreTest is Test { function testInitializeRevertsIfSysTaskCapacityZero() public { AutomationCore implementation = new AutomationCore(); - bytes memory initData = abi.encodeCall( - AutomationCore.initialize, - ( - 3600, 10_000_000, 0.001 ether, 0.002 ether, 50, 0.002 ether, - 2, 500, 2000, 3600, 5_000_000, - 0, // system task capacity - vmSigner, address(erc20Supra) - ) - ); + LibConfig.InitializeParams memory params = defaultInitParams(); + params.sysTaskCapacity = 0; + + bytes memory initData = abi.encodeCall(AutomationCore.initialize, (params)); vm.expectRevert(IAutomationCore.InvalidSysTaskCapacity.selector); new ERC1967Proxy(address(implementation), initData); @@ -423,8 +394,10 @@ contract AutomationCoreTest is Test { /// @dev Helper function that deploys AutomationRegistry and returns its address. function deployAutomationRegistry() internal returns (address) { // Deploy AutomationRegistry proxy + uint256 currentNonce = vm.getNonce(admin); + address precomputed = computeCreateAddress(admin, currentNonce); AutomationRegistry registryImpl = new AutomationRegistry(); - bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize,(address(automationCore))); + bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize,(address(automationCore), precomputed, admin)); ERC1967Proxy registryProxy = new ERC1967Proxy(address(registryImpl), registryInitData); return address(registryProxy); @@ -484,7 +457,7 @@ contract AutomationCoreTest is Test { function deployAutomationController() internal returns (address) { // Deploy AutomationController proxy AutomationController controllerImpl = new AutomationController(); - bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), true)); + bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), admin, true, 1000)); ERC1967Proxy controllerProxy = new ERC1967Proxy(address(controllerImpl), controllerInitData); return address(controllerProxy); @@ -942,4 +915,4 @@ contract AutomationCoreTest is Test { ); vm.stopPrank(); } -} \ No newline at end of file +} diff --git a/solidity/supra_contracts/test/AutomationRegistry.t.sol b/solidity/supra_contracts/test/AutomationRegistry.t.sol index 8eb4d6e2d6..519c71ccd6 100644 --- a/solidity/supra_contracts/test/AutomationRegistry.t.sol +++ b/solidity/supra_contracts/test/AutomationRegistry.t.sol @@ -29,6 +29,29 @@ contract AutomationRegistryTest is Test { address alice = address(0x123); address bob = address(0x456); + /// @dev Helper function that returns default initialization parameters. + function defaultInitParams(address _controller, address _registry, address _owner) internal view returns (LibConfig.InitializeParams memory) { + return LibConfig.InitializeParams({ + taskDurationCapSecs: 3600, + registryMaxGasCap: 10_000_000, + automationBaseFeeWeiPerSec: 0.001 ether, + flatRegistrationFeeWei: 0.002 ether, + congestionThresholdPercentage: 50, + congestionBaseFeeWeiPerSec: 0.002 ether, + congestionExponent: 2, + taskCapacity: 500, + cycleDurationSecs: 2000, + sysTaskDurationCapSecs: 3600, + sysRegistryMaxGasCap: 5_000_000, + sysTaskCapacity: 500, + vmSigner: vmSigner, + erc20Supra: address(erc20Supra), + controller: _controller, + registry: _registry, + owner: _owner + }); + } + /// @dev Sets up initial state for testing. /// @dev Sets balance of 'alice' to 100 ether. /// @dev Deploys and initializes all contracts with required parameters. @@ -38,36 +61,28 @@ contract AutomationRegistryTest is Test { vm.startPrank(admin); erc20Supra = new ERC20Supra(msg.sender); + // Get current nonce for admin (after ERC20Supra deployment) + uint256 currentNonce = vm.getNonce(admin); + address coreProxyAddr = computeCreateAddress(admin, currentNonce + 1); + address registryProxyAddr = computeCreateAddress(admin, currentNonce + 3); + address controllerProxyAddr = computeCreateAddress(admin, currentNonce + 5); + AutomationCore automationCoreImpl = new AutomationCore(); + LibConfig.InitializeParams memory initParams = defaultInitParams(controllerProxyAddr, registryProxyAddr, admin); bytes memory automationCoreInitData = abi.encodeCall( AutomationCore.initialize, - ( - 3600, // taskDurationCapSecs - 10_000_000, // registryMaxGasCap - 0.001 ether, // automationBaseFeeWeiPerSec - 0.002 ether, // flatRegistrationFeeWei - 50, // congestionThresholdPercentage - 0.002 ether, // congestionBaseFeeWeiPerSec - 2, // congestionExponent - 500, // taskCapacity - 2000, // cycleDurationSecs - 3600, // sysTaskDurationCapSecs - 5_000_000, // sysRegistryMaxGasCap - 500, // sysTaskCapacity - vmSigner, // VM Signer address - address(erc20Supra) // ERC20Supra address - ) + (initParams) ); ERC1967Proxy automationCoreProxy = new ERC1967Proxy(address(automationCoreImpl), automationCoreInitData); automationCore = AutomationCore(address(automationCoreProxy)); AutomationRegistry registryImpl = new AutomationRegistry(); - bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore))); + bytes memory registryInitData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore), controllerProxyAddr, admin)); ERC1967Proxy registryProxy = new ERC1967Proxy(address(registryImpl), registryInitData); registry = AutomationRegistry(address(registryProxy)); AutomationController controllerImpl = new AutomationController(); - bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), true)); + bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), admin, true, initParams.cycleDurationSecs)); ERC1967Proxy controllerProxy = new ERC1967Proxy(address(controllerImpl), controllerInitData); controller = AutomationController(address(controllerProxy)); @@ -98,34 +113,43 @@ contract AutomationRegistryTest is Test { vm.expectRevert(Initializable.InvalidInitialization.selector); vm.prank(admin); - registry.initialize(address(automationCoreImplementation)); + registry.initialize(address(automationCoreImplementation), address(controller), admin); } /// @dev Test to ensure initialization fails if AutomationCore address is zero. function testInitializeRevertsIfAutomationCoreAddressIsZero() public { AutomationRegistry implementation = new AutomationRegistry(); - bytes memory initData = abi.encodeCall(AutomationRegistry.initialize, (address(0))); + bytes memory initData = abi.encodeCall(AutomationRegistry.initialize, (address(0), address (controller), admin)); vm.expectRevert(CommonUtils.AddressCannotBeZero.selector); new ERC1967Proxy(address(implementation), initData); } - - /// @dev Test to ensure initialization fails if EOA is passed as AutomationCore address. - function testInitializeRevertsIfAutomationCoreAddressIsEoa() public { + + /// @dev Test to ensure initialization fails if AutomationCore address is zero. + function testInitializeRevertsIfAutomationControllerAddressIsZero() public { AutomationRegistry implementation = new AutomationRegistry(); - bytes memory initData = abi.encodeCall(AutomationRegistry.initialize, (admin)); + bytes memory initData = abi.encodeCall(AutomationRegistry.initialize, (address(automationCore), address (0), admin)); - vm.expectRevert(CommonUtils.AddressCannotBeEOA.selector); + vm.expectRevert(CommonUtils.AddressCannotBeZero.selector); new ERC1967Proxy(address(implementation), initData); } +// /// @dev Test to ensure initialization fails if EOA is passed as AutomationCore address. +// function testInitializeRevertsIfAutomationCoreAddressIsEoa() public { +// AutomationRegistry implementation = new AutomationRegistry(); +// bytes memory initData = abi.encodeCall(AutomationRegistry.initialize, (admin)); +// +// vm.expectRevert(CommonUtils.AddressCannotBeEOA.selector); +// new ERC1967Proxy(address(implementation), initData); +// } + // :::::::::::::::::::::::::::::::::::::::::::::::::::::: Tests related to 'setAutomationController' :::::::::::::::::::::::::::::::::::::::::::::::::::::: /// @dev Helper function that deploys AutomationController and returns its address. function deployAutomationController() internal returns (address) { // Deploy AutomationController proxy AutomationController controllerImpl = new AutomationController(); - bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), true)); + bytes memory controllerInitData = abi.encodeCall(AutomationController.initialize,(address(automationCore), address(registry), admin, true, 1000)); ERC1967Proxy controllerProxy = new ERC1967Proxy(address(controllerImpl), controllerInitData); return address(controllerProxy); @@ -471,7 +495,7 @@ contract AutomationRegistryTest is Test { bytes[] memory auxData; bytes memory payload = createPayload(0, address(erc20Supra)); - vm.expectRevert(IAutomationCore.InsufficientFeeCapForCycle.selector); + vm.expectPartialRevert(IAutomationCore.InsufficientFeeCapForCycle.selector); vm.prank(alice); registry.register( @@ -1158,4 +1182,4 @@ contract AutomationRegistryTest is Test { 0.1 ether ); } -} \ No newline at end of file +} diff --git a/solidity/supra_contracts/test/BlockMeta.t.sol b/solidity/supra_contracts/test/BlockMeta.t.sol index f827763b22..1fd945aa08 100644 --- a/solidity/supra_contracts/test/BlockMeta.t.sol +++ b/solidity/supra_contracts/test/BlockMeta.t.sol @@ -28,7 +28,7 @@ contract BlockMetaTest is Test { // Deploy BlockMeta proxy BlockMeta blockMetaImpl = new BlockMeta(); - bytes memory blockMetaInitData = abi.encodeCall(BlockMeta.initialize, ()); + bytes memory blockMetaInitData = abi.encodeCall(BlockMeta.initialize, admin); ERC1967Proxy blockMetaProxy = new ERC1967Proxy(address(blockMetaImpl), blockMetaInitData); blockMeta = BlockMeta(address(blockMetaProxy));