From 28dd7f1042247c8288b2e9be69a6a254a7ddb525 Mon Sep 17 00:00:00 2001 From: Gustavo Gonzalez Date: Thu, 29 Aug 2024 07:23:13 -0400 Subject: [PATCH 01/16] docs: add rc tag to antora docs and improve security warning in docs (#267) Add the rc tag to the docs so we can publish them before the audit. It should be shown as `0.1.0-rc` on the site. I also made clear in the warning that this hasn't been audited yet. Signed-off-by: Gustavo Gonzalez --- docs/antora.yml | 1 + docs/modules/ROOT/pages/index.adoc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/antora.yml b/docs/antora.yml index 9c514982..524da2ac 100644 --- a/docs/antora.yml +++ b/docs/antora.yml @@ -1,5 +1,6 @@ name: contracts-stylus title: Contracts for Stylus version: 0.1.0 +prerelease: '-rc' #we can remove this with the official release nav: - modules/ROOT/nav.adoc diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 273a855e..01bf3f87 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -4,6 +4,6 @@ *A library for secure smart contract development* written in Rust for {stylus}. -WARNING: This repo contains highly experimental code. *Use at your own risk.* +WARNING: This repo contains highly experimental code. It has never been audited nor thoroughly reviewed for security vulnerabilities. *Use at your own risk.* NOTE: You can track our roadmap in our https://github.com/orgs/OpenZeppelin/projects/35[Github Project]. From bda95a2b374cde7d348bf0e235bd62f72728ba9c Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Thu, 29 Aug 2024 13:49:51 +0200 Subject: [PATCH 02/16] build: bump version to 0.1.0-rc (#268) Bump version to `0.1.0-rc`. --- Cargo.lock | 4 ++-- contracts/Cargo.toml | 2 +- lib/crypto/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e380b92..6b04119e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2568,7 +2568,7 @@ dependencies = [ [[package]] name = "openzeppelin-crypto" -version = "0.1.0" +version = "0.1.0-rc" dependencies = [ "hex-literal", "mini-alloc", @@ -2578,7 +2578,7 @@ dependencies = [ [[package]] name = "openzeppelin-stylus" -version = "0.1.0-alpha.1" +version = "0.1.0-rc" dependencies = [ "alloy-primitives 0.3.3", "alloy-sol-types 0.3.1", diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index c0ed507e..d7c64340 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true keywords.workspace = true license.workspace = true repository.workspace = true -version = "0.1.0-alpha.1" +version = "0.1.0-rc" [dependencies] alloy-primitives.workspace = true diff --git a/lib/crypto/Cargo.toml b/lib/crypto/Cargo.toml index fdcc7678..cf119fc9 100644 --- a/lib/crypto/Cargo.toml +++ b/lib/crypto/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true keywords.workspace = true license.workspace = true repository.workspace = true -version = "0.1.0" +version = "0.1.0-rc" [dependencies] mini-alloc.workspace = true From 6741de1cd0b6c69e2184496248beebfb516d1d5c Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Thu, 5 Sep 2024 13:47:06 +0200 Subject: [PATCH 03/16] build: bump Stylus SDK to v0.6.0 and cargo-stylus to v0.5.1 (#273) Bump: - Stylus SDK to `v0.6.0` - cargo-stylus to `v0.5.1` --- .github/workflows/check-wasm.yml | 2 +- .github/workflows/e2e-tests.yml | 2 +- Cargo.lock | 471 ++++++++---------- Cargo.toml | 10 +- benches/Cargo.toml | 2 +- contracts/src/access/control.rs | 27 +- contracts/src/access/ownable.rs | 4 +- .../src/token/erc20/extensions/capped.rs | 4 +- .../src/token/erc20/extensions/metadata.rs | 4 +- .../src/token/erc20/extensions/permit.rs | 6 +- contracts/src/token/erc20/mod.rs | 4 +- .../token/erc721/extensions/consecutive.rs | 10 +- .../src/token/erc721/extensions/enumerable.rs | 4 +- .../src/token/erc721/extensions/metadata.rs | 4 +- .../token/erc721/extensions/uri_storage.rs | 4 +- contracts/src/token/erc721/mod.rs | 20 +- contracts/src/utils/cryptography/ecdsa.rs | 6 +- contracts/src/utils/cryptography/eip712.rs | 2 +- contracts/src/utils/metadata.rs | 4 +- contracts/src/utils/nonces.rs | 4 +- contracts/src/utils/pausable.rs | 4 +- examples/access-control/src/lib.rs | 4 +- examples/basic/token/src/lib.rs | 4 +- examples/ecdsa/src/lib.rs | 4 +- examples/erc20-permit/src/lib.rs | 4 +- examples/erc20/src/lib.rs | 4 +- examples/erc20/tests/erc20.rs | 3 +- examples/erc721-consecutive/src/lib.rs | 2 +- examples/erc721-metadata/src/lib.rs | 4 +- examples/erc721/src/lib.rs | 4 +- examples/erc721/tests/erc721.rs | 3 +- examples/merkle-proofs/src/lib.rs | 4 +- examples/ownable/src/lib.rs | 4 +- scripts/check-wasm.sh | 2 +- 34 files changed, 299 insertions(+), 345 deletions(-) diff --git a/.github/workflows/check-wasm.yml b/.github/workflows/check-wasm.yml index ca16f313..f452c4fa 100644 --- a/.github/workflows/check-wasm.yml +++ b/.github/workflows/check-wasm.yml @@ -30,7 +30,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: install cargo-stylus - run: cargo install cargo-stylus@0.4.2 cargo-stylus-check@0.4.2 + run: cargo install cargo-stylus@0.5.1 - name: run wasm check run: | diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 22fa1d85..f1a5880b 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -39,7 +39,7 @@ jobs: key: "e2e-tests" - name: install cargo-stylus - run: cargo install cargo-stylus@0.4.2 cargo-stylus-check@0.4.2 + run: cargo install cargo-stylus@0.5.1 - name: install solc run: | diff --git a/Cargo.lock b/Cargo.lock index 6b04119e..ebb25bb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ name = "access-control-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "mini-alloc", @@ -83,9 +83,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "096bfe5b4ae72138eab21ba5789e74e09f80461352b2261dfde69e7538f0b3f6" +checksum = "0ba1c79677c9ce51c8d45e20845b05e6fb070ea2c863fba03ad6af2c778474bd" dependencies = [ "alloy-consensus", "alloy-contract", @@ -101,7 +101,6 @@ dependencies = [ "alloy-signer-local", "alloy-transport", "alloy-transport-http", - "reqwest", ] [[package]] @@ -121,7 +120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f63a6c9eb45684a5468536bc55379a2af0f45ffa5d756e4e4964532737e1836" dependencies = [ "alloy-eips", - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-rlp", "alloy-serde", "c-kzg", @@ -137,10 +136,10 @@ dependencies = [ "alloy-dyn-abi", "alloy-json-abi", "alloy-network", - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-provider", "alloy-rpc-types-eth", - "alloy-sol-types 0.7.6", + "alloy-sol-types", "alloy-transport", "futures", "futures-util", @@ -155,8 +154,8 @@ checksum = "5af3faff14c12c8b11037e0a093dd157c3702becb8435577a2408534d0758315" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", - "alloy-primitives 0.7.6", - "alloy-sol-types 0.7.6", + "alloy-primitives", + "alloy-sol-types", ] [[package]] @@ -166,9 +165,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb6e6436a9530f25010d13653e206fab4c9feddacf21a54de8d7311b275bc56b" dependencies = [ "alloy-json-abi", - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-sol-type-parser", - "alloy-sol-types 0.7.6", + "alloy-sol-types", "const-hex", "itoa", "serde", @@ -182,7 +181,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4b0fc6a572ef2eebda0a31a5e393d451abda703fec917c75d9615d8c978cf2" dependencies = [ - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-rlp", "alloy-serde", "c-kzg", @@ -197,7 +196,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48450f9c6f0821c1eee00ed912942492ed4f11dd69532825833de23ecc7a2256" dependencies = [ - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-serde", "serde", ] @@ -208,7 +207,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaeaccd50238126e3a0ff9387c7c568837726ad4f4e399b528ca88104d6c25ef" dependencies = [ - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-sol-type-parser", "serde", "serde_json", @@ -220,7 +219,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d484c2a934d0a4d86f8ad4db8113cb1d607707a6c54f6e78f4f1b4451b47aa70" dependencies = [ - "alloy-primitives 0.7.6", + "alloy-primitives", "serde", "serde_json", "thiserror", @@ -236,39 +235,17 @@ dependencies = [ "alloy-consensus", "alloy-eips", "alloy-json-rpc", - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", "alloy-signer", - "alloy-sol-types 0.7.6", + "alloy-sol-types", "async-trait", "auto_impl", "futures-utils-wasm", "thiserror", ] -[[package]] -name = "alloy-primitives" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e416903084d3392ebd32d94735c395d6709415b76c7728e594d3f996f2b03e65" -dependencies = [ - "alloy-rlp", - "arbitrary", - "bytes", - "cfg-if 1.0.0", - "const-hex", - "derive_arbitrary", - "derive_more", - "hex-literal", - "itoa", - "proptest", - "proptest-derive", - "ruint", - "serde", - "tiny-keccak", -] - [[package]] name = "alloy-primitives" version = "0.7.6" @@ -276,16 +253,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad" dependencies = [ "alloy-rlp", + "arbitrary", "bytes", "cfg-if 1.0.0", "const-hex", + "derive_arbitrary", "derive_more", + "ethereum_ssz", "getrandom", "hex-literal", "itoa", "k256", "keccak-asm", "proptest", + "proptest-derive", "rand", "ruint", "serde", @@ -303,7 +284,7 @@ dependencies = [ "alloy-eips", "alloy-json-rpc", "alloy-network", - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-rpc-client", "alloy-rpc-types-eth", "alloy-transport", @@ -341,8 +322,8 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -385,10 +366,10 @@ checksum = "13bd7aa9ff9e67f1ba7ee0dd8cebfc95831d1649b0e4eeefae940dc3681079fa" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-rlp", "alloy-serde", - "alloy-sol-types 0.7.6", + "alloy-sol-types", "itertools 0.13.0", "serde", "serde_json", @@ -401,7 +382,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8913f9e825068d77c516188c221c44f78fd814fce8effe550a783295a2757d19" dependencies = [ - "alloy-primitives 0.7.6", + "alloy-primitives", "serde", "serde_json", ] @@ -412,7 +393,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f740e13eb4c6a0e4d0e49738f1e86f31ad2d7ef93be499539f492805000f7237" dependencies = [ - "alloy-primitives 0.7.6", + "alloy-primitives", "async-trait", "auto_impl", "elliptic-curve", @@ -428,7 +409,7 @@ checksum = "87db68d926887393a1d0f9c43833b44446ea29d603291e7b20e5d115f31aa4e3" dependencies = [ "alloy-consensus", "alloy-network", - "alloy-primitives 0.7.6", + "alloy-primitives", "alloy-signer", "async-trait", "elliptic-curve", @@ -438,21 +419,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "alloy-sol-macro" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ceeffdacf9dd0910404d743d07273776fd17b85f9cb17b49a97e5c6055ce9" -dependencies = [ - "dunce", - "heck 0.4.1", - "proc-macro2 1.0.86", - "quote 1.0.36", - "syn 2.0.68", - "syn-solidity 0.3.1", - "tiny-keccak", -] - [[package]] name = "alloy-sol-macro" version = "0.7.6" @@ -462,8 +428,8 @@ dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -476,13 +442,13 @@ dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", - "heck 0.5.0", + "heck", "indexmap 2.2.6", "proc-macro-error", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", - "syn-solidity 0.7.6", + "syn-solidity", "tiny-keccak", ] @@ -495,12 +461,12 @@ dependencies = [ "alloy-json-abi", "const-hex", "dunce", - "heck 0.5.0", - "proc-macro2 1.0.86", - "quote 1.0.36", + "heck", + "proc-macro2", + "quote", "serde_json", "syn 2.0.68", - "syn-solidity 0.7.6", + "syn-solidity", ] [[package]] @@ -512,17 +478,6 @@ dependencies = [ "winnow 0.6.13", ] -[[package]] -name = "alloy-sol-types" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f347cb6bb307b3802ec455ef43ce00f5e590e0ceca3d2f3b070f5ee367e235" -dependencies = [ - "alloy-primitives 0.3.3", - "alloy-sol-macro 0.3.1", - "const-hex", -] - [[package]] name = "alloy-sol-types" version = "0.7.6" @@ -530,8 +485,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a49042c6d3b66a9fe6b2b5a8bf0d39fc2ae1ee0310a2a26ffedd79fb097878dd" dependencies = [ "alloy-json-abi", - "alloy-primitives 0.7.6", - "alloy-sol-macro 0.7.6", + "alloy-primitives", + "alloy-sol-macro", "const-hex", "serde", ] @@ -668,7 +623,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "quote 1.0.36", + "quote", "syn 1.0.109", ] @@ -678,7 +633,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "quote 1.0.36", + "quote", "syn 1.0.109", ] @@ -690,7 +645,7 @@ checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ "num-bigint", "num-traits", - "quote 1.0.36", + "quote", "syn 1.0.109", ] @@ -702,8 +657,8 @@ checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint", "num-traits", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -771,8 +726,8 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -782,8 +737,8 @@ version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -793,8 +748,8 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -841,7 +796,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" name = "basic-example" version = "0.0.0" dependencies = [ - "alloy-primitives 0.3.3", + "alloy-primitives", "mini-alloc", "openzeppelin-stylus", "stylus-proc", @@ -853,7 +808,7 @@ name = "basic-example-script" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "basic-example", "koba", "tokio", @@ -864,7 +819,7 @@ name = "benches" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "keccak-const", @@ -983,8 +938,8 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -1079,9 +1034,9 @@ version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ - "heck 0.5.0", - "proc-macro2 1.0.86", - "quote 1.0.36", + "heck", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -1310,7 +1265,7 @@ name = "cryptography-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "mini-alloc", @@ -1347,8 +1302,8 @@ checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -1359,7 +1314,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", - "quote 1.0.36", + "quote", "syn 2.0.68", ] @@ -1392,8 +1347,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -1403,8 +1358,8 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -1415,8 +1370,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case 0.4.0", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "rustc_version 0.4.0", "syn 2.0.68", ] @@ -1466,8 +1421,8 @@ dependencies = [ name = "e2e-proc" version = "0.1.0" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -1525,8 +1480,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -1546,8 +1501,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" dependencies = [ "darling", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -1562,7 +1517,7 @@ name = "erc20-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "mini-alloc", @@ -1577,7 +1532,7 @@ name = "erc20-permit-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "mini-alloc", @@ -1592,8 +1547,8 @@ name = "erc721-consecutive-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", - "alloy-sol-types 0.3.1", + "alloy-primitives", + "alloy-sol-types", "e2e", "eyre", "mini-alloc", @@ -1609,7 +1564,7 @@ name = "erc721-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "mini-alloc", @@ -1625,7 +1580,7 @@ name = "erc721-metadata-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "mini-alloc", @@ -1668,6 +1623,44 @@ dependencies = [ "uuid 0.8.2", ] +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "ethereum_ssz" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3627f83d8b87b432a5fad9934b4565260722a141a2c40f371f8080adec9425" +dependencies = [ + "ethereum-types", + "itertools 0.10.5", + "smallvec", +] + [[package]] name = "eyre" version = "0.6.12" @@ -1717,6 +1710,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ + "arbitrary", "byteorder", "rand", "rustc-hex", @@ -1813,8 +1807,8 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -1938,12 +1932,6 @@ dependencies = [ "allocator-api2", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -2100,14 +2088,32 @@ dependencies = [ "parity-scale-codec", ] +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + [[package]] name = "impl-trait-for-tuples" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -2356,8 +2362,8 @@ checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" name = "merkle-proofs-example" version = "0.0.0" dependencies = [ - "alloy-primitives 0.3.3", - "alloy-sol-types 0.3.1", + "alloy-primitives", + "alloy-sol-types", "mini-alloc", "openzeppelin-crypto", "stylus-proc", @@ -2421,11 +2427,11 @@ dependencies = [ name = "motsu-proc" version = "0.1.0" dependencies = [ - "alloy-primitives 0.3.3", - "alloy-sol-types 0.3.1", + "alloy-primitives", + "alloy-sol-types", "motsu", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "stylus-proc", "stylus-sdk", "syn 2.0.68", @@ -2502,8 +2508,8 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -2543,8 +2549,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -2580,8 +2586,8 @@ dependencies = [ name = "openzeppelin-stylus" version = "0.1.0-rc" dependencies = [ - "alloy-primitives 0.3.3", - "alloy-sol-types 0.3.1", + "alloy-primitives", + "alloy-sol-types", "keccak-const", "mini-alloc", "motsu", @@ -2595,7 +2601,7 @@ name = "ownable-example" version = "0.0.0" dependencies = [ "alloy", - "alloy-primitives 0.3.3", + "alloy-primitives", "e2e", "eyre", "mini-alloc", @@ -2632,8 +2638,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -2707,8 +2713,8 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -2754,6 +2760,8 @@ checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", + "impl-rlp", + "impl-serde", "uint", ] @@ -2773,8 +2781,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", "version_check", ] @@ -2785,20 +2793,11 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "version_check", ] -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -dependencies = [ - "unicode-xid", -] - [[package]] name = "proc-macro2" version = "1.0.86" @@ -2830,13 +2829,13 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90b46295382dc76166cb7cf2bb4a97952464e4b7ed5a43e6cd34e1fec3349ddc" +checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -2854,8 +2853,8 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -2865,22 +2864,13 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -dependencies = [ - "proc-macro2 0.4.30", -] - [[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ - "proc-macro2 1.0.86", + "proc-macro2", ] [[package]] @@ -3093,8 +3083,8 @@ version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -3351,8 +3341,8 @@ version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -3518,40 +3508,40 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", - "proc-macro2 1.0.86", - "quote 1.0.36", + "heck", + "proc-macro2", + "quote", "rustversion", "syn 2.0.68", ] [[package]] name = "stylus-proc" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f274700c5c74abfcc9068f96564615173d8fed72ea44afd1e4404bb04478c00" +checksum = "9fd02e91dffe7b73df84a861c992494d6b72054bc9a17fe73e147e34e9a64ef3" dependencies = [ - "alloy-primitives 0.3.3", - "alloy-sol-types 0.3.1", + "alloy-primitives", + "alloy-sol-types", "cfg-if 1.0.0", "convert_case 0.6.0", "lazy_static", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "regex", "sha3", "syn 1.0.109", - "syn-solidity 0.3.1", + "syn-solidity", ] [[package]] name = "stylus-sdk" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4424e5f067b1b0922a4294efc01acaa1e36bfc7b31e6b0aed33d7221680f974" +checksum = "26042693706e29fb7e3cf3d71c99534ac97fca98b6f81ba77ab658022ab2e210" dependencies = [ - "alloy-primitives 0.3.3", - "alloy-sol-types 0.3.1", + "alloy-primitives", + "alloy-sol-types", "cfg-if 1.0.0", "derivative", "hex", @@ -3566,25 +3556,14 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid", -] - [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "unicode-ident", ] @@ -3594,22 +3573,11 @@ version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "unicode-ident", ] -[[package]] -name = "syn-solidity" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5f995d2140b0f751dbe94365be2591edbf3d1b75dcfaeac14183abbd2ff07bd" -dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", - "syn 2.0.68", -] - [[package]] name = "syn-solidity" version = "0.7.6" @@ -3617,8 +3585,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d71e19bca02c807c9faa67b5a47673ff231b6e7449b251695188522f1dc44b2" dependencies = [ "paste", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -3667,8 +3635,8 @@ version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -3730,8 +3698,8 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -3861,8 +3829,8 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -3899,6 +3867,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ + "arbitrary", "byteorder", "crunchy", "hex", @@ -3944,12 +3913,6 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" - [[package]] name = "url" version = "2.5.2" @@ -4044,8 +4007,8 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", "wasm-bindgen-shared", ] @@ -4068,8 +4031,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -4091,7 +4054,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ - "quote 1.0.36", + "quote", "wasm-bindgen-macro-support", ] @@ -4101,8 +4064,8 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -4200,8 +4163,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97901fdbaae383dbb90ea162cc3a76a9fa58ac39aec7948b4c0b9bbef9307738" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 1.0.109", ] @@ -4558,8 +4521,8 @@ version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] @@ -4578,7 +4541,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.36", + "proc-macro2", + "quote", "syn 2.0.68", ] diff --git a/Cargo.toml b/Cargo.toml index 5e0d14f7..f196fd18 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,11 +60,11 @@ all = "warn" [workspace.dependencies] # stylus-related -stylus-sdk = { version = "=0.5.0", default-features = false } -stylus-proc = { version = "=0.5.0", default-features = false } +stylus-sdk = { version = "=0.6.0", default-features = false } +stylus-proc = { version = "=0.6.0", default-features = false } mini-alloc = "0.4.2" -alloy = { version = "0.1.1", features = [ +alloy = { version = "0.1.4", features = [ "contract", "network", "providers", @@ -77,8 +77,8 @@ alloy = { version = "0.1.1", features = [ # Even though `alloy` includes `alloy-primitives` and `alloy-sol-types` we need # to keep both versions for compatibility with the Stylus SDK. Once they start # using `alloy` we can remove these. -alloy-primitives = { version = "0.3.1", default-features = false } -alloy-sol-types = { version = "0.3.1", default-features = false } +alloy-primitives = { version = "0.7.6", default-features = false } +alloy-sol-types = { version = "0.7.6", default-features = false } const-hex = { version = "1.11.1", default-features = false } eyre = "0.6.8" diff --git a/benches/Cargo.toml b/benches/Cargo.toml index c6b5c745..921de2f6 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -8,7 +8,7 @@ version = "0.0.0" [dependencies] openzeppelin-stylus = { path = "../contracts" } -alloy-primitives.workspace = true +alloy-primitives = { workspace = true, features = ["tiny-keccak"] } alloy.workspace = true tokio.workspace = true eyre.workspace = true diff --git a/contracts/src/access/control.rs b/contracts/src/access/control.rs index c3ca0e22..7d5a7cf5 100644 --- a/contracts/src/access/control.rs +++ b/contracts/src/access/control.rs @@ -45,7 +45,7 @@ use alloy_sol_types::sol; use stylus_proc::SolidityError; use stylus_sdk::{ evm, msg, - stylus_proc::{external, sol_storage}, + stylus_proc::{public, sol_storage}, }; sol! { @@ -115,7 +115,7 @@ sol_storage! { } } -#[external] +#[public] impl AccessControl { /// The default admin role. `[0; 32]` by default. pub const DEFAULT_ADMIN_ROLE: [u8; 32] = [0; 32]; @@ -286,9 +286,9 @@ impl AccessControl { let previous_admin_role = self.get_role_admin(role); self._roles.setter(role).admin_role.set(new_admin_role); evm::log(RoleAdminChanged { - role: *role, - previous_admin_role: *previous_admin_role, - new_admin_role: *new_admin_role, + role, + previous_admin_role, + new_admin_role, }); } @@ -311,10 +311,7 @@ impl AccessControl { ) -> Result<(), Error> { if !self.has_role(role, account) { return Err(Error::UnauthorizedAccount( - AccessControlUnauthorizedAccount { - account, - needed_role: *role, - }, + AccessControlUnauthorizedAccount { account, needed_role: role }, )); } @@ -340,11 +337,7 @@ impl AccessControl { false } else { self._roles.setter(role).has_role.insert(account, true); - evm::log(RoleGranted { - role: *role, - account, - sender: msg::sender(), - }); + evm::log(RoleGranted { role, account, sender: msg::sender() }); true } } @@ -366,11 +359,7 @@ impl AccessControl { pub fn _revoke_role(&mut self, role: B256, account: Address) -> bool { if self.has_role(role, account) { self._roles.setter(role).has_role.insert(account, false); - evm::log(RoleRevoked { - role: *role, - account, - sender: msg::sender(), - }); + evm::log(RoleRevoked { role, account, sender: msg::sender() }); true } else { false diff --git a/contracts/src/access/ownable.rs b/contracts/src/access/ownable.rs index 7c51d191..01a56369 100644 --- a/contracts/src/access/ownable.rs +++ b/contracts/src/access/ownable.rs @@ -13,7 +13,7 @@ use alloy_sol_types::sol; use stylus_proc::SolidityError; use stylus_sdk::{ evm, msg, - stylus_proc::{external, sol_storage}, + stylus_proc::{public, sol_storage}, }; sol! { @@ -54,7 +54,7 @@ sol_storage! { } } -#[external] +#[public] impl Ownable { /// Returns the address of the current owner. pub fn owner(&self) -> Address { diff --git a/contracts/src/token/erc20/extensions/capped.rs b/contracts/src/token/erc20/extensions/capped.rs index 5329038a..40fdea92 100644 --- a/contracts/src/token/erc20/extensions/capped.rs +++ b/contracts/src/token/erc20/extensions/capped.rs @@ -7,7 +7,7 @@ use alloy_primitives::U256; use alloy_sol_types::sol; -use stylus_proc::{external, sol_storage, SolidityError}; +use stylus_proc::{public, sol_storage, SolidityError}; sol! { /// Indicates an error related to the operation that failed @@ -43,7 +43,7 @@ sol_storage! { } } -#[external] +#[public] impl Capped { /// Returns the cap on the token's total supply. pub fn cap(&self) -> U256 { diff --git a/contracts/src/token/erc20/extensions/metadata.rs b/contracts/src/token/erc20/extensions/metadata.rs index f3db7420..4035f558 100644 --- a/contracts/src/token/erc20/extensions/metadata.rs +++ b/contracts/src/token/erc20/extensions/metadata.rs @@ -2,7 +2,7 @@ use alloc::string::String; -use stylus_proc::{external, sol_storage}; +use stylus_proc::{public, sol_storage}; /// Number of decimals used by default on implementors of [`Metadata`]. pub const DEFAULT_DECIMALS: u8 = 18; @@ -59,7 +59,7 @@ pub trait IErc20Metadata { // FIXME: Apply multi-level inheritance to export Metadata's functions. // With the current version of SDK it is not possible. // See https://github.com/OffchainLabs/stylus-sdk-rs/pull/120 -#[external] +#[public] impl IErc20Metadata for Erc20Metadata { fn name(&self) -> String { self._metadata.name() diff --git a/contracts/src/token/erc20/extensions/permit.rs b/contracts/src/token/erc20/extensions/permit.rs index 00537371..0e57300d 100644 --- a/contracts/src/token/erc20/extensions/permit.rs +++ b/contracts/src/token/erc20/extensions/permit.rs @@ -11,7 +11,7 @@ //! and thus is not required to hold Ether at all. use alloy_primitives::{b256, keccak256, Address, B256, U256}; use alloy_sol_types::{sol, SolType}; -use stylus_proc::{external, sol_storage, SolidityError}; +use stylus_proc::{public, sol_storage, SolidityError}; use stylus_sdk::{block, prelude::StorageType, storage::TopLevelStorage}; use crate::{ @@ -77,7 +77,7 @@ sol_storage! { /// BorrowMut)`. Should be fixed in the future by the Stylus team. unsafe impl TopLevelStorage for Erc20Permit {} -#[external] +#[public] impl Erc20Permit { /// Returns the current nonce for `owner`. /// @@ -156,7 +156,7 @@ impl Erc20Permit { return Err(ERC2612ExpiredSignature { deadline }.into()); } - let struct_hash = keccak256(StructHashTuple::encode_params(&( + let struct_hash = keccak256(StructHashTuple::abi_encode(&( *PERMIT_TYPEHASH, owner, spender, diff --git a/contracts/src/token/erc20/mod.rs b/contracts/src/token/erc20/mod.rs index 240d93bb..5f9629af 100644 --- a/contracts/src/token/erc20/mod.rs +++ b/contracts/src/token/erc20/mod.rs @@ -10,7 +10,7 @@ use stylus_proc::SolidityError; use stylus_sdk::{ call::MethodError, evm, msg, - stylus_proc::{external, sol_storage}, + stylus_proc::{public, sol_storage}, }; pub mod extensions; @@ -238,7 +238,7 @@ pub trait IErc20 { ) -> Result; } -#[external] +#[public] impl IErc20 for Erc20 { type Error = Error; diff --git a/contracts/src/token/erc721/extensions/consecutive.rs b/contracts/src/token/erc721/extensions/consecutive.rs index 51ee0cf4..35a88440 100644 --- a/contracts/src/token/erc721/extensions/consecutive.rs +++ b/contracts/src/token/erc721/extensions/consecutive.rs @@ -26,7 +26,7 @@ use alloc::vec; use alloy_primitives::{uint, Address, U256}; use alloy_sol_types::sol; -use stylus_proc::{external, sol_storage, SolidityError}; +use stylus_proc::{public, sol_storage, SolidityError}; use stylus_sdk::{abi::Bytes, evm, msg, prelude::TopLevelStorage}; use crate::{ @@ -131,7 +131,7 @@ unsafe impl TopLevelStorage for Erc721Consecutive {} // ************** ERC-721 External ************** -#[external] +#[public] impl IErc721 for Erc721Consecutive { type Error = Error; @@ -168,7 +168,7 @@ impl IErc721 for Erc721Consecutive { from, to, token_id, - &data, + data, )?) } @@ -547,7 +547,7 @@ impl Erc721Consecutive { Address::ZERO, to, token_id, - &data, + data, )?) } @@ -700,7 +700,7 @@ impl Erc721Consecutive { from, to, token_id, - &data, + data, )?) } diff --git a/contracts/src/token/erc721/extensions/enumerable.rs b/contracts/src/token/erc721/extensions/enumerable.rs index 41604064..263f676a 100644 --- a/contracts/src/token/erc721/extensions/enumerable.rs +++ b/contracts/src/token/erc721/extensions/enumerable.rs @@ -12,7 +12,7 @@ use alloy_primitives::{uint, Address, U256}; use alloy_sol_types::sol; -use stylus_proc::{external, sol_storage, SolidityError}; +use stylus_proc::{public, sol_storage, SolidityError}; use crate::token::{erc721, erc721::IErc721}; @@ -114,7 +114,7 @@ pub trait IErc721Enumerable { fn token_by_index(&self, index: U256) -> Result; } -#[external] +#[public] impl IErc721Enumerable for Erc721Enumerable { type Error = Error; diff --git a/contracts/src/token/erc721/extensions/metadata.rs b/contracts/src/token/erc721/extensions/metadata.rs index 9bb5b34a..5b315bf4 100644 --- a/contracts/src/token/erc721/extensions/metadata.rs +++ b/contracts/src/token/erc721/extensions/metadata.rs @@ -2,7 +2,7 @@ use alloc::string::String; -use stylus_proc::{external, sol_storage}; +use stylus_proc::{public, sol_storage}; use crate::utils::Metadata; @@ -44,7 +44,7 @@ pub trait IErc721Metadata { // FIXME: Apply multi-level inheritance to export Metadata's functions. // With the current version of SDK it is not possible. // See https://github.com/OffchainLabs/stylus-sdk-rs/pull/120 -#[external] +#[public] impl IErc721Metadata for Erc721Metadata { fn name(&self) -> String { self._metadata.name() diff --git a/contracts/src/token/erc721/extensions/uri_storage.rs b/contracts/src/token/erc721/extensions/uri_storage.rs index fd5ad0ba..f5afc180 100644 --- a/contracts/src/token/erc721/extensions/uri_storage.rs +++ b/contracts/src/token/erc721/extensions/uri_storage.rs @@ -5,7 +5,7 @@ use alloc::string::String; use alloy_primitives::U256; use alloy_sol_types::sol; -use stylus_proc::{external, sol_storage}; +use stylus_proc::{public, sol_storage}; use stylus_sdk::evm; sol! { @@ -48,7 +48,7 @@ impl Erc721UriStorage { } } -#[external] +#[public] impl Erc721UriStorage { /// Returns the Uniform Resource Identifier (URI) for `token_id` token. /// diff --git a/contracts/src/token/erc721/mod.rs b/contracts/src/token/erc721/mod.rs index 30fdef3d..119422f1 100644 --- a/contracts/src/token/erc721/mod.rs +++ b/contracts/src/token/erc721/mod.rs @@ -462,7 +462,7 @@ pub trait IErc721 { fn is_approved_for_all(&self, owner: Address, operator: Address) -> bool; } -#[external] +#[public] impl IErc721 for Erc721 { type Error = Error; @@ -497,7 +497,7 @@ impl IErc721 for Erc721 { data: Bytes, ) -> Result<(), Error> { self.transfer_from(from, to, token_id)?; - self._check_on_erc721_received(msg::sender(), from, to, token_id, &data) + self._check_on_erc721_received(msg::sender(), from, to, token_id, data) } fn transfer_from( @@ -814,7 +814,7 @@ impl Erc721 { Address::ZERO, to, token_id, - &data, + data, ) } @@ -955,7 +955,7 @@ impl Erc721 { data: Bytes, ) -> Result<(), Error> { self._transfer(from, to, token_id)?; - self._check_on_erc721_received(msg::sender(), from, to, token_id, &data) + self._check_on_erc721_received(msg::sender(), from, to, token_id, data) } /// Approve `to` to operate on `token_id`. @@ -1101,7 +1101,7 @@ impl Erc721 { from: Address, to: Address, token_id: U256, - data: &Bytes, + data: Bytes, ) -> Result<(), Error> { const RECEIVER_FN_SELECTOR: FixedBytes<4> = fixed_bytes!("150b7a02"); @@ -1111,9 +1111,13 @@ impl Erc721 { let receiver = IERC721Receiver::new(to); let call = Call::new_in(self); - let data = data.to_vec(); - let result = - receiver.on_erc_721_received(call, operator, from, token_id, data); + let result = receiver.on_erc_721_received( + call, + operator, + from, + token_id, + data.to_vec().into(), + ); let id = match result { Ok(id) => id, diff --git a/contracts/src/utils/cryptography/ecdsa.rs b/contracts/src/utils/cryptography/ecdsa.rs index 0bf4659a..e667393d 100644 --- a/contracts/src/utils/cryptography/ecdsa.rs +++ b/contracts/src/utils/cryptography/ecdsa.rs @@ -170,8 +170,8 @@ fn _recover( /// * `r` - `r` value from the signature. /// * `s` - `s` value from the signature. fn encode_calldata(hash: B256, v: u8, r: B256, s: B256) -> Vec { - let calldata = EcRecoverData { hash: *hash, v, r: *r, s: *s }; - EcRecoverData::encode(&calldata) + let calldata = EcRecoverData { hash, v, r, s }; + EcRecoverData::abi_encode(&calldata) } /// Validates the `s` value of a signature. @@ -207,7 +207,7 @@ fn encode_calldata(hash: B256, v: u8, r: B256, s: B256) -> Vec { fn check_if_malleable(s: &B256) -> Result<(), Error> { let s_u256 = U256::from_be_slice(s.as_slice()); if s_u256 > SIGNATURE_S_UPPER_BOUND { - return Err(ECDSAInvalidSignatureS { s: **s }.into()); + return Err(ECDSAInvalidSignatureS { s: *s }.into()); } Ok(()) } diff --git a/contracts/src/utils/cryptography/eip712.rs b/contracts/src/utils/cryptography/eip712.rs index 2dab05fd..4a13e1ab 100644 --- a/contracts/src/utils/cryptography/eip712.rs +++ b/contracts/src/utils/cryptography/eip712.rs @@ -110,7 +110,7 @@ pub trait IEip712 { /// /// * `&self` - Read access to the contract's state. fn domain_separator_v4(&self) -> B256 { - let encoded = DomainSeparatorTuple::encode(&( + let encoded = DomainSeparatorTuple::abi_encode(&( TYPE_HASH, Self::HASHED_NAME, Self::HASHED_VERSION, diff --git a/contracts/src/utils/metadata.rs b/contracts/src/utils/metadata.rs index b9ff5070..de3e83f8 100644 --- a/contracts/src/utils/metadata.rs +++ b/contracts/src/utils/metadata.rs @@ -1,7 +1,7 @@ //! Common Metadata Smart Contract. use alloc::string::String; -use stylus_proc::{external, sol_storage}; +use stylus_proc::{public, sol_storage}; sol_storage! { /// Metadata of the token. @@ -13,7 +13,7 @@ sol_storage! { } } -#[external] +#[public] impl Metadata { /// Returns the name of the token. /// diff --git a/contracts/src/utils/nonces.rs b/contracts/src/utils/nonces.rs index 6426429a..da02be73 100644 --- a/contracts/src/utils/nonces.rs +++ b/contracts/src/utils/nonces.rs @@ -4,7 +4,7 @@ use alloy_primitives::{uint, Address, U256}; use alloy_sol_types::sol; -use stylus_proc::{external, sol_storage, SolidityError}; +use stylus_proc::{public, sol_storage, SolidityError}; const ONE: U256 = uint!(1_U256); @@ -30,7 +30,7 @@ sol_storage! { } } -#[external] +#[public] impl Nonces { /// Returns the unused nonce for the given account. /// diff --git a/contracts/src/utils/pausable.rs b/contracts/src/utils/pausable.rs index d838ac60..a49aec77 100644 --- a/contracts/src/utils/pausable.rs +++ b/contracts/src/utils/pausable.rs @@ -11,7 +11,7 @@ //! only once the modifiers are put in place. use alloy_sol_types::sol; -use stylus_proc::{external, sol_storage, SolidityError}; +use stylus_proc::{public, sol_storage, SolidityError}; use stylus_sdk::{evm, msg}; sol! { @@ -57,7 +57,7 @@ sol_storage! { } } -#[external] +#[public] impl Pausable { /// Returns true if the contract is paused, and false otherwise. /// diff --git a/examples/access-control/src/lib.rs b/examples/access-control/src/lib.rs index 20dba96e..dc7e416a 100644 --- a/examples/access-control/src/lib.rs +++ b/examples/access-control/src/lib.rs @@ -8,7 +8,7 @@ use openzeppelin_stylus::{ access::control::AccessControl, token::erc20::{Erc20, IErc20}, }; -use stylus_sdk::prelude::{entrypoint, external, sol_storage}; +use stylus_sdk::prelude::{entrypoint, public, sol_storage}; sol_storage! { #[entrypoint] @@ -26,7 +26,7 @@ pub const TRANSFER_ROLE: [u8; 32] = [ 166, 190, 60, 19, 139, 159, 191, 0, 55, 82, 164, 200, 188, 232, 111, 108, ]; -#[external] +#[public] #[inherit(Erc20, AccessControl)] impl AccessControlExample { pub const TRANSFER_ROLE: [u8; 32] = TRANSFER_ROLE; diff --git a/examples/basic/token/src/lib.rs b/examples/basic/token/src/lib.rs index c237d8b6..6510b223 100644 --- a/examples/basic/token/src/lib.rs +++ b/examples/basic/token/src/lib.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; use alloy_primitives::{Address, U256}; use openzeppelin_stylus::token::erc20::{extensions::Erc20Metadata, Erc20}; -use stylus_sdk::prelude::{entrypoint, external, sol_storage}; +use stylus_sdk::prelude::{entrypoint, public, sol_storage}; sol_storage! { #[entrypoint] @@ -17,7 +17,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc20, Erc20Metadata)] impl Erc20Example { pub fn mint( diff --git a/examples/ecdsa/src/lib.rs b/examples/ecdsa/src/lib.rs index 327dcdf1..7f31e621 100644 --- a/examples/ecdsa/src/lib.rs +++ b/examples/ecdsa/src/lib.rs @@ -5,14 +5,14 @@ use alloc::vec::Vec; use alloy_primitives::{Address, B256}; use openzeppelin_stylus::utils::cryptography::ecdsa; -use stylus_sdk::prelude::{entrypoint, external, sol_storage}; +use stylus_sdk::prelude::{entrypoint, public, sol_storage}; sol_storage! { #[entrypoint] struct ECDSAExample {} } -#[external] +#[public] impl ECDSAExample { pub fn recover( &mut self, diff --git a/examples/erc20-permit/src/lib.rs b/examples/erc20-permit/src/lib.rs index 599e40d3..6853704b 100644 --- a/examples/erc20-permit/src/lib.rs +++ b/examples/erc20-permit/src/lib.rs @@ -7,7 +7,7 @@ use alloy_primitives::{Address, U256}; use openzeppelin_stylus::{ token::erc20::extensions::Erc20Permit, utils::cryptography::eip712::IEip712, }; -use stylus_sdk::prelude::{entrypoint, external, sol_storage}; +use stylus_sdk::prelude::{entrypoint, public, sol_storage}; sol_storage! { #[entrypoint] @@ -24,7 +24,7 @@ impl IEip712 for Eip712 { const VERSION: &'static str = "1"; } -#[external] +#[public] #[inherit(Erc20Permit)] impl Erc20PermitExample { // Add token minting feature. diff --git a/examples/erc20/src/lib.rs b/examples/erc20/src/lib.rs index de212eef..407e87d0 100644 --- a/examples/erc20/src/lib.rs +++ b/examples/erc20/src/lib.rs @@ -11,7 +11,7 @@ use openzeppelin_stylus::{ }, utils::Pausable, }; -use stylus_sdk::prelude::{entrypoint, external, sol_storage}; +use stylus_sdk::prelude::{entrypoint, public, sol_storage}; const DECIMALS: u8 = 10; @@ -29,7 +29,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc20, Erc20Metadata, Capped, Pausable)] impl Erc20Example { // Overrides the default [`Metadata::decimals`], and sets it to `10`. diff --git a/examples/erc20/tests/erc20.rs b/examples/erc20/tests/erc20.rs index 86256b43..cc82c8de 100644 --- a/examples/erc20/tests/erc20.rs +++ b/examples/erc20/tests/erc20.rs @@ -2,10 +2,9 @@ use abi::Erc20; use alloy::{ - primitives::{Address, U256}, + primitives::{uint, Address, U256}, sol, }; -use alloy_primitives::uint; use e2e::{ receipt, send, watch, Account, EventExt, Panic, PanicCode, ReceiptExt, Revert, diff --git a/examples/erc721-consecutive/src/lib.rs b/examples/erc721-consecutive/src/lib.rs index d847499e..cb14ef03 100644 --- a/examples/erc721-consecutive/src/lib.rs +++ b/examples/erc721-consecutive/src/lib.rs @@ -15,7 +15,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc721Consecutive)] impl Erc721ConsecutiveExample { pub fn burn(&mut self, token_id: U256) -> Result<(), Error> { diff --git a/examples/erc721-metadata/src/lib.rs b/examples/erc721-metadata/src/lib.rs index 2dea5e55..006efa56 100644 --- a/examples/erc721-metadata/src/lib.rs +++ b/examples/erc721-metadata/src/lib.rs @@ -14,7 +14,7 @@ use openzeppelin_stylus::token::erc721::{ }, Erc721, IErc721, }; -use stylus_sdk::prelude::{entrypoint, external, sol_storage}; +use stylus_sdk::prelude::{entrypoint, public, sol_storage}; sol_storage! { #[entrypoint] @@ -28,7 +28,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc721, Metadata, UriStorage)] impl Erc721MetadataExample { pub fn mint(&mut self, to: Address, token_id: U256) -> Result<(), Vec> { diff --git a/examples/erc721/src/lib.rs b/examples/erc721/src/lib.rs index fe873815..8d2a4d62 100644 --- a/examples/erc721/src/lib.rs +++ b/examples/erc721/src/lib.rs @@ -13,7 +13,7 @@ use openzeppelin_stylus::{ }; use stylus_sdk::{ abi::Bytes, - prelude::{entrypoint, external, sol_storage}, + prelude::{entrypoint, public, sol_storage}, }; sol_storage! { @@ -28,7 +28,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc721, Enumerable, Pausable)] impl Erc721Example { pub fn burn(&mut self, token_id: U256) -> Result<(), Vec> { diff --git a/examples/erc721/tests/erc721.rs b/examples/erc721/tests/erc721.rs index a9356ccf..b8bf68fd 100644 --- a/examples/erc721/tests/erc721.rs +++ b/examples/erc721/tests/erc721.rs @@ -1,8 +1,7 @@ #![cfg(feature = "e2e")] use abi::Erc721; -use alloy::primitives::{fixed_bytes, Address, Bytes, U256}; -use alloy_primitives::uint; +use alloy::primitives::{fixed_bytes, uint, Address, Bytes, U256}; use e2e::{receipt, send, watch, Account, EventExt, ReceiptExt, Revert}; use mock::{receiver, receiver::ERC721ReceiverMock}; diff --git a/examples/merkle-proofs/src/lib.rs b/examples/merkle-proofs/src/lib.rs index ff466774..2fab9264 100644 --- a/examples/merkle-proofs/src/lib.rs +++ b/examples/merkle-proofs/src/lib.rs @@ -11,7 +11,7 @@ use openzeppelin_crypto::{ use stylus_proc::SolidityError; use stylus_sdk::{ alloy_sol_types::sol, - prelude::{entrypoint, external, sol_storage}, + prelude::{entrypoint, public, sol_storage}, }; #[global_allocator] @@ -61,7 +61,7 @@ sol_storage! { struct VerifierContract { } } -#[external] +#[public] impl VerifierContract { pub fn verify(&self, proof: Vec, root: B256, leaf: B256) -> bool { let proof: Vec<[u8; 32]> = proof.into_iter().map(|m| *m).collect(); diff --git a/examples/ownable/src/lib.rs b/examples/ownable/src/lib.rs index 7cad28fb..43d1aef2 100644 --- a/examples/ownable/src/lib.rs +++ b/examples/ownable/src/lib.rs @@ -8,7 +8,7 @@ use openzeppelin_stylus::{ access::ownable::Ownable, token::erc20::{Erc20, IErc20}, }; -use stylus_sdk::prelude::{entrypoint, external, sol_storage}; +use stylus_sdk::prelude::{entrypoint, public, sol_storage}; sol_storage! { #[entrypoint] @@ -20,7 +20,7 @@ sol_storage! { } } -#[external] +#[public] #[inherit(Erc20, Ownable)] impl OwnableExample { pub fn transfer( diff --git a/scripts/check-wasm.sh b/scripts/check-wasm.sh index 1f6ce078..9ec839dd 100755 --- a/scripts/check-wasm.sh +++ b/scripts/check-wasm.sh @@ -12,7 +12,7 @@ check_wasm () { echo echo "Checking contract $CONTRACT_CRATE_NAME" - cargo stylus check --wasm-file ./target/wasm32-unknown-unknown/release/"$CONTRACT_BIN_NAME" --no-verify + cargo stylus check --wasm-file ./target/wasm32-unknown-unknown/release/"$CONTRACT_BIN_NAME" } # Retrieve all alphanumeric contract's crate names in `./examples` directory. From ce60bebbf5323b927f4e0ac3ed2408605629fca3 Mon Sep 17 00:00:00 2001 From: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:37:47 +0400 Subject: [PATCH 04/16] docs: e2e tests setup guide (#277) Extend guidelines for e2e tests and adjust ux of few scripts. --------- Co-authored-by: Gustavo Gonzalez --- .github/workflows/e2e-tests.yml | 2 +- .github/workflows/gas-bench.yml | 2 +- GUIDELINES.md | 48 +++++++++++++++++++++++++++++---- lib/e2e/src/system.rs | 6 +++-- scripts/e2e-tests.sh | 2 +- scripts/nitro-testnode.sh | 8 +++--- 6 files changed, 54 insertions(+), 14 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index f1a5880b..cebd0379 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -43,7 +43,7 @@ jobs: - name: install solc run: | - curl -LO https://github.com/ethereum/solidity/releases/download/v0.8.21/solc-static-linux + curl -LO https://github.com/ethereum/solidity/releases/download/v0.8.24/solc-static-linux sudo mv solc-static-linux /usr/bin/solc sudo chmod a+x /usr/bin/solc diff --git a/.github/workflows/gas-bench.yml b/.github/workflows/gas-bench.yml index 7d572fc4..67a6f127 100644 --- a/.github/workflows/gas-bench.yml +++ b/.github/workflows/gas-bench.yml @@ -33,7 +33,7 @@ jobs: - name: install solc run: | - curl -LO https://github.com/ethereum/solidity/releases/download/v0.8.21/solc-static-linux + curl -LO https://github.com/ethereum/solidity/releases/download/v0.8.24/solc-static-linux sudo mv solc-static-linux /usr/bin/solc sudo chmod a+x /usr/bin/solc diff --git a/GUIDELINES.md b/GUIDELINES.md index 6f41be09..2772b3a5 100644 --- a/GUIDELINES.md +++ b/GUIDELINES.md @@ -131,7 +131,7 @@ Use 1-word names for function parameters or variables that have larger scopes: ```rust pub fn commit(repo: &Repository, sig: &Signature) -> Result { -... + ... } ``` @@ -207,6 +207,41 @@ Make sure all tests are passing with: $ cargo test --all-features +### Running end-to-end tests + +In order to run end-to-end (e2e) tests you need to have a specific nightly toolchain. +"Nightly" is necessary to use optimization compiler flags and have contract wasm small enough to be eligible for +deployment. + +Run the following commands to install the necessary toolchain: + +```shell +rustup install nightly-2024-01-01 +rustup component add rust-src +``` + +Also, you should have the cargo stylus tool: + +```shell +cargo install cargo-stylus +``` + +Since most of the e2e tests use [koba](https://github.com/OpenZeppelin/koba) for deploying contracts, you need to +[install](https://docs.soliditylang.org/en/latest/installing-solidity.html#) the solidity compiler (`v0.8.24`). + +To run e2e tests, you need to have a local nitro test node up and running. +Run the following command and wait till script exit successfully: + +```shell +./scripts/nitro-testnode.sh -i -d +``` + +Then you will be able to run e2e tests: + +```shell +./scripts/e2e-tests.sh +``` + ### Checking the docs If you make documentation changes, you may want to check whether there are any @@ -279,12 +314,15 @@ conventions that must be followed. - Custom errors should be declared following the [EIP-6093] rationale whenever reasonable. Also, consider the following: - - The domain prefix should be picked in the following order: - 1. Use `ERC` if the error is a violation of an ERC specification. - 2. Use the name of the underlying component where it belongs (eg. - `Governor`, `ECDSA`, or `Timelock`). + - The domain prefix should be picked in the following order: + 1. Use `ERC` if the error is a violation of an ERC specification. + 2. Use the name of the underlying component where it belongs (eg. + `Governor`, `ECDSA`, or `Timelock`). [The Rust Style Guide]: https://doc.rust-lang.org/nightly/style-guide/ + [EIP-6093]: https://eips.ethereum.org/EIPS/eip-6093 + [Semantic versioning]: https://semver.org/spec/v2.0.0.html + [Conventional Commits]: https://www.conventionalcommits.org/en/v1.0.0/ diff --git a/lib/e2e/src/system.rs b/lib/e2e/src/system.rs index 0bd0d487..aef9ac3e 100644 --- a/lib/e2e/src/system.rs +++ b/lib/e2e/src/system.rs @@ -62,9 +62,11 @@ pub fn provider() -> Provider { /// Send `amount` eth to `address` in the nitro-tesnode. pub fn fund_account(address: Address, amount: &str) -> eyre::Result<()> { - // ./test-node.bash script send-l2 --to - // address_0x01fA6bf4Ee48B6C95900BCcf9BEA172EF5DBd478 --ethamount 10 let node_script = get_node_path()?.join("test-node.bash"); + if !node_script.exists() { + bail!("Test nitro node wasn't setup properly. Try to setup it first with `./scripts/nitro-testnode.sh -i -d`") + }; + let output = std::process::Command::new(node_script) .arg("script") .arg("send-l2") diff --git a/scripts/e2e-tests.sh b/scripts/e2e-tests.sh index 3a26eacb..f7b9cdeb 100755 --- a/scripts/e2e-tests.sh +++ b/scripts/e2e-tests.sh @@ -5,7 +5,7 @@ MYDIR=$(realpath "$(dirname "$0")") cd "$MYDIR" cd .. -NIGHTLY_TOOLCHAIN=${NIGHTLY_TOOLCHAIN:-nightly} +NIGHTLY_TOOLCHAIN=${NIGHTLY_TOOLCHAIN:-nightly-2024-01-01} cargo +"$NIGHTLY_TOOLCHAIN" build --release --target wasm32-unknown-unknown -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort export RPC_URL=http://localhost:8547 diff --git a/scripts/nitro-testnode.sh b/scripts/nitro-testnode.sh index e14a8da4..815323c2 100755 --- a/scripts/nitro-testnode.sh +++ b/scripts/nitro-testnode.sh @@ -17,15 +17,15 @@ do HAS_DETACH=true shift ;; - -down|--shutdown) - docker container stop "$(docker container ls -q --filter name=nitro-testnode)" + -q|--quit) + docker container stop $(docker container ls -q --filter name=nitro-testnode) exit 0 ;; *) echo "OPTIONS:" echo "-i|--init: clone repo and init nitro test node" echo "-d|--detach: setup nitro test node in detached mode" - echo "-down|--shutdown: shutdown nitro test node docker containers" + echo "-q|--quit: shutdown nitro test node docker containers" exit 0 ;; esac @@ -46,7 +46,7 @@ then # `release` branch. git checkout 8cb6b84e31909157d431e7e4af9fb83799443e00 || exit - ./test-node.bash --no-run --init --no-tokenbridge || exit + ./test-node.bash --no-run --init || exit fi From 38ad0eda201c882d06ad7a6ec32c4d29c754d8cb Mon Sep 17 00:00:00 2001 From: Gustavo Gonzalez Date: Fri, 13 Sep 2024 07:41:47 -0400 Subject: [PATCH 05/16] docs: update readme to specify crates.io as the source (#283) - Specify crates.io as the main source for the library --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a036747a..5eab8f1b 100644 --- a/README.md +++ b/README.md @@ -23,16 +23,19 @@ ## Usage -The library has not been published yet to `crates.io`, and this will be the case -until we reach a stable version. However, one can [specify a git dependency] in -a `Cargo.toml`, like so: +You can import OpenZeppelin Contracts from crates.io by adding the following line to your `Cargo.toml` (We recommend pinning to a specific version): ```toml [dependencies] -openzeppelin-stylus = { git = "https://github.com/OpenZeppelin/rust-contracts-stylus" } +openzeppelin-stylus = "0.1.0-rc" ``` -We recommend pinning to a specific version -- expect rapid iteration. +Optionally,you can specify a git dependency if you want to have the latest changes from the `main` branch: + +```toml +[dependencies] +openzeppelin-stylus = { git = "https://github.com/OpenZeppelin/rust-contracts-stylus" } +``` Once defined as a dependency, use one of our pre-defined implementations by importing them: @@ -62,8 +65,6 @@ For a full example that includes deploying and querying a contract, see the For more information on what this library will include in the future, see our [roadmap]. -[specify a git dependency]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories -[examples]: ./examples [basic]: ./examples/basic [roadmap]: https://github.com/OpenZeppelin/rust-contracts-stylus/milestone/1 From d5ed376f8a1c2f47b4816be30c2c3fc96d5b230a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:25:31 +0200 Subject: [PATCH 06/16] build(deps): bump crate-ci/typos from 1.24.1 to 1.24.6 (#288) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.24.1 to 1.24.6.
Release notes

Sourced from crate-ci/typos's releases.

v1.24.6

[1.24.6] - 2024-09-16

Fixes

  • Respect negation (!) in extend-exclude

v1.24.5

[1.24.5] - 2024-09-04

Features

  • (action) Support windows

v1.24.4

[1.24.4] - 2024-09-03

Fixes

  • Offer a correction for grather

v1.24.3

[1.24.3] - 2024-08-30

Fixes

v1.24.2

[1.24.2] - 2024-08-30

Performance

  • Cap unbounded parsing to avoid worst case performance (hit with test data)
Changelog

Sourced from crate-ci/typos's changelog.

[1.24.6] - 2024-09-16

Fixes

  • Respect negation (!) in extend-exclude

[1.24.5] - 2024-09-04

Features

  • (action) Support windows

[1.24.4] - 2024-09-03

Fixes

  • Offer a correction for grather

[1.24.3] - 2024-08-30

Fixes

[1.24.2] - 2024-08-30

Performance

  • Cap unbounded parsing to avoid worst case performance (hit with test data)
Commits
  • 8e6a428 chore: Release
  • cab7c3c docs: Update changelog
  • c4a6592 Merge pull request #1100 from epage/invert
  • ad3538f refactor(cli): Switch from Overrides to Gitignore
  • d9b55f9 fix(cli): Allow negative expressions in extend-exclude
  • 777cf42 refactor(cli): Be explicit in overrides
  • 0e8148f test(cli): Show inverted extend-exclude behavior
  • 945d407 chore: Release
  • e972e95 docs: Update changelog
  • fcfade4 Merge pull request #1095 from zyf722/actions-windows
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.24.1&new-version=1.24.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Daniel Bigos --- .github/workflows/check.yml | 2 +- docs/modules/ROOT/pages/crypto.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 708a0862..6ac80efd 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -110,4 +110,4 @@ jobs: - name: Checkout Actions Repository uses: actions/checkout@v4 - name: Check spelling of files in the workspace - uses: crate-ci/typos@v1.24.1 + uses: crate-ci/typos@v1.24.6 diff --git a/docs/modules/ROOT/pages/crypto.adoc b/docs/modules/ROOT/pages/crypto.adoc index 456f8518..7754486c 100644 --- a/docs/modules/ROOT/pages/crypto.adoc +++ b/docs/modules/ROOT/pages/crypto.adoc @@ -22,6 +22,6 @@ pub fn verify(&self, proof: Vec, root: B256, leaf: B256) -> bool { } ---- -Note that these functions use `keccak256` as the hashing algorithm, but our library also provides generic counterparts: https://docs.rs/crypto/latest/merkle/struct.Verifier.html#method.verify_with_builder[`verify_with_builer`] and https://docs.rs/crypto/latest/merkle/struct.Verifier.html#method.verify_multi_proof_with_builder[`verify_multi_proof_with_builder`]. +Note that these functions use `keccak256` as the hashing algorithm, but our library also provides generic counterparts: https://docs.rs/crypto/latest/merkle/struct.Verifier.html#method.verify_with_builder[`verify_with_builder`] and https://docs.rs/crypto/latest/merkle/struct.Verifier.html#method.verify_multi_proof_with_builder[`verify_multi_proof_with_builder`]. We also provide an adapter https://docs.rs/crypto/latest/hash/index.html[`hash`] module to use your own hashers in conjunction with them that resembles Rust's standard library's API. From b1eef8057c2e438881cd8687d81963452e868c90 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Sat, 21 Sep 2024 00:32:56 +0200 Subject: [PATCH 07/16] ref: new workspace structure and version management (#280) - [x] Set `motsu` version to `v0.1.0` - [x] Improve version management for the workspace - `contracts`, `lib/crypto`, `examples`, and `benches` use version set for the whole workspace - `motsu`, `motsu-proc`, `e2e`, `e2e-proc` have their own version per crate - [x] Cleanup dependencies for the workspace - [x] Add CI checks for pre-publishing on crates.io - [x] Fix issues with publishing `motsu` to crates.io: ``` cargo publish -p motsu --target wasm32-unknown-unknown --dry-run Updating crates.io index error: all dependencies must have a version specified when publishing. dependency `motsu-proc` does not specify a version Note: The published dependency will use the version from crates.io, the `path` specification will be removed from the dependency declaration. ``` --------- --- .github/workflows/check-publish.yml | 42 ++++++++++++++++++++++++++ Cargo.lock | 20 ++++++------ Cargo.toml | 9 ++++++ benches/Cargo.toml | 6 ++-- contracts/Cargo.toml | 4 +-- examples/access-control/Cargo.toml | 6 ++-- examples/basic/token/Cargo.toml | 4 +-- examples/ecdsa/Cargo.toml | 6 ++-- examples/erc20-permit/Cargo.toml | 6 ++-- examples/erc20/Cargo.toml | 6 ++-- examples/erc721-consecutive/Cargo.toml | 6 ++-- examples/erc721-metadata/Cargo.toml | 6 ++-- examples/erc721/Cargo.toml | 6 ++-- examples/merkle-proofs/Cargo.toml | 4 +-- examples/ownable/Cargo.toml | 4 +-- lib/crypto/Cargo.toml | 2 +- lib/e2e/Cargo.toml | 2 +- lib/motsu-proc/Cargo.toml | 2 +- lib/motsu/Cargo.toml | 2 +- 19 files changed, 97 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/check-publish.yml diff --git a/.github/workflows/check-publish.yml b/.github/workflows/check-publish.yml new file mode 100644 index 00000000..67bbb311 --- /dev/null +++ b/.github/workflows/check-publish.yml @@ -0,0 +1,42 @@ +name: check-publish +# This workflow checks that the libraries can be published on crates.io. +permissions: + contents: read +on: + push: + branches: [ main ] + pull_request: +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true +env: + CARGO_TERM_COLOR: always +jobs: + check-publish: + name: Check publish on crates.io + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: set up rust + uses: dtolnay/rust-toolchain@master + id: toolchain + with: + target: wasm32-unknown-unknown + components: rust-src + toolchain: nightly-2024-01-01 + + - uses: Swatinem/rust-cache@v2 + + - name: check motsu-proc + run: cargo publish -p motsu-proc --dry-run + + - name: check motsu + run: cargo publish -p motsu --dry-run + + - name: check openzeppelin-crypto + run: cargo publish -p openzeppelin-crypto --target wasm32-unknown-unknown --dry-run + + # TODO: https://github.com/OpenZeppelin/rust-contracts-stylus/issues/291 + # - name: check openzeppelin-stylus + # run: cargo publish -p openzeppelin-stylus --target wasm32-unknown-unknown --dry-run diff --git a/Cargo.lock b/Cargo.lock index ebb25bb5..591250ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "access-control-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -794,7 +794,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy-primitives", "mini-alloc", @@ -816,7 +816,7 @@ dependencies = [ [[package]] name = "benches" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -1262,7 +1262,7 @@ dependencies = [ [[package]] name = "cryptography-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -1514,7 +1514,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erc20-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -1529,7 +1529,7 @@ dependencies = [ [[package]] name = "erc20-permit-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -1544,7 +1544,7 @@ dependencies = [ [[package]] name = "erc721-consecutive-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -1561,7 +1561,7 @@ dependencies = [ [[package]] name = "erc721-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -1577,7 +1577,7 @@ dependencies = [ [[package]] name = "erc721-metadata-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy", "alloy-primitives", @@ -2360,7 +2360,7 @@ checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" [[package]] name = "merkle-proofs-example" -version = "0.0.0" +version = "0.1.0-rc" dependencies = [ "alloy-primitives", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index f196fd18..059b99e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ edition = "2021" license = "MIT" keywords = ["arbitrum", "ethereum", "stylus"] repository = "https://github.com/OpenZeppelin/rust-contracts-stylus" +version = "0.1.0-rc" [workspace.lints.rust] missing_docs = "warn" @@ -95,6 +96,14 @@ syn = { version = "2.0.58", features = ["full"] } proc-macro2 = "1.0.79" quote = "1.0.35" +# members +openzeppelin-stylus = { path = "contracts" } +openzeppelin-crypto = { path = "lib/crypto" } +motsu = { path = "lib/motsu"} +motsu-proc = { path = "lib/motsu-proc", version = "0.1.0" } +e2e = { path = "lib/e2e" } +e2e-proc = {path = "lib/e2e-proc"} + [profile.release] codegen-units = 1 panic = "abort" diff --git a/benches/Cargo.toml b/benches/Cargo.toml index 921de2f6..f16effd4 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -4,15 +4,15 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives = { workspace = true, features = ["tiny-keccak"] } alloy.workspace = true tokio.workspace = true eyre.workspace = true koba.workspace = true -e2e = { path = "../lib/e2e" } +e2e.workspace = true serde = "1.0.203" keccak-const = "0.2.0" diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index d7c64340..f079ce0e 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true keywords.workspace = true license.workspace = true repository.workspace = true -version = "0.1.0-rc" +version.workspace = true [dependencies] alloy-primitives.workspace = true @@ -18,7 +18,7 @@ keccak-const.workspace = true [dev-dependencies] alloy-primitives = { workspace = true, features = ["arbitrary"] } -motsu = { path = "../lib/motsu" } +motsu.workspace = true rand.workspace = true [features] diff --git a/examples/access-control/Cargo.toml b/examples/access-control/Cargo.toml index d3fdeef2..cf032181 100644 --- a/examples/access-control/Cargo.toml +++ b/examples/access-control/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true stylus-proc.workspace = true @@ -15,7 +15,7 @@ mini-alloc.workspace = true [dev-dependencies] alloy.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true tokio.workspace = true eyre.workspace = true diff --git a/examples/basic/token/Cargo.toml b/examples/basic/token/Cargo.toml index baee1283..077980f9 100644 --- a/examples/basic/token/Cargo.toml +++ b/examples/basic/token/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true stylus-proc.workspace = true diff --git a/examples/ecdsa/Cargo.toml b/examples/ecdsa/Cargo.toml index 2d5b3a91..7cac7e54 100644 --- a/examples/ecdsa/Cargo.toml +++ b/examples/ecdsa/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true stylus-proc.workspace = true @@ -15,7 +15,7 @@ mini-alloc.workspace = true [dev-dependencies] alloy.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true tokio.workspace = true eyre.workspace = true diff --git a/examples/erc20-permit/Cargo.toml b/examples/erc20-permit/Cargo.toml index 29cc3424..90081954 100644 --- a/examples/erc20-permit/Cargo.toml +++ b/examples/erc20-permit/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives = { workspace = true, features = ["tiny-keccak"] } stylus-sdk.workspace = true stylus-proc.workspace = true @@ -17,7 +17,7 @@ mini-alloc.workspace = true alloy.workspace = true eyre.workspace = true tokio.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true [features] e2e = [] diff --git a/examples/erc20/Cargo.toml b/examples/erc20/Cargo.toml index 18156804..037d3be9 100644 --- a/examples/erc20/Cargo.toml +++ b/examples/erc20/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true stylus-proc.workspace = true @@ -17,7 +17,7 @@ mini-alloc.workspace = true alloy.workspace = true eyre.workspace = true tokio.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true [features] e2e = [] diff --git a/examples/erc721-consecutive/Cargo.toml b/examples/erc721-consecutive/Cargo.toml index 2c6eef27..08b7f5b4 100644 --- a/examples/erc721-consecutive/Cargo.toml +++ b/examples/erc721-consecutive/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true alloy-sol-types.workspace = true stylus-sdk.workspace = true @@ -16,7 +16,7 @@ mini-alloc.workspace = true [dev-dependencies] alloy.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true tokio.workspace = true eyre.workspace = true rand.workspace = true diff --git a/examples/erc721-metadata/Cargo.toml b/examples/erc721-metadata/Cargo.toml index 1bc6050a..62b1f298 100644 --- a/examples/erc721-metadata/Cargo.toml +++ b/examples/erc721-metadata/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true stylus-proc.workspace = true @@ -15,7 +15,7 @@ mini-alloc.workspace = true [dev-dependencies] alloy.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true tokio.workspace = true eyre.workspace = true rand.workspace = true diff --git a/examples/erc721/Cargo.toml b/examples/erc721/Cargo.toml index 6f70bb7f..c11254dc 100644 --- a/examples/erc721/Cargo.toml +++ b/examples/erc721/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true stylus-proc.workspace = true @@ -15,7 +15,7 @@ mini-alloc.workspace = true [dev-dependencies] alloy.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true tokio.workspace = true eyre.workspace = true rand.workspace = true diff --git a/examples/merkle-proofs/Cargo.toml b/examples/merkle-proofs/Cargo.toml index 60931af4..e741ccbe 100644 --- a/examples/merkle-proofs/Cargo.toml +++ b/examples/merkle-proofs/Cargo.toml @@ -4,10 +4,10 @@ edition.workspace = true license.workspace = true repository.workspace = true publish = false -version = "0.0.0" +version.workspace = true [dependencies] -openzeppelin-crypto = { path = "../../lib/crypto" } +openzeppelin-crypto.workspace = true alloy-primitives.workspace = true alloy-sol-types.workspace = true stylus-sdk.workspace = true diff --git a/examples/ownable/Cargo.toml b/examples/ownable/Cargo.toml index 13ebcbe7..6ac97fa3 100644 --- a/examples/ownable/Cargo.toml +++ b/examples/ownable/Cargo.toml @@ -7,7 +7,7 @@ publish = false version = "0.0.0" [dependencies] -openzeppelin-stylus = { path = "../../contracts" } +openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true stylus-proc.workspace = true @@ -15,7 +15,7 @@ mini-alloc.workspace = true [dev-dependencies] alloy.workspace = true -e2e = { path = "../../lib/e2e" } +e2e.workspace = true tokio.workspace = true eyre.workspace = true diff --git a/lib/crypto/Cargo.toml b/lib/crypto/Cargo.toml index cf119fc9..81a44fd8 100644 --- a/lib/crypto/Cargo.toml +++ b/lib/crypto/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true keywords.workspace = true license.workspace = true repository.workspace = true -version = "0.1.0-rc" +version.workspace = true [dependencies] mini-alloc.workspace = true diff --git a/lib/e2e/Cargo.toml b/lib/e2e/Cargo.toml index 6d6cf933..0c48aa14 100644 --- a/lib/e2e/Cargo.toml +++ b/lib/e2e/Cargo.toml @@ -15,7 +15,7 @@ eyre.workspace = true regex.workspace = true once_cell.workspace = true koba.workspace = true -e2e-proc = { path = "../e2e-proc" } +e2e-proc.workspace = true toml = "0.8.13" [lints] diff --git a/lib/motsu-proc/Cargo.toml b/lib/motsu-proc/Cargo.toml index 1e6bbbcf..7b172b60 100644 --- a/lib/motsu-proc/Cargo.toml +++ b/lib/motsu-proc/Cargo.toml @@ -13,7 +13,7 @@ quote.workspace = true syn.workspace = true [dev-dependencies] -motsu = { path = "../motsu" } +motsu.workspace = true alloy-primitives.workspace = true alloy-sol-types.workspace = true stylus-sdk.workspace = true diff --git a/lib/motsu/Cargo.toml b/lib/motsu/Cargo.toml index ed66709e..57f1f19a 100644 --- a/lib/motsu/Cargo.toml +++ b/lib/motsu/Cargo.toml @@ -12,7 +12,7 @@ const-hex.workspace = true once_cell.workspace = true tiny-keccak.workspace = true stylus-sdk.workspace = true -motsu-proc = { path = "../motsu-proc" } +motsu-proc.workspace = true [lints] workspace = true From 8fb27580da9a921949864a7fc86aa9d9d2e915df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20FP?= <105675159+TucksonDev@users.noreply.github.com> Date: Mon, 23 Sep 2024 14:09:21 +0100 Subject: [PATCH 08/16] fix(e2e): deploy contracts without Solidity constructor when not needed (#295) This PR changes the `e2e` testing library to allow deployments of contracts without a constructor., when the constructor file is not present. This is already allowed by [koba](https://github.com/OpenZeppelin/koba/blob/main/src/generator.rs#L27-L30). #### PR Checklist - [x] Tests - [ ] ~Documentation~ (not required) --------- Co-authored-by: Daniel Bigos Co-authored-by: Alisander Qoshqosh --- examples/ecdsa/src/constructor.sol | 6 ------ lib/e2e/src/deploy.rs | 6 +++++- 2 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 examples/ecdsa/src/constructor.sol diff --git a/examples/ecdsa/src/constructor.sol b/examples/ecdsa/src/constructor.sol deleted file mode 100644 index d10ca026..00000000 --- a/examples/ecdsa/src/constructor.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.21; - -contract ECDSAExample { - constructor() {} -} diff --git a/lib/e2e/src/deploy.rs b/lib/e2e/src/deploy.rs index a307472e..e65aef6e 100644 --- a/lib/e2e/src/deploy.rs +++ b/lib/e2e/src/deploy.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use alloy::{rpc::types::TransactionReceipt, sol_types::SolConstructor}; use koba::config::Deploy; @@ -45,11 +47,13 @@ impl Deployer { let pkg = Crate::new()?; let wasm_path = pkg.wasm; let sol_path = pkg.manifest_dir.join("src/constructor.sol"); + let sol = + if Path::new(&sol_path).exists() { Some(sol_path) } else { None }; let config = Deploy { generate_config: koba::config::Generate { wasm: wasm_path.clone(), - sol: Some(sol_path), + sol, args: self.ctr_args, legacy: false, }, From d186818da04bd354db5a02c90671ddd6243ead66 Mon Sep 17 00:00:00 2001 From: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:15:37 +0400 Subject: [PATCH 09/16] chore: update keywords for crates.io (#297) Adds more relevant and different keywords for different crates. --- Cargo.toml | 1 - contracts/Cargo.toml | 4 ++-- lib/crypto/Cargo.toml | 6 +++--- lib/e2e-proc/Cargo.toml | 3 ++- lib/e2e/Cargo.toml | 3 ++- lib/motsu-proc/Cargo.toml | 3 ++- lib/motsu/Cargo.toml | 3 ++- 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 059b99e0..94431294 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,6 @@ resolver = "2" authors = ["OpenZeppelin"] edition = "2021" license = "MIT" -keywords = ["arbitrum", "ethereum", "stylus"] repository = "https://github.com/OpenZeppelin/rust-contracts-stylus" version = "0.1.0-rc" diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index f079ce0e..b6f9d776 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "openzeppelin-stylus" -categories = ["no-std", "wasm"] description = "OpenZeppelin Contracts for Stylus" edition.workspace = true -keywords.workspace = true +categories = ["cryptography::cryptocurrencies", "no-std", "wasm"] +keywords = ["arbitrum", "ethereum", "stylus", "smart-contracts", "standards"] license.workspace = true repository.workspace = true version.workspace = true diff --git a/lib/crypto/Cargo.toml b/lib/crypto/Cargo.toml index 81a44fd8..777aeaca 100644 --- a/lib/crypto/Cargo.toml +++ b/lib/crypto/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "openzeppelin-crypto" -categories = ["cryptography", "algorithms", "no-std", "wasm"] -description = "Cryptography Utilities" +description = "Cryptographic Utilities" edition.workspace = true -keywords.workspace = true +categories = ["cryptography", "algorithms", "no-std", "wasm"] +keywords = ["crypto", "web3", "blockchain", "merkle"] license.workspace = true repository.workspace = true version.workspace = true diff --git a/lib/e2e-proc/Cargo.toml b/lib/e2e-proc/Cargo.toml index c89b39f3..aaa76ad1 100644 --- a/lib/e2e-proc/Cargo.toml +++ b/lib/e2e-proc/Cargo.toml @@ -2,10 +2,11 @@ name = "e2e-proc" description = "End-to-end Testing Procedural Macros" version = "0.1.0" +categories = ["development-tools::testing", "cryptography::cryptocurrencies"] +keywords = ["arbitrum", "ethereum", "stylus", "integration-testing", "tests"] authors.workspace = true edition.workspace = true license.workspace = true -keywords.workspace = true repository.workspace = true [dependencies] diff --git a/lib/e2e/Cargo.toml b/lib/e2e/Cargo.toml index 0c48aa14..84a9c6df 100644 --- a/lib/e2e/Cargo.toml +++ b/lib/e2e/Cargo.toml @@ -2,10 +2,11 @@ name = "e2e" description = "End-to-end Testing for Stylus" version = "0.1.0" +categories = ["development-tools::testing", "cryptography::cryptocurrencies"] +keywords = ["arbitrum", "ethereum", "stylus", "integration-testing", "tests"] authors.workspace = true edition.workspace = true license.workspace = true -keywords.workspace = true repository.workspace = true [dependencies] diff --git a/lib/motsu-proc/Cargo.toml b/lib/motsu-proc/Cargo.toml index 7b172b60..4d009022 100644 --- a/lib/motsu-proc/Cargo.toml +++ b/lib/motsu-proc/Cargo.toml @@ -2,7 +2,8 @@ name = "motsu-proc" description = "Mostu's Procedural Macros" edition.workspace = true -keywords.workspace = true +categories = ["development-tools::testing", "cryptography::cryptocurrencies"] +keywords = ["arbitrum", "ethereum", "stylus", "unit-tests", "tests"] license.workspace = true repository.workspace = true version = "0.1.0" diff --git a/lib/motsu/Cargo.toml b/lib/motsu/Cargo.toml index 57f1f19a..5f3e5958 100644 --- a/lib/motsu/Cargo.toml +++ b/lib/motsu/Cargo.toml @@ -2,7 +2,8 @@ name = "motsu" description = "Unit Testing for Stylus" edition.workspace = true -keywords.workspace = true +categories = ["development-tools::testing", "cryptography::cryptocurrencies"] +keywords = ["arbitrum", "ethereum", "stylus", "unit-tests", "tests"] license.workspace = true repository.workspace = true version = "0.1.0" From 9b615264f94a8b3320294d6ac6d98a92a8389047 Mon Sep 17 00:00:00 2001 From: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:32:12 +0400 Subject: [PATCH 10/16] tests: increase code coverage at consecutive (#293) Adds missing tests to erc721 consecutive mostly associated with erc721 standard's operations. --- .../token/erc721/extensions/consecutive.rs | 337 +++++++++++++++++- contracts/src/token/erc721/mod.rs | 14 +- 2 files changed, 340 insertions(+), 11 deletions(-) diff --git a/contracts/src/token/erc721/extensions/consecutive.rs b/contracts/src/token/erc721/extensions/consecutive.rs index 35a88440..d5f173a2 100644 --- a/contracts/src/token/erc721/extensions/consecutive.rs +++ b/contracts/src/token/erc721/extensions/consecutive.rs @@ -801,13 +801,16 @@ mod tests { ERC721ExceededMaxBatchMint, Erc721Consecutive, Error, }, tests::random_token_id, - ERC721InvalidReceiver, ERC721NonexistentToken, IErc721, + ERC721IncorrectOwner, ERC721InvalidApprover, + ERC721InvalidReceiver, ERC721InvalidSender, + ERC721NonexistentToken, IErc721, }, }, utils::structs::checkpoints::U96, }; const BOB: Address = address!("F4EaCDAbEf3c8f1EdE91b6f2A6840bc2E4DD3526"); + const DAVE: Address = address!("0BB78F7e7132d1651B4Fd884B7624394e92156F1"); fn init( contract: &mut Erc721Consecutive, @@ -858,6 +861,43 @@ mod tests { assert_eq!(balance2, balance1 + uint!(1_U256)); } + #[motsu::test] + fn error_when_minting_token_id_twice(contract: Erc721Consecutive) { + let alice = msg::sender(); + let token_id = random_token_id(); + contract + ._mint(alice, token_id) + .expect("should mint the token a first time"); + let err = contract + ._mint(alice, token_id) + .expect_err("should not mint a token with `token_id` twice"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::InvalidSender(ERC721InvalidSender { + sender: Address::ZERO + })) + )); + } + + #[motsu::test] + fn error_when_minting_token_invalid_receiver(contract: Erc721Consecutive) { + let invalid_receiver = Address::ZERO; + + let token_id = random_token_id(); + + let err = contract + ._mint(invalid_receiver, token_id) + .expect_err("should not mint a token for invalid receiver"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::InvalidReceiver(ERC721InvalidReceiver { + receiver + })) if receiver == invalid_receiver + )); + } + #[motsu::test] fn error_when_to_is_zero(contract: Erc721Consecutive) { let err = contract @@ -994,5 +1034,300 @@ mod tests { Error::Erc721(erc721::Error::NonexistentToken(ERC721NonexistentToken { token_id })) if token_id == U256::from(non_consecutive_token_id) )); + + // After being burnt the token should not be burnt again. + let non_existent_token = non_consecutive_token_id; + let err = contract + ._burn(non_existent_token) + .expect_err("should return Error::NonexistentToken"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::NonexistentToken (ERC721NonexistentToken{ + token_id: t_id + })) if t_id == non_existent_token + )); + } + + #[motsu::test] + fn safe_transfer_from(contract: Erc721Consecutive) { + let alice = msg::sender(); + let token_id = random_token_id(); + contract._mint(alice, token_id).expect("should mint a token to Alice"); + + contract + .safe_transfer_from(alice, BOB, token_id) + .expect("should transfer a token from Alice to Bob"); + + let owner = contract + .owner_of(token_id) + .expect("should return the owner of the token"); + + assert_eq!(owner, BOB); + } + + #[motsu::test] + fn safe_transfers_from_approved_token(contract: Erc721Consecutive) { + let alice = msg::sender(); + let token_id = random_token_id(); + contract._mint(BOB, token_id).expect("should mint token to Bob"); + contract.erc721._token_approvals.setter(token_id).set(alice); + contract + .safe_transfer_from(BOB, alice, token_id) + .expect("should transfer Bob's token to Alice"); + let owner = contract + .owner_of(token_id) + .expect("should return the owner of the token"); + assert_eq!(owner, alice); + } + + #[motsu::test] + fn error_when_safe_transfer_from_incorrect_owner( + contract: Erc721Consecutive, + ) { + let alice = msg::sender(); + let token_id = random_token_id(); + + contract._mint(alice, token_id).expect("should mint a token to Alice"); + + let err = contract + .safe_transfer_from(DAVE, BOB, token_id) + .expect_err("should not transfer from incorrect owner"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::IncorrectOwner(ERC721IncorrectOwner { + sender, + token_id: t_id, + owner + })) if sender == DAVE && t_id == token_id && owner == alice + )); + } + + #[motsu::test] + fn error_when_internal_safe_transfer_nonexistent_token( + contract: Erc721Consecutive, + ) { + let alice = msg::sender(); + let token_id = random_token_id(); + let err = contract + ._safe_transfer(alice, BOB, token_id, vec![0, 1, 2, 3].into()) + .expect_err("should not transfer a non-existent token"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::NonexistentToken(ERC721NonexistentToken { + token_id: t_id, + })) if t_id == token_id + )); + } + + #[motsu::test] + fn error_when_safe_transfer_to_invalid_receiver( + contract: Erc721Consecutive, + ) { + let alice = msg::sender(); + let token_id = random_token_id(); + let invalid_receiver = Address::ZERO; + + contract._mint(alice, token_id).expect("should mint a token to Alice"); + + let err = contract + .safe_transfer_from(alice, invalid_receiver, token_id) + .expect_err("should not transfer the token to invalid receiver"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::InvalidReceiver(ERC721InvalidReceiver { + receiver + })) if receiver == invalid_receiver + )); + + let owner = contract + .owner_of(token_id) + .expect("should return the owner of the token"); + assert_eq!(alice, owner); + } + + #[motsu::test] + fn safe_transfers_from_with_data(contract: Erc721Consecutive) { + let alice = msg::sender(); + let token_id = random_token_id(); + contract._mint(alice, token_id).expect("should mint a token to Alice"); + + contract + .safe_transfer_from_with_data( + alice, + BOB, + token_id, + vec![0, 1, 2, 3].into(), + ) + .expect("should transfer a token from Alice to Bob"); + + let owner = contract + .owner_of(token_id) + .expect("should return the owner of the token"); + + assert_eq!(owner, BOB); + } + + #[motsu::test] + fn error_when_internal_safe_transfer_to_invalid_receiver( + contract: Erc721Consecutive, + ) { + let alice = msg::sender(); + let token_id = random_token_id(); + let invalid_receiver = Address::ZERO; + + contract._mint(alice, token_id).expect("should mint a token to Alice"); + + let err = contract + ._safe_transfer( + alice, + invalid_receiver, + token_id, + vec![0, 1, 2, 3].into(), + ) + .expect_err("should not transfer the token to invalid receiver"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::InvalidReceiver(ERC721InvalidReceiver { + receiver + })) if receiver == invalid_receiver + )); + + let owner = contract + .owner_of(token_id) + .expect("should return the owner of the token"); + assert_eq!(alice, owner); + } + + #[motsu::test] + fn error_when_internal_safe_transfer_from_incorrect_owner( + contract: Erc721Consecutive, + ) { + let alice = msg::sender(); + let token_id = random_token_id(); + + contract._mint(alice, token_id).expect("should mint a token to Alice"); + + let err = contract + ._safe_transfer(DAVE, BOB, token_id, vec![0, 1, 2, 3].into()) + .expect_err("should not transfer the token from incorrect owner"); + assert!(matches!( + err, + Error::Erc721(erc721::Error::IncorrectOwner(ERC721IncorrectOwner { + sender, + token_id: t_id, + owner + })) if sender == DAVE && t_id == token_id && owner == alice + )); + } + + #[motsu::test] + fn safe_mints(contract: Erc721Consecutive) { + let alice = msg::sender(); + let token_id = random_token_id(); + + let initial_balance = contract + .balance_of(alice) + .expect("should return the balance of Alice"); + + contract + ._safe_mint(alice, token_id, vec![0, 1, 2, 3].into()) + .expect("should mint a token for Alice"); + + let owner = contract + .owner_of(token_id) + .expect("should return the owner of the token"); + assert_eq!(owner, alice); + + let balance = contract + .balance_of(alice) + .expect("should return the balance of Alice"); + + assert_eq!(initial_balance + uint!(1_U256), balance); + } + + #[motsu::test] + fn approves(contract: Erc721Consecutive) { + let alice = msg::sender(); + let token_id = random_token_id(); + contract._mint(alice, token_id).expect("should mint a token"); + contract + .approve(BOB, token_id) + .expect("should approve Bob for operations on token"); + assert_eq!(contract.erc721._token_approvals.get(token_id), BOB); + } + + #[motsu::test] + fn error_when_approve_for_nonexistent_token(contract: Erc721Consecutive) { + let token_id = random_token_id(); + let err = contract + .approve(BOB, token_id) + .expect_err("should not approve for a non-existent token"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::NonexistentToken(ERC721NonexistentToken { + token_id: t_id + })) if token_id == t_id + )); + } + + #[motsu::test] + fn error_when_approve_by_invalid_approver(contract: Erc721Consecutive) { + let token_id = random_token_id(); + contract._mint(BOB, token_id).expect("should mint a token"); + + let err = contract + .approve(DAVE, token_id) + .expect_err("should not approve when invalid approver"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::InvalidApprover(ERC721InvalidApprover { + approver + })) if approver == msg::sender() + )); + } + + #[motsu::test] + fn approval_for_all(contract: Erc721Consecutive) { + let alice = msg::sender(); + contract + .erc721 + ._operator_approvals + .setter(alice) + .setter(BOB) + .set(false); + + contract + .set_approval_for_all(BOB, true) + .expect("should approve Bob for operations on all Alice's tokens"); + assert_eq!(contract.is_approved_for_all(alice, BOB), true); + + contract.set_approval_for_all(BOB, false).expect( + "should disapprove Bob for operations on all Alice's tokens", + ); + assert_eq!(contract.is_approved_for_all(alice, BOB), false); + } + + #[motsu::test] + fn error_when_get_approved_of_nonexistent_token( + contract: Erc721Consecutive, + ) { + let token_id = random_token_id(); + let err = contract + .get_approved(token_id) + .expect_err("should not return approved for a non-existent token"); + + assert!(matches!( + err, + Error::Erc721(erc721::Error::NonexistentToken(ERC721NonexistentToken { + token_id: t_id + })) if token_id == t_id + )); } } diff --git a/contracts/src/token/erc721/mod.rs b/contracts/src/token/erc721/mod.rs index 119422f1..9d527695 100644 --- a/contracts/src/token/erc721/mod.rs +++ b/contracts/src/token/erc721/mod.rs @@ -1511,9 +1511,7 @@ mod tests { } #[motsu::test] - fn error_when_safe_transfer_from_transfers_to_invalid_receiver( - contract: Erc721, - ) { + fn error_when_safe_transfer_to_invalid_receiver(contract: Erc721) { let alice = msg::sender(); let token_id = random_token_id(); let invalid_receiver = Address::ZERO; @@ -2306,9 +2304,7 @@ mod tests { } #[motsu::test] - fn error_when_safe_transfer_internal_ransfers_to_invalid_receiver( - contract: Erc721, - ) { + fn error_when_internal_safe_transfer_to_invalid_receiver(contract: Erc721) { let alice = msg::sender(); let token_id = random_token_id(); let invalid_receiver = Address::ZERO; @@ -2338,7 +2334,7 @@ mod tests { } #[motsu::test] - fn error_when_safe_transfer_internal_transfers_from_incorrect_owner( + fn error_when_internal_safe_transfer_from_incorrect_owner( contract: Erc721, ) { let alice = msg::sender(); @@ -2366,9 +2362,7 @@ mod tests { } #[motsu::test] - fn error_when_safe_transfer_internal_transfers_nonexistent_token( - contract: Erc721, - ) { + fn error_when_internal_safe_transfer_nonexistent_token(contract: Erc721) { let alice = msg::sender(); let token_id = random_token_id(); let err = contract From 61000df2759b42c1fa72a05d3baf684f49d35da2 Mon Sep 17 00:00:00 2001 From: alexfertel Date: Fri, 27 Sep 2024 10:48:24 +0200 Subject: [PATCH 11/16] feat: cache contracts before benching (#254) Use the `cargo stylus cache` to cache contracts in the `CacheManager` before running benches. --------- Co-authored-by: Alisander Qoshqosh Co-authored-by: Gustavo Gonzalez --- .github/workflows/gas-bench.yml | 3 + Cargo.lock | 1 + Cargo.toml | 1 + benches/Cargo.toml | 1 + benches/src/access_control.rs | 38 +++++++-- benches/src/erc20.rs | 40 +++++++-- benches/src/erc721.rs | 40 +++++++-- benches/src/lib.rs | 66 +++++++++++---- benches/src/main.rs | 25 +++--- benches/src/merkle_proofs.rs | 39 +++++++-- benches/src/report.rs | 145 ++++++++++++++++++++++++++------ lib/e2e/src/account.rs | 6 +- lib/e2e/src/system.rs | 4 +- scripts/bench.sh | 11 ++- scripts/nitro-testnode.sh | 13 ++- 15 files changed, 339 insertions(+), 94 deletions(-) diff --git a/.github/workflows/gas-bench.yml b/.github/workflows/gas-bench.yml index 67a6f127..a14bf25c 100644 --- a/.github/workflows/gas-bench.yml +++ b/.github/workflows/gas-bench.yml @@ -31,6 +31,9 @@ jobs: with: key: "gas-bench" + - name: install cargo-stylus + run: cargo install cargo-stylus@0.5.1 + - name: install solc run: | curl -LO https://github.com/ethereum/solidity/releases/download/v0.8.24/solc-static-linux diff --git a/Cargo.lock b/Cargo.lock index 591250ee..a756c697 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -822,6 +822,7 @@ dependencies = [ "alloy-primitives", "e2e", "eyre", + "futures", "keccak-const", "koba", "openzeppelin-stylus", diff --git a/Cargo.toml b/Cargo.toml index 94431294..ed00cd54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,6 +89,7 @@ rand = "0.8.5" regex = "1.10.4" tiny-keccak = { version = "2.0.2", features = ["keccak"] } tokio = { version = "1.12.0", features = ["full"] } +futures = "0.3.30" # procedural macros syn = { version = "2.0.58", features = ["full"] } diff --git a/benches/Cargo.toml b/benches/Cargo.toml index f16effd4..5cb17d8e 100644 --- a/benches/Cargo.toml +++ b/benches/Cargo.toml @@ -11,6 +11,7 @@ openzeppelin-stylus.workspace = true alloy-primitives = { workspace = true, features = ["tiny-keccak"] } alloy.workspace = true tokio.workspace = true +futures.workspace = true eyre.workspace = true koba.workspace = true e2e.workspace = true diff --git a/benches/src/access_control.rs b/benches/src/access_control.rs index 7c9b7978..12ccfaa8 100644 --- a/benches/src/access_control.rs +++ b/benches/src/access_control.rs @@ -8,7 +8,10 @@ use alloy::{ }; use e2e::{receipt, Account}; -use crate::report::Report; +use crate::{ + report::{ContractReport, FunctionReport}, + CacheOpt, +}; sol!( #[sol(rpc)] @@ -33,7 +36,22 @@ const ROLE: [u8; 32] = const NEW_ADMIN_ROLE: [u8; 32] = hex!("879ce0d4bfd332649ca3552efe772a38d64a315eb70ab69689fd309c735946b5"); -pub async fn bench() -> eyre::Result { +pub async fn bench() -> eyre::Result { + let receipts = run_with(CacheOpt::None).await?; + let report = receipts + .into_iter() + .try_fold(ContractReport::new("AccessControl"), ContractReport::add)?; + + let cached_receipts = run_with(CacheOpt::Bid(0)).await?; + let report = cached_receipts + .into_iter() + .try_fold(report, ContractReport::add_cached)?; + + Ok(report) +} +pub async fn run_with( + cache_opt: CacheOpt, +) -> eyre::Result> { let alice = Account::new().await?; let alice_addr = alice.address(); let alice_wallet = ProviderBuilder::new() @@ -50,7 +68,8 @@ pub async fn bench() -> eyre::Result { .wallet(EthereumWallet::from(bob.signer.clone())) .on_http(bob.url().parse()?); - let contract_addr = deploy(&alice).await; + let contract_addr = deploy(&alice, cache_opt).await?; + let contract = AccessControl::new(contract_addr, &alice_wallet); let contract_bob = AccessControl::new(contract_addr, &bob_wallet); @@ -66,14 +85,17 @@ pub async fn bench() -> eyre::Result { (setRoleAdminCall::SIGNATURE, receipt!(contract.setRoleAdmin(ROLE.into(), NEW_ADMIN_ROLE.into()))?), ]; - let report = receipts + receipts .into_iter() - .try_fold(Report::new("AccessControl"), Report::add)?; - Ok(report) + .map(FunctionReport::new) + .collect::>>() } -async fn deploy(account: &Account) -> Address { +async fn deploy( + account: &Account, + cache_opt: CacheOpt, +) -> eyre::Result
{ let args = AccessControl::constructorCall {}; let args = alloy::hex::encode(args.abi_encode()); - crate::deploy(account, "access-control", Some(args)).await + crate::deploy(account, "access-control", Some(args), cache_opt).await } diff --git a/benches/src/erc20.rs b/benches/src/erc20.rs index 22f2aff0..bcf63435 100644 --- a/benches/src/erc20.rs +++ b/benches/src/erc20.rs @@ -9,7 +9,10 @@ use alloy::{ use alloy_primitives::U256; use e2e::{receipt, Account}; -use crate::report::Report; +use crate::{ + report::{ContractReport, FunctionReport}, + CacheOpt, +}; sol!( #[sol(rpc)] @@ -39,7 +42,23 @@ const TOKEN_NAME: &str = "Test Token"; const TOKEN_SYMBOL: &str = "TTK"; const CAP: U256 = uint!(1_000_000_U256); -pub async fn bench() -> eyre::Result { +pub async fn bench() -> eyre::Result { + let reports = run_with(CacheOpt::None).await?; + let report = reports + .into_iter() + .try_fold(ContractReport::new("Erc20"), ContractReport::add)?; + + let cached_reports = run_with(CacheOpt::Bid(0)).await?; + let report = cached_reports + .into_iter() + .try_fold(report, ContractReport::add_cached)?; + + Ok(report) +} + +pub async fn run_with( + cache_opt: CacheOpt, +) -> eyre::Result> { let alice = Account::new().await?; let alice_addr = alice.address(); let alice_wallet = ProviderBuilder::new() @@ -56,7 +75,8 @@ pub async fn bench() -> eyre::Result { .wallet(EthereumWallet::from(bob.signer.clone())) .on_http(bob.url().parse()?); - let contract_addr = deploy(&alice).await; + let contract_addr = deploy(&alice, cache_opt).await?; + let contract = Erc20::new(contract_addr, &alice_wallet); let contract_bob = Erc20::new(contract_addr, &bob_wallet); @@ -79,17 +99,21 @@ pub async fn bench() -> eyre::Result { (transferFromCall::SIGNATURE, receipt!(contract_bob.transferFrom(alice_addr, bob_addr, uint!(4_U256)))?), ]; - let report = - receipts.into_iter().try_fold(Report::new("Erc20"), Report::add)?; - Ok(report) + receipts + .into_iter() + .map(FunctionReport::new) + .collect::>>() } -async fn deploy(account: &Account) -> Address { +async fn deploy( + account: &Account, + cache_opt: CacheOpt, +) -> eyre::Result
{ let args = Erc20Example::constructorCall { name_: TOKEN_NAME.to_owned(), symbol_: TOKEN_SYMBOL.to_owned(), cap_: CAP, }; let args = alloy::hex::encode(args.abi_encode()); - crate::deploy(account, "erc20", Some(args)).await + crate::deploy(account, "erc20", Some(args), cache_opt).await } diff --git a/benches/src/erc721.rs b/benches/src/erc721.rs index b5dc4bb2..b00729a1 100644 --- a/benches/src/erc721.rs +++ b/benches/src/erc721.rs @@ -8,7 +8,10 @@ use alloy::{ }; use e2e::{receipt, Account}; -use crate::report::Report; +use crate::{ + report::{ContractReport, FunctionReport}, + CacheOpt, +}; sol!( #[sol(rpc)] @@ -29,7 +32,23 @@ sol!( sol!("../examples/erc721/src/constructor.sol"); -pub async fn bench() -> eyre::Result { +pub async fn bench() -> eyre::Result { + let reports = run_with(CacheOpt::None).await?; + let report = reports + .into_iter() + .try_fold(ContractReport::new("Erc721"), ContractReport::add)?; + + let cached_reports = run_with(CacheOpt::Bid(0)).await?; + let report = cached_reports + .into_iter() + .try_fold(report, ContractReport::add_cached)?; + + Ok(report) +} + +pub async fn run_with( + cache_opt: CacheOpt, +) -> eyre::Result> { let alice = Account::new().await?; let alice_addr = alice.address(); let alice_wallet = ProviderBuilder::new() @@ -41,7 +60,8 @@ pub async fn bench() -> eyre::Result { let bob = Account::new().await?; let bob_addr = bob.address(); - let contract_addr = deploy(&alice).await; + let contract_addr = deploy(&alice, cache_opt).await?; + let contract = Erc721::new(contract_addr, &alice_wallet); let token_1 = uint!(1_U256); @@ -70,13 +90,17 @@ pub async fn bench() -> eyre::Result { (burnCall::SIGNATURE, receipt!(contract.burn(token_1))?), ]; - let report = - receipts.into_iter().try_fold(Report::new("Erc721"), Report::add)?; - Ok(report) + receipts + .into_iter() + .map(FunctionReport::new) + .collect::>>() } -async fn deploy(account: &Account) -> Address { +async fn deploy( + account: &Account, + cache_opt: CacheOpt, +) -> eyre::Result
{ let args = Erc721Example::constructorCall {}; let args = alloy::hex::encode(args.abi_encode()); - crate::deploy(account, "erc721", Some(args)).await + crate::deploy(account, "erc721", Some(args), cache_opt).await } diff --git a/benches/src/lib.rs b/benches/src/lib.rs index 85a37ca0..c884bcdb 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -1,3 +1,5 @@ +use std::process::Command; + use alloy::{ primitives::Address, rpc::types::{ @@ -7,6 +9,7 @@ use alloy::{ }; use alloy_primitives::U128; use e2e::{Account, ReceiptExt}; +use eyre::WrapErr; use koba::config::{Deploy, Generate, PrivateKey}; use serde::Deserialize; @@ -16,8 +19,6 @@ pub mod erc721; pub mod merkle_proofs; pub mod report; -const RPC_URL: &str = "http://localhost:8547"; - #[derive(Debug, Deserialize)] struct ArbOtherFields { #[serde(rename = "gasUsedForL1")] @@ -27,23 +28,24 @@ struct ArbOtherFields { l1_block_number: String, } +/// Cache options for the contract. +/// `Bid(0)` will likely cache the contract on the nitro test node. +pub enum CacheOpt { + None, + Bid(u32), +} + type ArbTxReceipt = WithOtherFields>>; -fn get_l2_gas_used(receipt: &ArbTxReceipt) -> eyre::Result { - let l2_gas = receipt.gas_used; - let arb_fields: ArbOtherFields = receipt.other.deserialize_as()?; - let l1_gas = arb_fields.gas_used_for_l1.to::(); - Ok(l2_gas - l1_gas) -} - async fn deploy( account: &Account, contract_name: &str, args: Option, -) -> Address { + cache_opt: CacheOpt, +) -> eyre::Result
{ let manifest_dir = - std::env::current_dir().expect("should get current dir from env"); + std::env::current_dir().context("should get current dir from env")?; let wasm_path = manifest_dir .join("target") @@ -53,7 +55,7 @@ async fn deploy( let sol_path = args.as_ref().map(|_| { manifest_dir .join("examples") - .join(format!("{}", contract_name)) + .join(contract_name) .join("src") .join("constructor.sol") }); @@ -72,14 +74,46 @@ async fn deploy( keystore_path: None, keystore_password_path: None, }, - endpoint: RPC_URL.to_owned(), + endpoint: env("RPC_URL")?, deploy_only: false, quiet: true, }; - koba::deploy(&config) + let address = koba::deploy(&config) .await .expect("should deploy contract") - .address() - .expect("should return contract address") + .address()?; + + if let CacheOpt::Bid(bid) = cache_opt { + cache_contract(account, address, bid)?; + } + + Ok(address) +} + +/// Try to cache a contract on the stylus network. +/// Already cached contracts won't be cached, and this function will not return +/// an error. +/// Output will be forwarded to the child process. +fn cache_contract( + account: &Account, + contract_addr: Address, + bid: u32, +) -> eyre::Result<()> { + // We don't need a status code. + // Since it is not zero when the contract is already cached. + let _ = Command::new("cargo") + .args(["stylus", "cache", "bid"]) + .args(["-e", &env("RPC_URL")?]) + .args(["--private-key", &format!("0x{}", account.pk())]) + .arg(contract_addr.to_string()) + .arg(bid.to_string()) + .status() + .context("failed to execute `cargo stylus cache bid` command")?; + Ok(()) +} + +/// Load the `name` environment variable. +fn env(name: &str) -> eyre::Result { + std::env::var(name).wrap_err(format!("failed to load {name}")) } diff --git a/benches/src/main.rs b/benches/src/main.rs index cd4e0e38..52278d77 100644 --- a/benches/src/main.rs +++ b/benches/src/main.rs @@ -1,18 +1,21 @@ -use benches::{access_control, erc20, erc721, merkle_proofs, report::Reports}; +use benches::{ + access_control, erc20, erc721, merkle_proofs, report::BenchmarkReport, +}; +use futures::FutureExt; #[tokio::main] async fn main() -> eyre::Result<()> { - let reports = tokio::join!( - access_control::bench(), - erc20::bench(), - erc721::bench(), - merkle_proofs::bench() - ); - - let reports = [reports.0?, reports.1?, reports.2?, reports.3?]; - let report = - reports.into_iter().fold(Reports::default(), Reports::merge_with); + let report = futures::future::try_join_all([ + access_control::bench().boxed(), + erc20::bench().boxed(), + erc721::bench().boxed(), + merkle_proofs::bench().boxed(), + ]) + .await? + .into_iter() + .fold(BenchmarkReport::default(), BenchmarkReport::merge_with); + println!(); println!("{report}"); Ok(()) diff --git a/benches/src/merkle_proofs.rs b/benches/src/merkle_proofs.rs index 92a7d55e..fd986520 100644 --- a/benches/src/merkle_proofs.rs +++ b/benches/src/merkle_proofs.rs @@ -8,7 +8,10 @@ use alloy::{ }; use e2e::{receipt, Account}; -use crate::report::Report; +use crate::{ + report::{ContractReport, FunctionReport}, + CacheOpt, +}; sol!( #[sol(rpc)] @@ -57,7 +60,23 @@ const PROOF: [[u8; 32]; 16] = bytes_array! { "fd47b6c292f51911e8dfdc3e4f8bd127773b17f25b7a554beaa8741e99c41208", }; -pub async fn bench() -> eyre::Result { +pub async fn bench() -> eyre::Result { + let reports = run_with(CacheOpt::None).await?; + let report = reports + .into_iter() + .try_fold(ContractReport::new("MerkleProofs"), ContractReport::add)?; + + let cached_reports = run_with(CacheOpt::Bid(0)).await?; + let report = cached_reports + .into_iter() + .try_fold(report, ContractReport::add_cached)?; + + Ok(report) +} + +pub async fn run_with( + cache_opt: CacheOpt, +) -> eyre::Result> { let alice = Account::new().await?; let alice_wallet = ProviderBuilder::new() .network::() @@ -65,7 +84,8 @@ pub async fn bench() -> eyre::Result { .wallet(EthereumWallet::from(alice.signer.clone())) .on_http(alice.url().parse()?); - let contract_addr = deploy(&alice).await; + let contract_addr = deploy(&alice, cache_opt).await?; + let contract = Verifier::new(contract_addr, &alice_wallet); let proof = PROOF.map(|h| h.into()).to_vec(); @@ -75,12 +95,15 @@ pub async fn bench() -> eyre::Result { receipt!(contract.verify(proof, ROOT.into(), LEAF.into()))?, )]; - let report = receipts + receipts .into_iter() - .try_fold(Report::new("MerkleProofs"), Report::add)?; - Ok(report) + .map(FunctionReport::new) + .collect::>>() } -async fn deploy(account: &Account) -> Address { - crate::deploy(account, "merkle-proofs", None).await +async fn deploy( + account: &Account, + cache_opt: CacheOpt, +) -> eyre::Result
{ + crate::deploy(account, "merkle-proofs", None, cache_opt).await } diff --git a/benches/src/report.rs b/benches/src/report.rs index 3a1184b2..49b5fe70 100644 --- a/benches/src/report.rs +++ b/benches/src/report.rs @@ -1,64 +1,157 @@ -use std::fmt::Display; +use std::{collections::HashMap, fmt::Display}; -use crate::{get_l2_gas_used, ArbTxReceipt}; +use crate::{ArbOtherFields, ArbTxReceipt}; const SEPARATOR: &str = "::"; #[derive(Debug)] -pub struct Report { +pub struct FunctionReport { + sig: String, + gas: u128, +} + +impl FunctionReport { + pub(crate) fn new(receipt: (&str, ArbTxReceipt)) -> eyre::Result { + Ok(FunctionReport { + sig: receipt.0.to_owned(), + gas: get_l2_gas_used(&receipt.1)?, + }) + } +} + +#[derive(Debug)] +pub struct ContractReport { contract: String, - fns: Vec<(String, u128)>, + functions: Vec, + functions_cached: Vec, } -impl Report { +impl ContractReport { pub fn new(contract: &str) -> Self { - Report { contract: contract.to_owned(), fns: vec![] } + ContractReport { + contract: contract.to_owned(), + functions: vec![], + functions_cached: vec![], + } + } + + pub fn add(mut self, fn_report: FunctionReport) -> eyre::Result { + self.functions.push(fn_report); + Ok(self) } - pub fn add(mut self, receipt: (&str, ArbTxReceipt)) -> eyre::Result { - let gas = get_l2_gas_used(&receipt.1)?; - self.fns.push((receipt.0.to_owned(), gas)); + pub fn add_cached( + mut self, + fn_report: FunctionReport, + ) -> eyre::Result { + self.functions_cached.push(fn_report); Ok(self) } - fn get_longest_signature(&self) -> usize { + fn signature_max_len(&self) -> usize { let prefix_len = self.contract.len() + SEPARATOR.len(); - self.fns + self.functions + .iter() + .map(|FunctionReport { sig: name, .. }| prefix_len + name.len()) + .max() + .unwrap_or_default() + } + + fn gas_max_len(&self) -> usize { + self.functions + .iter() + .map(|FunctionReport { gas, .. }| gas.to_string().len()) + .max() + .unwrap_or_default() + } + + fn gas_cached_max_len(&self) -> usize { + self.functions_cached .iter() - .map(|(sig, _)| prefix_len + sig.len()) + .map(|FunctionReport { gas, .. }| gas.to_string().len()) .max() .unwrap_or_default() } } #[derive(Debug, Default)] -pub struct Reports(Vec); +pub struct BenchmarkReport(Vec); -impl Reports { - pub fn merge_with(mut self, report: Report) -> Self { +impl BenchmarkReport { + pub fn merge_with(mut self, report: ContractReport) -> Self { self.0.push(report); self } -} -impl Display for Reports { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let reports = &self.0; - let width = reports + pub fn column_width( + &self, + column_value: impl FnMut(&ContractReport) -> usize, + header: &str, + ) -> usize { + self.0 .iter() - .map(Report::get_longest_signature) + .map(column_value) + .chain(std::iter::once(header.len())) .max() - .unwrap_or_default(); + .unwrap_or_default() + } +} + +impl Display for BenchmarkReport { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + const HEADER_SIG: &str = "Contract::function"; + const HEADER_GAS_CACHED: &str = "Cached"; + const HEADER_GAS: &str = "Not Cached"; + + // Calculating the width of table columns. + let width1 = + self.column_width(ContractReport::signature_max_len, HEADER_SIG); + let width2 = self.column_width( + ContractReport::gas_cached_max_len, + HEADER_GAS_CACHED, + ); + let width3 = self.column_width(ContractReport::gas_max_len, HEADER_GAS); - for report in reports { + // Print headers for the table columns. + writeln!( + f, + "| {HEADER_SIG:width2$} | {HEADER_GAS:>width3$} |" + )?; + writeln!( + f, + "| {:->width1$} | {:->width2$} | {:->width3$} |", + "", "", "" + )?; + + // Merging a non-cached gas report with a cached one. + for report in &self.0 { let prefix = format!("{}{SEPARATOR}", report.contract); + let gas: HashMap<_, _> = report + .functions + .iter() + .map(|func| (&*func.sig, func.gas)) + .collect(); + + for report_cached in &report.functions_cached { + let sig = &*report_cached.sig; + let gas_cached = &report_cached.gas; + let gas = gas[sig]; - for (sig, gas) in &report.fns { - let signature = format!("{prefix}{sig}"); - writeln!(f, "{signature:10}")?; + let full_sig = format!("{prefix}{sig}"); + writeln!( + f, + "| {full_sig:width2$} | {gas:>width3$} |" + )?; } } Ok(()) } } + +fn get_l2_gas_used(receipt: &ArbTxReceipt) -> eyre::Result { + let l2_gas = receipt.gas_used; + let arb_fields: ArbOtherFields = receipt.other.deserialize_as()?; + let l1_gas = arb_fields.gas_used_for_l1.to::(); + Ok(l2_gas - l1_gas) +} diff --git a/lib/e2e/src/account.rs b/lib/e2e/src/account.rs index 5e0e9559..83d4cd26 100644 --- a/lib/e2e/src/account.rs +++ b/lib/e2e/src/account.rs @@ -13,6 +13,8 @@ use crate::{ system::{fund_account, Wallet, RPC_URL_ENV_VAR_NAME}, }; +const DEFAULT_FUNDING_ETH: u32 = 100; + /// Type that corresponds to a test account. #[derive(Clone, Debug)] pub struct Account { @@ -23,7 +25,7 @@ pub struct Account { } impl Account { - /// Create a new account. + /// Create a new account with a default funding of [`DEFAULT_FUNDING_ETH`]. /// /// # Errors /// @@ -103,7 +105,7 @@ impl AccountFactory { let signer = PrivateKeySigner::random(); let addr = signer.address(); - fund_account(addr, "100")?; + fund_account(addr, DEFAULT_FUNDING_ETH)?; let rpc_url = std::env::var(RPC_URL_ENV_VAR_NAME) .expect("failed to load RPC_URL var from env") diff --git a/lib/e2e/src/system.rs b/lib/e2e/src/system.rs index aef9ac3e..5d90cd8b 100644 --- a/lib/e2e/src/system.rs +++ b/lib/e2e/src/system.rs @@ -61,7 +61,7 @@ pub fn provider() -> Provider { } /// Send `amount` eth to `address` in the nitro-tesnode. -pub fn fund_account(address: Address, amount: &str) -> eyre::Result<()> { +pub fn fund_account(address: Address, amount: u32) -> eyre::Result<()> { let node_script = get_node_path()?.join("test-node.bash"); if !node_script.exists() { bail!("Test nitro node wasn't setup properly. Try to setup it first with `./scripts/nitro-testnode.sh -i -d`") @@ -73,7 +73,7 @@ pub fn fund_account(address: Address, amount: &str) -> eyre::Result<()> { .arg("--to") .arg(format!("address_{address}")) .arg("--ethamount") - .arg(amount) + .arg(amount.to_string()) .output()?; if !output.status.success() { diff --git a/scripts/bench.sh b/scripts/bench.sh index 8878daec..1801d6c3 100755 --- a/scripts/bench.sh +++ b/scripts/bench.sh @@ -5,9 +5,16 @@ MYDIR=$(realpath "$(dirname "$0")") cd "$MYDIR" cd .. -NIGHTLY_TOOLCHAIN=${NIGHTLY_TOOLCHAIN:-nightly} +NIGHTLY_TOOLCHAIN=${NIGHTLY_TOOLCHAIN:-nightly-2024-01-01} cargo +"$NIGHTLY_TOOLCHAIN" build --release --target wasm32-unknown-unknown -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort export RPC_URL=http://localhost:8547 -cargo run --release -p benches + +# No need to compile benchmarks with `--release` +# since this only runs the benchmarking code and the contracts have already been compiled with `--release` +cargo run -p benches + +echo "NOTE: To measure non cached contract's gas usage correctly, + benchmarks should run on a clean instance of the nitro test node." +echo echo "Finished running benches!" diff --git a/scripts/nitro-testnode.sh b/scripts/nitro-testnode.sh index 815323c2..4e807379 100755 --- a/scripts/nitro-testnode.sh +++ b/scripts/nitro-testnode.sh @@ -18,7 +18,14 @@ do shift ;; -q|--quit) - docker container stop $(docker container ls -q --filter name=nitro-testnode) + NITRO_CONTAINERS=$(docker container ls -q --filter name=nitro-testnode) + + if [ -z "$NITRO_CONTAINERS" ]; then + echo "No nitro-testnode containers running" + else + docker container stop $NITRO_CONTAINERS || exit + fi + exit 0 ;; *) @@ -43,8 +50,8 @@ then git clone --recurse-submodules https://github.com/OffchainLabs/nitro-testnode.git cd ./nitro-testnode || exit - # `release` branch. - git checkout 8cb6b84e31909157d431e7e4af9fb83799443e00 || exit + git pull origin release --recurse-submodules + git checkout d4244cd5c2cb56ca3d11c23478ef9642f8ebf472 || exit ./test-node.bash --no-run --init || exit fi From 9b04143090dd3308bbce92da529e4f81d9f1442d Mon Sep 17 00:00:00 2001 From: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com> Date: Fri, 27 Sep 2024 20:42:34 +0400 Subject: [PATCH 12/16] feat: erc165 support interface (#281) Adds erc165 standard altogether with a proc macro, that lets to compute interface id in a simple way. Resolves #33 #### PR Checklist - [x] Tests - [x] Documentation --------- Co-authored-by: Daniel Bigos --- .github/workflows/check-publish.yml | 3 + Cargo.lock | 11 ++ Cargo.toml | 3 + contracts-proc/Cargo.toml | 22 ++++ contracts-proc/src/interface_id.rs | 102 ++++++++++++++++++ contracts-proc/src/lib.rs | 64 +++++++++++ contracts/Cargo.toml | 1 + .../src/token/erc20/extensions/metadata.rs | 24 +++++ contracts/src/token/erc20/mod.rs | 28 ++++- .../src/token/erc721/extensions/enumerable.rs | 23 +++- .../src/token/erc721/extensions/metadata.rs | 26 ++++- contracts/src/token/erc721/mod.rs | 27 ++++- contracts/src/utils/introspection/erc165.rs | 64 +++++++++++ contracts/src/utils/introspection/mod.rs | 2 + contracts/src/utils/mod.rs | 1 + examples/erc20/src/lib.rs | 9 +- examples/erc20/tests/abi/mod.rs | 2 + examples/erc20/tests/erc20.rs | 47 ++++++++ examples/erc721/src/lib.rs | 9 +- examples/erc721/tests/abi/mod.rs | 5 + examples/erc721/tests/erc721.rs | 42 ++++++++ 21 files changed, 506 insertions(+), 9 deletions(-) create mode 100644 contracts-proc/Cargo.toml create mode 100644 contracts-proc/src/interface_id.rs create mode 100644 contracts-proc/src/lib.rs create mode 100644 contracts/src/utils/introspection/erc165.rs create mode 100644 contracts/src/utils/introspection/mod.rs diff --git a/.github/workflows/check-publish.yml b/.github/workflows/check-publish.yml index 67bbb311..132eb00c 100644 --- a/.github/workflows/check-publish.yml +++ b/.github/workflows/check-publish.yml @@ -37,6 +37,9 @@ jobs: - name: check openzeppelin-crypto run: cargo publish -p openzeppelin-crypto --target wasm32-unknown-unknown --dry-run + - name: check openzeppelin-stylus-proc + run: cargo publish -p openzeppelin-stylus-proc --target wasm32-unknown-unknown --dry-run + # TODO: https://github.com/OpenZeppelin/rust-contracts-stylus/issues/291 # - name: check openzeppelin-stylus # run: cargo publish -p openzeppelin-stylus --target wasm32-unknown-unknown --dry-run diff --git a/Cargo.lock b/Cargo.lock index a756c697..e9852f29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2592,11 +2592,22 @@ dependencies = [ "keccak-const", "mini-alloc", "motsu", + "openzeppelin-stylus-proc", "rand", "stylus-proc", "stylus-sdk", ] +[[package]] +name = "openzeppelin-stylus-proc" +version = "0.1.0-rc" +dependencies = [ + "convert_case 0.6.0", + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "ownable-example" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index ed00cd54..9115cfcb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "contracts", + "contracts-proc", "lib/crypto", "lib/motsu", "lib/motsu-proc", @@ -21,6 +22,7 @@ members = [ ] default-members = [ "contracts", + "contracts-proc", "lib/crypto", "lib/motsu", "lib/motsu-proc", @@ -98,6 +100,7 @@ quote = "1.0.35" # members openzeppelin-stylus = { path = "contracts" } +openzeppelin-stylus-proc = { path = "contracts-proc" } openzeppelin-crypto = { path = "lib/crypto" } motsu = { path = "lib/motsu"} motsu-proc = { path = "lib/motsu-proc", version = "0.1.0" } diff --git a/contracts-proc/Cargo.toml b/contracts-proc/Cargo.toml new file mode 100644 index 00000000..763639e8 --- /dev/null +++ b/contracts-proc/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "openzeppelin-stylus-proc" +description = "Procedural macros for OpenZeppelin Stylus contracts" +version.workspace = true +authors.workspace = true +edition.workspace = true +license.workspace = true +keywords.workspace = true +repository.workspace = true + + +[dependencies] +proc-macro2.workspace = true +quote.workspace = true +syn.workspace = true +convert_case = "0.6.0" + +[lints] +workspace = true + +[lib] +proc-macro = true diff --git a/contracts-proc/src/interface_id.rs b/contracts-proc/src/interface_id.rs new file mode 100644 index 00000000..c2347caf --- /dev/null +++ b/contracts-proc/src/interface_id.rs @@ -0,0 +1,102 @@ +//! Defines the `#[interface_id]` procedural macro. + +use std::mem; + +use convert_case::{Case, Casing}; +use proc_macro::TokenStream; +use proc_macro2::Ident; +use quote::quote; +use syn::{ + parse::{Parse, ParseStream}, + parse_macro_input, FnArg, ItemTrait, LitStr, Result, Token, TraitItem, +}; + +/// Computes an interface id as an associated constant for the trait. +pub(crate) fn interface_id( + _attr: &TokenStream, + input: TokenStream, +) -> TokenStream { + let mut input = parse_macro_input!(input as ItemTrait); + + let mut selectors = Vec::new(); + for item in &mut input.items { + let TraitItem::Fn(func) = item else { + continue; + }; + + let mut override_fn_name = None; + for attr in mem::take(&mut func.attrs) { + if attr.path().is_ident("selector") { + if override_fn_name.is_some() { + error!(attr.path(), "more than one selector attribute"); + } + let args: SelectorArgs = match attr.parse_args() { + Ok(args) => args, + Err(error) => error!(attr.path(), "{}", error), + }; + override_fn_name = Some(args.name); + } else { + // Put back any other attributes. + func.attrs.push(attr); + } + } + + let solidity_fn_name = override_fn_name.unwrap_or_else(|| { + let rust_fn_name = func.sig.ident.to_string(); + rust_fn_name.to_case(Case::Camel) + }); + + let arg_types = func.sig.inputs.iter().filter_map(|arg| match arg { + FnArg::Typed(t) => Some(t.ty.clone()), + // Opt out any `self` arguments. + FnArg::Receiver(_) => None, + }); + + // Store selector expression from every function in the trait. + selectors.push( + quote! { u32::from_be_bytes(stylus_sdk::function_selector!(#solidity_fn_name #(, #arg_types )*)) } + ); + } + + let name = input.ident; + let vis = input.vis; + let attrs = input.attrs; + let trait_items = input.items; + let (_impl_generics, ty_generics, where_clause) = + input.generics.split_for_impl(); + + // Keep the same trait with an additional associated constant + // `INTERFACE_ID`. + quote! { + #(#attrs)* + #vis trait #name #ty_generics #where_clause { + #(#trait_items)* + + #[doc = concat!("Solidity interface id associated with ", stringify!(#name), " trait.")] + #[doc = "Computed as a XOR of selectors for each function in the trait."] + const INTERFACE_ID: u32 = { + #(#selectors)^* + }; + } + } + .into() +} + +/// Contains arguments of the `#[selector(..)]` attribute. +struct SelectorArgs { + name: String, +} + +impl Parse for SelectorArgs { + fn parse(input: ParseStream) -> Result { + let ident: Ident = input.parse()?; + + if ident == "name" { + let _: Token![=] = input.parse()?; + let lit: LitStr = input.parse()?; + Ok(SelectorArgs { name: lit.value() }) + } else { + error!(@ident, "expected identifier 'name'") + } + } +} diff --git a/contracts-proc/src/lib.rs b/contracts-proc/src/lib.rs new file mode 100644 index 00000000..0d174638 --- /dev/null +++ b/contracts-proc/src/lib.rs @@ -0,0 +1,64 @@ +//! Procedural macro definitions used in `openzeppelin-stylus` smart contracts +//! library. + +extern crate proc_macro; +use proc_macro::TokenStream; + +/// Shorthand to print nice errors. +/// +/// Note that it's defined before the module declarations. +macro_rules! error { + ($tokens:expr, $($msg:expr),+ $(,)?) => {{ + let error = syn::Error::new(syn::spanned::Spanned::span(&$tokens), format!($($msg),+)); + return error.to_compile_error().into(); + }}; + (@ $tokens:expr, $($msg:expr),+ $(,)?) => {{ + return Err(syn::Error::new(syn::spanned::Spanned::span(&$tokens), format!($($msg),+))) + }}; +} + +mod interface_id; + +/// Computes the interface id as an associated constant `INTERFACE_ID` for the +/// trait that describes contract's abi. +/// +/// Selector collision should be handled with +/// macro `#[selector(name = "actualSolidityMethodName")]` on top of the method. +/// +/// # Examples +/// +/// ```rust,ignore +/// #[interface_id] +/// pub trait IErc721 { +/// fn balance_of(&self, owner: Address) -> Result>; +/// +/// fn owner_of(&self, token_id: U256) -> Result>; +/// +/// fn safe_transfer_from( +/// &mut self, +/// from: Address, +/// to: Address, +/// token_id: U256, +/// ) -> Result<(), Vec>; +/// +/// #[selector(name = "safeTransferFrom")] +/// fn safe_transfer_from_with_data( +/// &mut self, +/// from: Address, +/// to: Address, +/// token_id: U256, +/// data: Bytes, +/// ) -> Result<(), Vec>; +/// } +/// +/// impl IErc165 for Erc721 { +/// fn supports_interface(interface_id: FixedBytes<4>) -> bool { +/// ::INTERFACE_ID == u32::from_be_bytes(*interface_id) +/// || Erc165::supports_interface(interface_id) +/// } +/// } +/// ``` +#[proc_macro_attribute] +pub fn interface_id(attr: TokenStream, input: TokenStream) -> TokenStream { + interface_id::interface_id(&attr, input) +} diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index b6f9d776..13054d80 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -15,6 +15,7 @@ stylus-sdk.workspace = true stylus-proc.workspace = true mini-alloc.workspace = true keccak-const.workspace = true +openzeppelin-stylus-proc.workspace = true [dev-dependencies] alloy-primitives = { workspace = true, features = ["arbitrary"] } diff --git a/contracts/src/token/erc20/extensions/metadata.rs b/contracts/src/token/erc20/extensions/metadata.rs index 4035f558..ea8680cb 100644 --- a/contracts/src/token/erc20/extensions/metadata.rs +++ b/contracts/src/token/erc20/extensions/metadata.rs @@ -2,8 +2,12 @@ use alloc::string::String; +use alloy_primitives::FixedBytes; +use openzeppelin_stylus_proc::interface_id; use stylus_proc::{public, sol_storage}; +use crate::utils::introspection::erc165::IErc165; + /// Number of decimals used by default on implementors of [`Metadata`]. pub const DEFAULT_DECIMALS: u8 = 18; @@ -20,6 +24,7 @@ sol_storage! { } /// Interface for the optional metadata functions from the ERC-20 standard. +#[interface_id] pub trait IErc20Metadata { /// Returns the name of the token. /// @@ -76,3 +81,22 @@ impl IErc20Metadata for Erc20Metadata { DEFAULT_DECIMALS } } + +impl IErc165 for Erc20Metadata { + fn supports_interface(interface_id: FixedBytes<4>) -> bool { + ::INTERFACE_ID + == u32::from_be_bytes(*interface_id) + } +} + +#[cfg(all(test, feature = "std"))] +mod tests { + use crate::token::erc20::extensions::{Erc20Metadata, IErc20Metadata}; + + #[motsu::test] + fn interface_id() { + let actual = ::INTERFACE_ID; + let expected = 0xa219a025; + assert_eq!(actual, expected); + } +} diff --git a/contracts/src/token/erc20/mod.rs b/contracts/src/token/erc20/mod.rs index 5f9629af..b1b069d5 100644 --- a/contracts/src/token/erc20/mod.rs +++ b/contracts/src/token/erc20/mod.rs @@ -4,8 +4,9 @@ //! revert instead of returning `false` on failure. This behavior is //! nonetheless conventional and does not conflict with the expectations of //! [`Erc20`] applications. -use alloy_primitives::{Address, U256}; +use alloy_primitives::{Address, FixedBytes, U256}; use alloy_sol_types::sol; +use openzeppelin_stylus_proc::interface_id; use stylus_proc::SolidityError; use stylus_sdk::{ call::MethodError, @@ -13,6 +14,8 @@ use stylus_sdk::{ stylus_proc::{public, sol_storage}, }; +use crate::utils::introspection::erc165::{Erc165, IErc165}; + pub mod extensions; sol! { @@ -111,6 +114,7 @@ sol_storage! { } /// Required interface of an [`Erc20`] compliant contract. +#[interface_id] pub trait IErc20 { /// The error type associated to this ERC-20 trait implementation. type Error: Into>; @@ -286,6 +290,13 @@ impl IErc20 for Erc20 { } } +impl IErc165 for Erc20 { + fn supports_interface(interface_id: FixedBytes<4>) -> bool { + ::INTERFACE_ID == u32::from_be_bytes(*interface_id) + || Erc165::supports_interface(interface_id) + } +} + impl Erc20 { /// Sets a `value` number of tokens as the allowance of `spender` over the /// caller's tokens. @@ -550,6 +561,10 @@ mod tests { use stylus_sdk::msg; use super::{Erc20, Error, IErc20}; + use crate::{ + token::erc721::{Erc721, IErc721}, + utils::introspection::erc165::IErc165, + }; #[motsu::test] fn reads_balance(contract: Erc20) { @@ -882,4 +897,15 @@ mod tests { let result = contract.approve(Address::ZERO, one); assert!(matches!(result, Err(Error::InvalidSpender(_)))); } + + #[motsu::test] + fn interface_id() { + let actual = ::INTERFACE_ID; + let expected = 0x36372b07; + assert_eq!(actual, expected); + + let actual = ::INTERFACE_ID; + let expected = 0x01ffc9a7; + assert_eq!(actual, expected); + } } diff --git a/contracts/src/token/erc721/extensions/enumerable.rs b/contracts/src/token/erc721/extensions/enumerable.rs index 263f676a..2c5095aa 100644 --- a/contracts/src/token/erc721/extensions/enumerable.rs +++ b/contracts/src/token/erc721/extensions/enumerable.rs @@ -10,11 +10,15 @@ //! [`Erc721Enumerable`]. // TODO: Add link for `Erc721Consecutive` to module docs. -use alloy_primitives::{uint, Address, U256}; +use alloy_primitives::{uint, Address, FixedBytes, U256}; use alloy_sol_types::sol; +use openzeppelin_stylus_proc::interface_id; use stylus_proc::{public, sol_storage, SolidityError}; -use crate::token::{erc721, erc721::IErc721}; +use crate::{ + token::{erc721, erc721::IErc721}, + utils::introspection::erc165::IErc165, +}; sol! { /// Indicates an error when an `owner`'s token query @@ -63,6 +67,7 @@ sol_storage! { /// This is the interface of the optional `Enumerable` extension /// of the ERC-721 standard. +#[interface_id] pub trait IErc721Enumerable { /// The error type associated to this ERC-721 enumerable trait /// implementation. @@ -144,6 +149,13 @@ impl IErc721Enumerable for Erc721Enumerable { } } +impl IErc165 for Erc721Enumerable { + fn supports_interface(interface_id: FixedBytes<4>) -> bool { + ::INTERFACE_ID + == u32::from_be_bytes(*interface_id) + } +} + impl Erc721Enumerable { /// Function to add a token to this extension's /// ownership-tracking data structures. @@ -547,4 +559,11 @@ mod tests { contract.token_of_owner_by_index(alice, U256::ZERO).unwrap_err(); assert!(matches!(err, Error::OutOfBoundsIndex(_))); } + + #[motsu::test] + fn interface_id() { + let actual = ::INTERFACE_ID; + let expected = 0x780e9d63; + assert_eq!(actual, expected); + } } diff --git a/contracts/src/token/erc721/extensions/metadata.rs b/contracts/src/token/erc721/extensions/metadata.rs index 5b315bf4..634d0eda 100644 --- a/contracts/src/token/erc721/extensions/metadata.rs +++ b/contracts/src/token/erc721/extensions/metadata.rs @@ -2,9 +2,11 @@ use alloc::string::String; +use alloy_primitives::FixedBytes; +use openzeppelin_stylus_proc::interface_id; use stylus_proc::{public, sol_storage}; -use crate::utils::Metadata; +use crate::utils::{introspection::erc165::IErc165, Metadata}; sol_storage! { /// Metadata of an [`crate::token::erc721::Erc721`] token. @@ -17,6 +19,7 @@ sol_storage! { } /// Interface for the optional metadata functions from the ERC-721 standard. +#[interface_id] pub trait IErc721Metadata { /// Returns the token collection name. /// @@ -58,3 +61,24 @@ impl IErc721Metadata for Erc721Metadata { self._base_uri.get_string() } } + +impl IErc165 for Erc721Metadata { + fn supports_interface(interface_id: FixedBytes<4>) -> bool { + ::INTERFACE_ID + == u32::from_be_bytes(*interface_id) + } +} + +#[cfg(all(test, feature = "std"))] +mod tests { + // use crate::token::erc721::extensions::{Erc721Metadata, IErc721Metadata}; + + // TODO: IErc721Metadata should be refactored to have same api as solidity + // has: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4764ea50750d8bda9096e833706beba86918b163/contracts/token/ERC721/extensions/IERC721Metadata.sol#L12 + // [motsu::test] + // fn interface_id() { + // let actual = ::INTERFACE_ID; + // let expected = 0x5b5e139f; + // assert_eq!(actual, expected); + // } +} diff --git a/contracts/src/token/erc721/mod.rs b/contracts/src/token/erc721/mod.rs index 9d527695..84692aef 100644 --- a/contracts/src/token/erc721/mod.rs +++ b/contracts/src/token/erc721/mod.rs @@ -2,6 +2,7 @@ use alloc::vec; use alloy_primitives::{fixed_bytes, uint, Address, FixedBytes, U128, U256}; +use openzeppelin_stylus_proc::interface_id; use stylus_sdk::{ abi::Bytes, alloy_sol_types::sol, @@ -10,7 +11,10 @@ use stylus_sdk::{ prelude::*, }; -use crate::utils::math::storage::{AddAssignUnchecked, SubAssignUnchecked}; +use crate::utils::{ + introspection::erc165::{Erc165, IErc165}, + math::storage::{AddAssignUnchecked, SubAssignUnchecked}, +}; pub mod extensions; @@ -198,6 +202,7 @@ sol_storage! { unsafe impl TopLevelStorage for Erc721 {} /// Required interface of an [`Erc721`] compliant contract. +#[interface_id] pub trait IErc721 { /// The error type associated to this ERC-721 trait implementation. type Error: Into>; @@ -317,6 +322,7 @@ pub trait IErc721 { /// # Events /// /// Emits a [`Transfer`] event. + #[selector(name = "safeTransferFrom")] fn safe_transfer_from_with_data( &mut self, from: Address, @@ -549,6 +555,13 @@ impl IErc721 for Erc721 { } } +impl IErc165 for Erc721 { + fn supports_interface(interface_id: FixedBytes<4>) -> bool { + ::INTERFACE_ID == u32::from_be_bytes(*interface_id) + || Erc165::supports_interface(interface_id) + } +} + impl Erc721 { /// Returns the owner of the `token_id`. Does NOT revert if the token /// doesn't exist. @@ -1153,6 +1166,7 @@ mod tests { ERC721InvalidReceiver, ERC721InvalidSender, ERC721NonexistentToken, Erc721, Error, IErc721, }; + use crate::utils::introspection::erc165::IErc165; const BOB: Address = address!("F4EaCDAbEf3c8f1EdE91b6f2A6840bc2E4DD3526"); const DAVE: Address = address!("0BB78F7e7132d1651B4Fd884B7624394e92156F1"); @@ -2481,4 +2495,15 @@ mod tests { }) if token_id == t_id )); } + + #[motsu::test] + fn interface_id() { + let actual = ::INTERFACE_ID; + let expected = 0x80ac58cd; + assert_eq!(actual, expected); + + let actual = ::INTERFACE_ID; + let expected = 0x01ffc9a7; + assert_eq!(actual, expected); + } } diff --git a/contracts/src/utils/introspection/erc165.rs b/contracts/src/utils/introspection/erc165.rs new file mode 100644 index 00000000..bace2799 --- /dev/null +++ b/contracts/src/utils/introspection/erc165.rs @@ -0,0 +1,64 @@ +//! Trait and implementation of the ERC-165 standard, as defined in the [ERC]. +//! +//! [ERC]: https://eips.ethereum.org/EIPS/eip-165 + +use alloy_primitives::FixedBytes; +use openzeppelin_stylus_proc::interface_id; + +/// Interface of the ERC-165 standard, as defined in the [ERC]. +/// +/// Implementers can declare support of contract interfaces, which others can +/// query. +/// +/// For an implementation, see [`Erc165`]. +/// +/// [ERC]: https://eips.ethereum.org/EIPS/eip-165 +#[interface_id] +pub trait IErc165 { + /// Returns true if this contract implements the interface defined by + /// `interface_id`. See the corresponding [ERC section] + /// to learn more about how these ids are created. + /// + /// Method [`IErc165::supports_interface`] should be reexported with + /// `#[public]` macro manually like this: + /// + /// ```rust,ignore + /// #[public] + /// impl Erc20Example { + /// fn supports_interface(interface_id: FixedBytes<4>) -> bool { + /// Erc20::supports_interface(interface_id) + /// || Erc20Metadata::supports_interface(interface_id) + /// } + /// } + /// ``` + /// + /// # Arguments + /// + /// * `interface_id` - The interface identifier, as specified in [ERC + /// section] + /// + /// [ERC section]: https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified + fn supports_interface(interface_id: FixedBytes<4>) -> bool; +} + +/// Implementation of the [`IErc165`] trait. +/// +/// Contracts that want to support ERC-165 should implement the [`IErc165`] +/// trait for the additional interface id that will be supported and call +/// [`Erc165::supports_interface`] like: +/// +/// ```rust,ignore +/// impl IErc165 for Erc20 { +/// fn supports_interface(interface_id: FixedBytes<4>) -> bool { +/// crate::token::erc20::INTERFACE_ID == u32::from_be_bytes(*interface_id) +/// || Erc165::supports_interface(interface_id) +/// } +/// } +/// ``` +pub struct Erc165; + +impl IErc165 for Erc165 { + fn supports_interface(interface_id: FixedBytes<4>) -> bool { + Self::INTERFACE_ID == u32::from_be_bytes(*interface_id) + } +} diff --git a/contracts/src/utils/introspection/mod.rs b/contracts/src/utils/introspection/mod.rs new file mode 100644 index 00000000..72077bf5 --- /dev/null +++ b/contracts/src/utils/introspection/mod.rs @@ -0,0 +1,2 @@ +//! Stylus contract's introspection helpers library. +pub mod erc165; diff --git a/contracts/src/utils/mod.rs b/contracts/src/utils/mod.rs index 7c24bc20..b8f56cef 100644 --- a/contracts/src/utils/mod.rs +++ b/contracts/src/utils/mod.rs @@ -1,5 +1,6 @@ //! Common Smart Contracts utilities. pub mod cryptography; +pub mod introspection; pub mod math; pub mod metadata; pub mod nonces; diff --git a/examples/erc20/src/lib.rs b/examples/erc20/src/lib.rs index 407e87d0..ace37b5f 100644 --- a/examples/erc20/src/lib.rs +++ b/examples/erc20/src/lib.rs @@ -3,13 +3,13 @@ extern crate alloc; use alloc::vec::Vec; -use alloy_primitives::{Address, U256}; +use alloy_primitives::{Address, FixedBytes, U256}; use openzeppelin_stylus::{ token::erc20::{ extensions::{capped, Capped, Erc20Metadata, IErc20Burnable}, Erc20, IErc20, }, - utils::Pausable, + utils::{introspection::erc165::IErc165, Pausable}, }; use stylus_sdk::prelude::{entrypoint, public, sol_storage}; @@ -105,4 +105,9 @@ impl Erc20Example { self.pausable.when_not_paused()?; self.erc20.transfer_from(from, to, value).map_err(|e| e.into()) } + + fn supports_interface(interface_id: FixedBytes<4>) -> bool { + Erc20::supports_interface(interface_id) + || Erc20Metadata::supports_interface(interface_id) + } } diff --git a/examples/erc20/tests/abi/mod.rs b/examples/erc20/tests/abi/mod.rs index 0e652d26..f042e396 100644 --- a/examples/erc20/tests/abi/mod.rs +++ b/examples/erc20/tests/abi/mod.rs @@ -29,6 +29,8 @@ sol!( #[derive(Debug)] function whenNotPaused() external view; + function supportsInterface(bytes4 interface_id) external view returns (bool supportsInterface); + error EnforcedPause(); error ExpectedPause(); diff --git a/examples/erc20/tests/erc20.rs b/examples/erc20/tests/erc20.rs index cc82c8de..a1301939 100644 --- a/examples/erc20/tests/erc20.rs +++ b/examples/erc20/tests/erc20.rs @@ -1340,3 +1340,50 @@ async fn error_when_transfer_from(alice: Account, bob: Account) -> Result<()> { Ok(()) } + +// ============================================================================ +// Integration Tests: ERC-165 Support Interface +// ============================================================================ + +#[e2e::test] +async fn support_interface(alice: Account) -> Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc20::new(contract_addr, &alice.wallet); + let invalid_interface_id: u32 = 0xffffffff; + let Erc20::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract.supportsInterface(invalid_interface_id.into()).call().await?; + + assert_eq!(supports_interface, false); + + let erc20_interface_id: u32 = 0x36372b07; + let Erc20::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract.supportsInterface(erc20_interface_id.into()).call().await?; + + assert_eq!(supports_interface, true); + + let erc165_interface_id: u32 = 0x01ffc9a7; + let Erc20::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract.supportsInterface(erc165_interface_id.into()).call().await?; + + assert_eq!(supports_interface, true); + + let erc20_metadata_interface_id: u32 = 0xa219a025; + let Erc20::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract + .supportsInterface(erc20_metadata_interface_id.into()) + .call() + .await?; + + assert_eq!(supports_interface, true); + + Ok(()) +} diff --git a/examples/erc721/src/lib.rs b/examples/erc721/src/lib.rs index 8d2a4d62..3b1c22ef 100644 --- a/examples/erc721/src/lib.rs +++ b/examples/erc721/src/lib.rs @@ -3,13 +3,13 @@ extern crate alloc; use alloc::vec::Vec; -use alloy_primitives::{Address, U256}; +use alloy_primitives::{Address, FixedBytes, U256}; use openzeppelin_stylus::{ token::erc721::{ extensions::{Erc721Enumerable as Enumerable, IErc721Burnable}, Erc721, IErc721, }, - utils::Pausable, + utils::{introspection::erc165::IErc165, Pausable}, }; use stylus_sdk::{ abi::Bytes, @@ -151,4 +151,9 @@ impl Erc721Example { Ok(()) } + + pub fn supports_interface(interface_id: FixedBytes<4>) -> bool { + Erc721::supports_interface(interface_id) + || Enumerable::supports_interface(interface_id) + } } diff --git a/examples/erc721/tests/abi/mod.rs b/examples/erc721/tests/abi/mod.rs index b02f4448..796f4174 100644 --- a/examples/erc721/tests/abi/mod.rs +++ b/examples/erc721/tests/abi/mod.rs @@ -18,8 +18,10 @@ sol!( function setApprovalForAll(address operator, bool approved) external; function totalSupply() external view returns (uint256 totalSupply); function transferFrom(address from, address to, uint256 tokenId) external; + function mint(address to, uint256 tokenId) external; function burn(uint256 tokenId) external; + function paused() external view returns (bool paused); function pause() external; function unpause() external; @@ -27,11 +29,14 @@ sol!( function whenPaused() external view; #[derive(Debug)] function whenNotPaused() external view; + #[derive(Debug)] function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); #[derive(Debug)] function tokenByIndex(uint256 index) external view returns (uint256 tokenId); + function supportsInterface(bytes4 interface_id) external view returns (bool supportsInterface); + error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); error ERC721InsufficientApproval(address operator, uint256 tokenId); error ERC721InvalidApprover(address approver); diff --git a/examples/erc721/tests/erc721.rs b/examples/erc721/tests/erc721.rs index b8bf68fd..f00504a9 100644 --- a/examples/erc721/tests/erc721.rs +++ b/examples/erc721/tests/erc721.rs @@ -2097,3 +2097,45 @@ async fn token_by_index_after_burn_and_some_mints( Ok(()) } + +// ============================================================================ +// Integration Tests: ERC-165 Support Interface +// ============================================================================ + +#[e2e::test] +async fn support_interface(alice: Account) -> eyre::Result<()> { + let contract_addr = alice.as_deployer().deploy().await?.address()?; + let contract = Erc721::new(contract_addr, &alice.wallet); + let invalid_interface_id: u32 = 0x_ffffffff; + let Erc721::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract.supportsInterface(invalid_interface_id.into()).call().await?; + + assert_eq!(supports_interface, false); + + let erc721_interface_id: u32 = 0x80ac58cd; + let Erc721::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract.supportsInterface(erc721_interface_id.into()).call().await?; + + assert_eq!(supports_interface, true); + + let erc165_interface_id: u32 = 0x01ffc9a7; + let Erc721::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract.supportsInterface(erc165_interface_id.into()).call().await?; + + assert_eq!(supports_interface, true); + + let erc721_enumerable_interface_id: u32 = 0x780e9d63; + let Erc721::supportsInterfaceReturn { + supportsInterface: supports_interface, + } = contract + .supportsInterface(erc721_enumerable_interface_id.into()) + .call() + .await?; + + assert_eq!(supports_interface, true); + + Ok(()) +} From 5f77db765631217fe957bf059f45278ce034123c Mon Sep 17 00:00:00 2001 From: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com> Date: Mon, 30 Sep 2024 06:41:03 +0400 Subject: [PATCH 13/16] fix: update keywords for contracts-proc (#301) Due to automerge `openzeppelin-stylus-proc` crate is using keywords from the workspace and breaks the build. --- contracts-proc/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts-proc/Cargo.toml b/contracts-proc/Cargo.toml index 763639e8..3372da2c 100644 --- a/contracts-proc/Cargo.toml +++ b/contracts-proc/Cargo.toml @@ -5,7 +5,8 @@ version.workspace = true authors.workspace = true edition.workspace = true license.workspace = true -keywords.workspace = true +categories = ["cryptography::cryptocurrencies", "no-std", "wasm"] +keywords = ["arbitrum", "ethereum", "stylus", "smart-contracts", "standards"] repository.workspace = true From 15378195b8be65be63af7b259af05677ea73d0be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:31:27 +0200 Subject: [PATCH 14/16] build(deps): bump crate-ci/typos from 1.24.6 to 1.25.0 (#303) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.24.6 to 1.25.0.
Release notes

Sourced from crate-ci/typos's releases.

v1.25.0

[1.25.0] - 2024-10-01

Fixes

Changelog

Sourced from crate-ci/typos's changelog.

[1.25.0] - 2024-10-01

Fixes

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.24.6&new-version=1.25.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 6ac80efd..ff13e16b 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -110,4 +110,4 @@ jobs: - name: Checkout Actions Repository uses: actions/checkout@v4 - name: Check spelling of files in the workspace - uses: crate-ci/typos@v1.24.6 + uses: crate-ci/typos@v1.25.0 From c40dc8e4ca836f28233d771f217d3354d5c03437 Mon Sep 17 00:00:00 2001 From: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com> Date: Wed, 2 Oct 2024 21:09:46 +0400 Subject: [PATCH 15/16] docs: erc165 + structs (#304) Follows up #62 #### PR Checklist - [ ] Tests - [x] Documentation --------- Co-authored-by: Gustavo Gonzalez --- docs/modules/ROOT/nav.adoc | 1 + docs/modules/ROOT/pages/utilities.adoc | 43 ++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 docs/modules/ROOT/pages/utilities.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 05060ec6..1bcc4ea4 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -9,3 +9,4 @@ * xref:access-control.adoc[Access Control] * xref:crypto.adoc[Cryptography] +* xref:utilities.adoc[Utilities] diff --git a/docs/modules/ROOT/pages/utilities.adoc b/docs/modules/ROOT/pages/utilities.adoc new file mode 100644 index 00000000..249752b7 --- /dev/null +++ b/docs/modules/ROOT/pages/utilities.adoc @@ -0,0 +1,43 @@ += Utilities + +The OpenZeppelin Stylus Contracts provides a ton of useful utilities that you can use in your project. +For a complete list, check out the https://docs.rs/openzeppelin-stylus/0.1.0-rc/openzeppelin_stylus/utils/index.html[API Reference]. +Here are some of the more popular ones. + +[[introspection]] +== Introspection + +It's frequently helpful to know whether a contract supports an interface you'd like to use. +https://eips.ethereum.org/EIPS/eip-165[`ERC-165`] is a standard that helps do runtime interface detection. +Contracts for Stylus provides helpers for implementing ERC-165 in your contracts: + +* https://docs.rs/openzeppelin-stylus/0.1.0-rc/openzeppelin_stylus/utils/introspection/erc165/trait.IErc165.html[`IERC165`] — this is the ERC-165 trait that defines https://docs.rs/openzeppelin-stylus/0.1.0-rc/openzeppelin_stylus/utils/introspection/erc165/trait.IErc165.html#tymethod.supports_interface[`supportsInterface`]. In order to implement ERC-165 interface detection, you should manually expose https://docs.rs/openzeppelin-stylus/0.1.0-rc/openzeppelin_stylus/utils/introspection/erc165/trait.IErc165.html#tymethod.supports_interface[`supportsInterface`] function in your contract. + +[source,rust] +---- +sol_storage! { + #[entrypoint] + struct Erc721Example { + #[borrow] + Erc721 erc721; + } +} + +#[public] +#[inherit(Erc721)] +impl Erc721Example { + pub fn supports_interface(interface_id: FixedBytes<4>) -> bool { + Erc721::supports_interface(interface_id) + } +} + +---- + +[[structures]] +== Structures + +Some use cases require more powerful data structures than arrays and mappings offered natively in alloy and the Stylus sdk. +Contracts for Stylus provides these libraries for enhanced data structure management: + +- https://docs.rs/openzeppelin-stylus/0.1.0-rc/openzeppelin_stylus/utils/structs/bitmap/index.html[`BitMaps`]: Store packed booleans in storage. +- https://docs.rs/openzeppelin-stylus/0.1.0-rc/openzeppelin_stylus/utils/structs/checkpoints/index.html[`Checkpoints`]: Checkpoint values with built-in lookups. \ No newline at end of file From dce09d3504c1e68d30c02bd5f1d0644ca430040a Mon Sep 17 00:00:00 2001 From: Alisander Qoshqosh <37006439+qalisander@users.noreply.github.com> Date: Wed, 2 Oct 2024 21:31:12 +0400 Subject: [PATCH 16/16] chore: use stylus-proc indirectly (#298) `stylus-sdk` already reexports matching `stylus-proc` version. Make sense to simplify dependencies a bit and use reexported library everywhere. --- Cargo.lock | 12 ------------ Cargo.toml | 1 - README.md | 15 +++++++++++---- contracts/Cargo.toml | 1 - contracts/src/access/control.rs | 3 +-- contracts/src/access/ownable.rs | 3 +-- contracts/src/token/erc20/extensions/capped.rs | 2 +- contracts/src/token/erc20/extensions/metadata.rs | 2 +- contracts/src/token/erc20/extensions/permit.rs | 8 ++++++-- contracts/src/token/erc20/mod.rs | 3 +-- .../src/token/erc721/extensions/consecutive.rs | 8 ++++++-- .../src/token/erc721/extensions/enumerable.rs | 2 +- contracts/src/token/erc721/extensions/metadata.rs | 2 +- .../src/token/erc721/extensions/uri_storage.rs | 6 ++++-- contracts/src/utils/cryptography/ecdsa.rs | 2 +- contracts/src/utils/metadata.rs | 2 +- contracts/src/utils/nonces.rs | 2 +- contracts/src/utils/pausable.rs | 6 ++++-- contracts/src/utils/structs/bitmap.rs | 2 +- contracts/src/utils/structs/checkpoints.rs | 2 +- examples/access-control/Cargo.toml | 1 - examples/basic/token/Cargo.toml | 1 - examples/ecdsa/Cargo.toml | 1 - examples/erc20-permit/Cargo.toml | 1 - examples/erc20/Cargo.toml | 1 - examples/erc721-consecutive/Cargo.toml | 1 - examples/erc721-metadata/Cargo.toml | 1 - examples/erc721/Cargo.toml | 1 - examples/merkle-proofs/Cargo.toml | 1 - examples/merkle-proofs/src/lib.rs | 2 +- examples/ownable/Cargo.toml | 1 - lib/motsu-proc/Cargo.toml | 1 - 32 files changed, 44 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9852f29..0629f702 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,7 +12,6 @@ dependencies = [ "eyre", "mini-alloc", "openzeppelin-stylus", - "stylus-proc", "stylus-sdk", "tokio", ] @@ -799,7 +798,6 @@ dependencies = [ "alloy-primitives", "mini-alloc", "openzeppelin-stylus", - "stylus-proc", "stylus-sdk", ] @@ -1271,7 +1269,6 @@ dependencies = [ "eyre", "mini-alloc", "openzeppelin-stylus", - "stylus-proc", "stylus-sdk", "tokio", ] @@ -1523,7 +1520,6 @@ dependencies = [ "eyre", "mini-alloc", "openzeppelin-stylus", - "stylus-proc", "stylus-sdk", "tokio", ] @@ -1538,7 +1534,6 @@ dependencies = [ "eyre", "mini-alloc", "openzeppelin-stylus", - "stylus-proc", "stylus-sdk", "tokio", ] @@ -1555,7 +1550,6 @@ dependencies = [ "mini-alloc", "openzeppelin-stylus", "rand", - "stylus-proc", "stylus-sdk", "tokio", ] @@ -1571,7 +1565,6 @@ dependencies = [ "mini-alloc", "openzeppelin-stylus", "rand", - "stylus-proc", "stylus-sdk", "tokio", ] @@ -1587,7 +1580,6 @@ dependencies = [ "mini-alloc", "openzeppelin-stylus", "rand", - "stylus-proc", "stylus-sdk", "tokio", ] @@ -2367,7 +2359,6 @@ dependencies = [ "alloy-sol-types", "mini-alloc", "openzeppelin-crypto", - "stylus-proc", "stylus-sdk", ] @@ -2433,7 +2424,6 @@ dependencies = [ "motsu", "proc-macro2", "quote", - "stylus-proc", "stylus-sdk", "syn 2.0.68", ] @@ -2594,7 +2584,6 @@ dependencies = [ "motsu", "openzeppelin-stylus-proc", "rand", - "stylus-proc", "stylus-sdk", ] @@ -2618,7 +2607,6 @@ dependencies = [ "eyre", "mini-alloc", "openzeppelin-stylus", - "stylus-proc", "stylus-sdk", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 9115cfcb..1886c295 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,6 @@ all = "warn" [workspace.dependencies] # stylus-related stylus-sdk = { version = "=0.6.0", default-features = false } -stylus-proc = { version = "=0.6.0", default-features = false } mini-alloc = "0.4.2" alloy = { version = "0.1.4", features = [ diff --git a/README.md b/README.md index 5eab8f1b..dec4d415 100644 --- a/README.md +++ b/README.md @@ -17,20 +17,25 @@ - [Unit] and [integration] test affordances, used in our own tests. [`openzeppelin-contracts`]: https://github.com/OpenZeppelin/openzeppelin-contracts + [`koba`]: https://github.com/OpenZeppelin/koba + [Unit]: ./lib/motsu/README.md + [integration]: ./lib/e2e/README.md ## Usage -You can import OpenZeppelin Contracts from crates.io by adding the following line to your `Cargo.toml` (We recommend pinning to a specific version): +You can import OpenZeppelin Contracts from crates.io by adding the following +line to your `Cargo.toml` (We recommend pinning to a specific version): ```toml [dependencies] openzeppelin-stylus = "0.1.0-rc" ``` -Optionally,you can specify a git dependency if you want to have the latest changes from the `main` branch: +Optionally, you can specify a git dependency if you want to have the latest +changes from the `main` branch: ```toml [dependencies] @@ -53,7 +58,7 @@ sol_storage! { #[external] #[inherit(Erc20)] -impl Erc20Example { } +impl Erc20Example {} ``` For a more complex display of what this library offers, refer to our @@ -66,6 +71,7 @@ For more information on what this library will include in the future, see our [roadmap]. [basic]: ./examples/basic + [roadmap]: https://github.com/OpenZeppelin/rust-contracts-stylus/milestone/1 ## Contribute @@ -85,4 +91,5 @@ Refer to our [Security Policy](SECURITY.md) for more details. ## License -OpenZeppelin Contracts for Stylus is released under the [MIT License](./LICENSE). +OpenZeppelin Contracts for Stylus is released under +the [MIT License](./LICENSE). diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index 13054d80..ba4f306a 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -12,7 +12,6 @@ version.workspace = true alloy-primitives.workspace = true alloy-sol-types.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true keccak-const.workspace = true openzeppelin-stylus-proc.workspace = true diff --git a/contracts/src/access/control.rs b/contracts/src/access/control.rs index 7d5a7cf5..1ef99735 100644 --- a/contracts/src/access/control.rs +++ b/contracts/src/access/control.rs @@ -42,10 +42,9 @@ //! this role. use alloy_primitives::{Address, B256}; use alloy_sol_types::sol; -use stylus_proc::SolidityError; use stylus_sdk::{ evm, msg, - stylus_proc::{public, sol_storage}, + stylus_proc::{public, sol_storage, SolidityError}, }; sol! { diff --git a/contracts/src/access/ownable.rs b/contracts/src/access/ownable.rs index 01a56369..157457fd 100644 --- a/contracts/src/access/ownable.rs +++ b/contracts/src/access/ownable.rs @@ -10,10 +10,9 @@ //! to the owner. use alloy_primitives::Address; use alloy_sol_types::sol; -use stylus_proc::SolidityError; use stylus_sdk::{ evm, msg, - stylus_proc::{public, sol_storage}, + stylus_proc::{public, sol_storage, SolidityError}, }; sol! { diff --git a/contracts/src/token/erc20/extensions/capped.rs b/contracts/src/token/erc20/extensions/capped.rs index 40fdea92..a971900b 100644 --- a/contracts/src/token/erc20/extensions/capped.rs +++ b/contracts/src/token/erc20/extensions/capped.rs @@ -7,7 +7,7 @@ use alloy_primitives::U256; use alloy_sol_types::sol; -use stylus_proc::{public, sol_storage, SolidityError}; +use stylus_sdk::stylus_proc::{public, sol_storage, SolidityError}; sol! { /// Indicates an error related to the operation that failed diff --git a/contracts/src/token/erc20/extensions/metadata.rs b/contracts/src/token/erc20/extensions/metadata.rs index ea8680cb..32697e07 100644 --- a/contracts/src/token/erc20/extensions/metadata.rs +++ b/contracts/src/token/erc20/extensions/metadata.rs @@ -4,7 +4,7 @@ use alloc::string::String; use alloy_primitives::FixedBytes; use openzeppelin_stylus_proc::interface_id; -use stylus_proc::{public, sol_storage}; +use stylus_sdk::stylus_proc::{public, sol_storage}; use crate::utils::introspection::erc165::IErc165; diff --git a/contracts/src/token/erc20/extensions/permit.rs b/contracts/src/token/erc20/extensions/permit.rs index 0e57300d..9283677d 100644 --- a/contracts/src/token/erc20/extensions/permit.rs +++ b/contracts/src/token/erc20/extensions/permit.rs @@ -11,8 +11,12 @@ //! and thus is not required to hold Ether at all. use alloy_primitives::{b256, keccak256, Address, B256, U256}; use alloy_sol_types::{sol, SolType}; -use stylus_proc::{public, sol_storage, SolidityError}; -use stylus_sdk::{block, prelude::StorageType, storage::TopLevelStorage}; +use stylus_sdk::{ + block, + prelude::StorageType, + storage::TopLevelStorage, + stylus_proc::{public, sol_storage, SolidityError}, +}; use crate::{ token::erc20::{self, Erc20, IErc20}, diff --git a/contracts/src/token/erc20/mod.rs b/contracts/src/token/erc20/mod.rs index b1b069d5..9a83384c 100644 --- a/contracts/src/token/erc20/mod.rs +++ b/contracts/src/token/erc20/mod.rs @@ -7,11 +7,10 @@ use alloy_primitives::{Address, FixedBytes, U256}; use alloy_sol_types::sol; use openzeppelin_stylus_proc::interface_id; -use stylus_proc::SolidityError; use stylus_sdk::{ call::MethodError, evm, msg, - stylus_proc::{public, sol_storage}, + stylus_proc::{public, sol_storage, SolidityError}, }; use crate::utils::introspection::erc165::{Erc165, IErc165}; diff --git a/contracts/src/token/erc721/extensions/consecutive.rs b/contracts/src/token/erc721/extensions/consecutive.rs index d5f173a2..22a29b9c 100644 --- a/contracts/src/token/erc721/extensions/consecutive.rs +++ b/contracts/src/token/erc721/extensions/consecutive.rs @@ -26,8 +26,12 @@ use alloc::vec; use alloy_primitives::{uint, Address, U256}; use alloy_sol_types::sol; -use stylus_proc::{public, sol_storage, SolidityError}; -use stylus_sdk::{abi::Bytes, evm, msg, prelude::TopLevelStorage}; +use stylus_sdk::{ + abi::Bytes, + evm, msg, + prelude::TopLevelStorage, + stylus_proc::{public, sol_storage, SolidityError}, +}; use crate::{ token::{ diff --git a/contracts/src/token/erc721/extensions/enumerable.rs b/contracts/src/token/erc721/extensions/enumerable.rs index 2c5095aa..b82df270 100644 --- a/contracts/src/token/erc721/extensions/enumerable.rs +++ b/contracts/src/token/erc721/extensions/enumerable.rs @@ -13,7 +13,7 @@ use alloy_primitives::{uint, Address, FixedBytes, U256}; use alloy_sol_types::sol; use openzeppelin_stylus_proc::interface_id; -use stylus_proc::{public, sol_storage, SolidityError}; +use stylus_sdk::stylus_proc::{public, sol_storage, SolidityError}; use crate::{ token::{erc721, erc721::IErc721}, diff --git a/contracts/src/token/erc721/extensions/metadata.rs b/contracts/src/token/erc721/extensions/metadata.rs index 634d0eda..2fe273e2 100644 --- a/contracts/src/token/erc721/extensions/metadata.rs +++ b/contracts/src/token/erc721/extensions/metadata.rs @@ -4,7 +4,7 @@ use alloc::string::String; use alloy_primitives::FixedBytes; use openzeppelin_stylus_proc::interface_id; -use stylus_proc::{public, sol_storage}; +use stylus_sdk::stylus_proc::{public, sol_storage}; use crate::utils::{introspection::erc165::IErc165, Metadata}; diff --git a/contracts/src/token/erc721/extensions/uri_storage.rs b/contracts/src/token/erc721/extensions/uri_storage.rs index f5afc180..651de00e 100644 --- a/contracts/src/token/erc721/extensions/uri_storage.rs +++ b/contracts/src/token/erc721/extensions/uri_storage.rs @@ -5,8 +5,10 @@ use alloc::string::String; use alloy_primitives::U256; use alloy_sol_types::sol; -use stylus_proc::{public, sol_storage}; -use stylus_sdk::evm; +use stylus_sdk::{ + evm, + stylus_proc::{public, sol_storage}, +}; sol! { /// This event gets emitted when the metadata of a token is changed. diff --git a/contracts/src/utils/cryptography/ecdsa.rs b/contracts/src/utils/cryptography/ecdsa.rs index e667393d..d91f44f7 100644 --- a/contracts/src/utils/cryptography/ecdsa.rs +++ b/contracts/src/utils/cryptography/ecdsa.rs @@ -6,10 +6,10 @@ use alloc::vec::Vec; use alloy_primitives::{address, uint, Address, B256, U256}; use alloy_sol_types::{sol, SolType}; -use stylus_proc::SolidityError; use stylus_sdk::{ call::{self, Call, MethodError}, storage::TopLevelStorage, + stylus_proc::SolidityError, }; use crate::utils::cryptography::ecdsa; diff --git a/contracts/src/utils/metadata.rs b/contracts/src/utils/metadata.rs index de3e83f8..7d904dbb 100644 --- a/contracts/src/utils/metadata.rs +++ b/contracts/src/utils/metadata.rs @@ -1,7 +1,7 @@ //! Common Metadata Smart Contract. use alloc::string::String; -use stylus_proc::{public, sol_storage}; +use stylus_sdk::stylus_proc::{public, sol_storage}; sol_storage! { /// Metadata of the token. diff --git a/contracts/src/utils/nonces.rs b/contracts/src/utils/nonces.rs index da02be73..75256517 100644 --- a/contracts/src/utils/nonces.rs +++ b/contracts/src/utils/nonces.rs @@ -4,7 +4,7 @@ use alloy_primitives::{uint, Address, U256}; use alloy_sol_types::sol; -use stylus_proc::{public, sol_storage, SolidityError}; +use stylus_sdk::stylus_proc::{public, sol_storage, SolidityError}; const ONE: U256 = uint!(1_U256); diff --git a/contracts/src/utils/pausable.rs b/contracts/src/utils/pausable.rs index a49aec77..d128ce0d 100644 --- a/contracts/src/utils/pausable.rs +++ b/contracts/src/utils/pausable.rs @@ -11,8 +11,10 @@ //! only once the modifiers are put in place. use alloy_sol_types::sol; -use stylus_proc::{public, sol_storage, SolidityError}; -use stylus_sdk::{evm, msg}; +use stylus_sdk::{ + evm, msg, + stylus_proc::{public, sol_storage, SolidityError}, +}; sol! { /// Emitted when pause is triggered by `account`. diff --git a/contracts/src/utils/structs/bitmap.rs b/contracts/src/utils/structs/bitmap.rs index 35489334..b36c0037 100644 --- a/contracts/src/utils/structs/bitmap.rs +++ b/contracts/src/utils/structs/bitmap.rs @@ -14,7 +14,7 @@ //! //! [merkle-distributor]: https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol use alloy_primitives::{uint, U256}; -use stylus_proc::sol_storage; +use stylus_sdk::stylus_proc::sol_storage; const ONE: U256 = uint!(0x1_U256); const HEX_FF: U256 = uint!(0xff_U256); diff --git a/contracts/src/utils/structs/checkpoints.rs b/contracts/src/utils/structs/checkpoints.rs index 9e055756..4080184c 100644 --- a/contracts/src/utils/structs/checkpoints.rs +++ b/contracts/src/utils/structs/checkpoints.rs @@ -6,10 +6,10 @@ //! block using the [`Trace160::push`] function. use alloy_primitives::{uint, Uint, U256, U32}; use alloy_sol_types::sol; -use stylus_proc::{sol_storage, SolidityError}; use stylus_sdk::{ call::MethodError, storage::{StorageGuard, StorageGuardMut}, + stylus_proc::{sol_storage, SolidityError}, }; use crate::utils::math::alloy::Math; diff --git a/examples/access-control/Cargo.toml b/examples/access-control/Cargo.toml index cf032181..37cdff42 100644 --- a/examples/access-control/Cargo.toml +++ b/examples/access-control/Cargo.toml @@ -10,7 +10,6 @@ version.workspace = true openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/examples/basic/token/Cargo.toml b/examples/basic/token/Cargo.toml index 077980f9..27998d9e 100644 --- a/examples/basic/token/Cargo.toml +++ b/examples/basic/token/Cargo.toml @@ -10,7 +10,6 @@ version.workspace = true openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [features] diff --git a/examples/ecdsa/Cargo.toml b/examples/ecdsa/Cargo.toml index 7cac7e54..b0c9b012 100644 --- a/examples/ecdsa/Cargo.toml +++ b/examples/ecdsa/Cargo.toml @@ -10,7 +10,6 @@ version.workspace = true openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/examples/erc20-permit/Cargo.toml b/examples/erc20-permit/Cargo.toml index 90081954..a17c2f3e 100644 --- a/examples/erc20-permit/Cargo.toml +++ b/examples/erc20-permit/Cargo.toml @@ -10,7 +10,6 @@ version.workspace = true openzeppelin-stylus.workspace = true alloy-primitives = { workspace = true, features = ["tiny-keccak"] } stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/examples/erc20/Cargo.toml b/examples/erc20/Cargo.toml index 037d3be9..3f89418b 100644 --- a/examples/erc20/Cargo.toml +++ b/examples/erc20/Cargo.toml @@ -10,7 +10,6 @@ version.workspace = true openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/examples/erc721-consecutive/Cargo.toml b/examples/erc721-consecutive/Cargo.toml index 08b7f5b4..4616b73a 100644 --- a/examples/erc721-consecutive/Cargo.toml +++ b/examples/erc721-consecutive/Cargo.toml @@ -11,7 +11,6 @@ openzeppelin-stylus.workspace = true alloy-primitives.workspace = true alloy-sol-types.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/examples/erc721-metadata/Cargo.toml b/examples/erc721-metadata/Cargo.toml index 62b1f298..50c22793 100644 --- a/examples/erc721-metadata/Cargo.toml +++ b/examples/erc721-metadata/Cargo.toml @@ -10,7 +10,6 @@ version.workspace = true openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/examples/erc721/Cargo.toml b/examples/erc721/Cargo.toml index c11254dc..1f6f916d 100644 --- a/examples/erc721/Cargo.toml +++ b/examples/erc721/Cargo.toml @@ -10,7 +10,6 @@ version.workspace = true openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/examples/merkle-proofs/Cargo.toml b/examples/merkle-proofs/Cargo.toml index e741ccbe..02c229e4 100644 --- a/examples/merkle-proofs/Cargo.toml +++ b/examples/merkle-proofs/Cargo.toml @@ -11,7 +11,6 @@ openzeppelin-crypto.workspace = true alloy-primitives.workspace = true alloy-sol-types.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [features] diff --git a/examples/merkle-proofs/src/lib.rs b/examples/merkle-proofs/src/lib.rs index 2fab9264..a442fb16 100644 --- a/examples/merkle-proofs/src/lib.rs +++ b/examples/merkle-proofs/src/lib.rs @@ -8,10 +8,10 @@ use openzeppelin_crypto::{ merkle::{self, Verifier}, KeccakBuilder, }; -use stylus_proc::SolidityError; use stylus_sdk::{ alloy_sol_types::sol, prelude::{entrypoint, public, sol_storage}, + stylus_proc::SolidityError, }; #[global_allocator] diff --git a/examples/ownable/Cargo.toml b/examples/ownable/Cargo.toml index 6ac97fa3..f60e1075 100644 --- a/examples/ownable/Cargo.toml +++ b/examples/ownable/Cargo.toml @@ -10,7 +10,6 @@ version = "0.0.0" openzeppelin-stylus.workspace = true alloy-primitives.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true mini-alloc.workspace = true [dev-dependencies] diff --git a/lib/motsu-proc/Cargo.toml b/lib/motsu-proc/Cargo.toml index 4d009022..99cbdb6d 100644 --- a/lib/motsu-proc/Cargo.toml +++ b/lib/motsu-proc/Cargo.toml @@ -18,7 +18,6 @@ motsu.workspace = true alloy-primitives.workspace = true alloy-sol-types.workspace = true stylus-sdk.workspace = true -stylus-proc.workspace = true [lib] proc-macro = true