From d5e3d566d8af7eeae65588c6f60a6091809081c8 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 3 Dec 2024 14:33:00 +0100 Subject: [PATCH 01/17] feat: add Pausable to Erc1155 Example --- examples/erc1155/src/constructor.sol | 6 ++-- examples/erc1155/src/lib.rs | 42 ++++++++++++++++++++++++---- examples/erc1155/tests/abi/mod.rs | 4 ++- examples/erc1155/tests/erc1155.rs | 4 +++ 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/examples/erc1155/src/constructor.sol b/examples/erc1155/src/constructor.sol index 08dd31f1a..5f6ed4782 100644 --- a/examples/erc1155/src/constructor.sol +++ b/examples/erc1155/src/constructor.sol @@ -4,10 +4,12 @@ pragma solidity ^0.8.24; contract Erc1155Example { mapping(address => mapping(uint256 => uint256)) private _balanceOf; mapping(address => mapping(address => bool)) private _isApprovedForAll; - + string private _uri; - + bool _paused; + constructor(string memory uri_) { _uri = uri_; + _paused = false; } } diff --git a/examples/erc1155/src/lib.rs b/examples/erc1155/src/lib.rs index 68dfc5d36..1e5fedd1b 100644 --- a/examples/erc1155/src/lib.rs +++ b/examples/erc1155/src/lib.rs @@ -7,9 +7,9 @@ use alloy_primitives::{Address, FixedBytes, U256}; use openzeppelin_stylus::{ token::erc1155::{ extensions::{Erc1155MetadataUri, IErc1155Burnable}, - Erc1155, + Erc1155, IErc1155, }, - utils::introspection::erc165::IErc165, + utils::{introspection::erc165::IErc165, Pausable}, }; use stylus_sdk::{ abi::Bytes, @@ -23,11 +23,13 @@ sol_storage! { Erc1155 erc1155; #[borrow] Erc1155MetadataUri metadata_uri; + #[borrow] + Pausable pausable; } } #[public] -#[inherit(Erc1155, Erc1155MetadataUri)] +#[inherit(Erc1155, Erc1155MetadataUri, Pausable)] impl Erc1155Example { pub fn mint( &mut self, @@ -36,6 +38,7 @@ impl Erc1155Example { amount: U256, data: Bytes, ) -> Result<(), Vec> { + self.pausable.when_not_paused()?; self.erc1155._mint(to, token_id, amount, &data)?; Ok(()) } @@ -47,6 +50,7 @@ impl Erc1155Example { amounts: Vec, data: Bytes, ) -> Result<(), Vec> { + self.pausable.when_not_paused()?; self.erc1155._mint_batch(to, token_ids, amounts, &data)?; Ok(()) } @@ -65,26 +69,54 @@ impl Erc1155Example { Ok(()) } - fn burn( + pub fn burn( &mut self, account: Address, token_id: U256, value: U256, ) -> Result<(), Vec> { + self.pausable.when_not_paused()?; self.erc1155.burn(account, token_id, value)?; Ok(()) } - fn burn_batch( + pub fn burn_batch( &mut self, account: Address, token_ids: Vec, values: Vec, ) -> Result<(), Vec> { + self.pausable.when_not_paused()?; self.erc1155.burn_batch(account, token_ids, values)?; Ok(()) } + pub fn safe_transfer_from( + &mut self, + from: Address, + to: Address, + id: U256, + value: U256, + data: Bytes, + ) -> Result<(), Vec> { + self.pausable.when_not_paused()?; + self.erc1155.safe_transfer_from(from, to, id, value, data)?; + Ok(()) + } + + fn safe_batch_transfer_from( + &mut self, + from: Address, + to: Address, + ids: Vec, + values: Vec, + data: Bytes, + ) -> Result<(), Vec> { + self.pausable.when_not_paused()?; + self.erc1155.safe_batch_transfer_from(from, to, ids, values, data)?; + Ok(()) + } + pub fn supports_interface(interface_id: FixedBytes<4>) -> bool { Erc1155::supports_interface(interface_id) || Erc1155MetadataUri::supports_interface(interface_id) diff --git a/examples/erc1155/tests/abi/mod.rs b/examples/erc1155/tests/abi/mod.rs index 909a08bbd..4d3b5b26f 100644 --- a/examples/erc1155/tests/abi/mod.rs +++ b/examples/erc1155/tests/abi/mod.rs @@ -16,8 +16,10 @@ sol!( function burn(address account, uint256 id, uint256 value) external; function burnBatch(address account, uint256[] memory ids, uint256[] memory values) external; function uri(uint256 id) external view returns (string memory uri); - function supportsInterface(bytes4 interfaceId) external view returns (bool); + function paused() external view returns (bool paused); + function pause() external; + function unpause() external; error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); error ERC1155InvalidOperator(address operator); diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index 612e23b04..d30766225 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -52,6 +52,10 @@ async fn constructs(alice: Account) -> eyre::Result<()> { let uri = contract.uri(U256::from(1)).call().await?.uri; assert_eq!(URI, uri); + let paused = contract.paused().call().await?.paused; + + assert_eq!(false, paused); + Ok(()) } From 70b48bb536d9c97abc7dd442fc39135033bf79e1 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 3 Dec 2024 14:57:41 +0100 Subject: [PATCH 02/17] docs: add Antora docs for Erc1155Pausable extension. --- docs/modules/ROOT/pages/erc1155-pausable.adoc | 129 ++++++++++++++++++ docs/modules/ROOT/pages/erc1155.adoc | 3 + examples/erc1155/src/lib.rs | 2 +- 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 docs/modules/ROOT/pages/erc1155-pausable.adoc diff --git a/docs/modules/ROOT/pages/erc1155-pausable.adoc b/docs/modules/ROOT/pages/erc1155-pausable.adoc new file mode 100644 index 000000000..b7cba3651 --- /dev/null +++ b/docs/modules/ROOT/pages/erc1155-pausable.adoc @@ -0,0 +1,129 @@ += ERC-1155 Pausable + +ERC1155 token with pausable token transfers, minting, and burning. + +Useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug. + +[[usage]] +== Usage + +In order to make your ERC1155 token `pausable`, you need to use the https://docs.rs/openzeppelin-stylus/0.2.0-alpha.2/openzeppelin_stylus/utils/pausable/index.html[`Pausable`] contract and apply its mechanisms to ERC1155 token functions as follows: + +[source,rust] +---- +use openzeppelin_stylus::{ + token::erc1155::{Erc1155, IErc1155}, + utils::Pausable, +}; + +sol_storage! { + #[entrypoint] + struct Erc1155Example { + #[borrow] + Erc1155 erc1155; + #[borrow] + Pausable pausable; + } +} + +#[public] +#[inherit(Erc1155, Pausable)] +impl Erc1155Example { + pub fn mint( + &mut self, + to: Address, + token_id: U256, + amount: U256, + data: Bytes, + ) -> Result<(), Vec> { + // ... + self.pausable.when_not_paused()?; + // ... + self.erc1155._mint(to, token_id, amount, &data)?; + Ok(()) + } + + pub fn mint_batch( + &mut self, + to: Address, + token_ids: Vec, + amounts: Vec, + data: Bytes, + ) -> Result<(), Vec> { + // ... + self.pausable.when_not_paused()?; + // ... + self.erc1155._mint_batch(to, token_ids, amounts, &data)?; + Ok(()) + } + + pub fn burn( + &mut self, + account: Address, + token_id: U256, + value: U256, + ) -> Result<(), Vec> { + // ... + self.pausable.when_not_paused()?; + // ... + self.erc1155.burn(account, token_id, value)?; + Ok(()) + } + + pub fn burn_batch( + &mut self, + account: Address, + token_ids: Vec, + values: Vec, + ) -> Result<(), Vec> { + // ... + self.pausable.when_not_paused()?; + // ... + self.erc1155.burn_batch(account, token_ids, values)?; + Ok(()) + } + + pub fn safe_transfer_from( + &mut self, + from: Address, + to: Address, + id: U256, + value: U256, + data: Bytes, + ) -> Result<(), Vec> { + // ... + self.pausable.when_not_paused()?; + // ... + self.erc1155.safe_transfer_from(from, to, id, value, data)?; + Ok(()) + } + + pub fn safe_batch_transfer_from( + &mut self, + from: Address, + to: Address, + ids: Vec, + values: Vec, + data: Bytes, + ) -> Result<(), Vec> { + // ... + self.pausable.when_not_paused()?; + // ... + self.erc1155.safe_batch_transfer_from(from, to, ids, values, data)?; + Ok(()) + } +} +---- + +Additionally, you need to ensure proper initialization during xref:deploy.adoc[contract deployment]. Make sure to include the following code in your Solidity Constructor: + +[source,solidity] +---- +contract Erc1155Example { + bool private _paused; + + constructor() { + _paused = false; + } +} +---- diff --git a/docs/modules/ROOT/pages/erc1155.adoc b/docs/modules/ROOT/pages/erc1155.adoc index cbe5ccc08..f67e5a224 100644 --- a/docs/modules/ROOT/pages/erc1155.adoc +++ b/docs/modules/ROOT/pages/erc1155.adoc @@ -9,3 +9,6 @@ Additionally, there are multiple custom extensions, including: * xref:erc1155-burnable.adoc[ERC-1155 Burnable]: Optional Burnable extension of the ERC-1155 standard. * xref:erc1155-metadata-uri.adoc[ERC-1155 Metadata URI]: Optional extension that adds a token metadata URI. +* xref:erc1155-pausable.adoc[ERC-1155 Pausable]: A primitive to pause contract operation like token transfers, minting and burning. + + diff --git a/examples/erc1155/src/lib.rs b/examples/erc1155/src/lib.rs index 1e5fedd1b..72f7be6f7 100644 --- a/examples/erc1155/src/lib.rs +++ b/examples/erc1155/src/lib.rs @@ -104,7 +104,7 @@ impl Erc1155Example { Ok(()) } - fn safe_batch_transfer_from( + pub fn safe_batch_transfer_from( &mut self, from: Address, to: Address, From fafa1f5365ae1edc55e24ed1e5c0b1b63e43865f Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 3 Dec 2024 15:22:19 +0100 Subject: [PATCH 03/17] chore: remove redundant fn from Erc1155 example --- docs/modules/ROOT/pages/erc1155.adoc | 2 -- examples/erc1155/src/lib.rs | 14 -------------- 2 files changed, 16 deletions(-) diff --git a/docs/modules/ROOT/pages/erc1155.adoc b/docs/modules/ROOT/pages/erc1155.adoc index f67e5a224..717b8ecce 100644 --- a/docs/modules/ROOT/pages/erc1155.adoc +++ b/docs/modules/ROOT/pages/erc1155.adoc @@ -10,5 +10,3 @@ Additionally, there are multiple custom extensions, including: * xref:erc1155-burnable.adoc[ERC-1155 Burnable]: Optional Burnable extension of the ERC-1155 standard. * xref:erc1155-metadata-uri.adoc[ERC-1155 Metadata URI]: Optional extension that adds a token metadata URI. * xref:erc1155-pausable.adoc[ERC-1155 Pausable]: A primitive to pause contract operation like token transfers, minting and burning. - - diff --git a/examples/erc1155/src/lib.rs b/examples/erc1155/src/lib.rs index 72f7be6f7..67af5c6bf 100644 --- a/examples/erc1155/src/lib.rs +++ b/examples/erc1155/src/lib.rs @@ -55,20 +55,6 @@ impl Erc1155Example { Ok(()) } - pub fn set_operator_approvals( - &mut self, - owner: Address, - operator: Address, - approved: bool, - ) -> Result<(), Vec> { - self.erc1155 - ._operator_approvals - .setter(owner) - .setter(operator) - .set(approved); - Ok(()) - } - pub fn burn( &mut self, account: Address, From 1e35736c4d84f261b5b7927278927cc302c558d0 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 3 Dec 2024 17:57:53 +0100 Subject: [PATCH 04/17] test: add E2E tests for Erc1155Pausable extension --- examples/erc1155/src/constructor.sol | 2 +- examples/erc1155/src/lib.rs | 8 + examples/erc1155/tests/abi/mod.rs | 7 + examples/erc1155/tests/erc1155.rs | 288 +++++++++++++++++++++++++++ 4 files changed, 304 insertions(+), 1 deletion(-) diff --git a/examples/erc1155/src/constructor.sol b/examples/erc1155/src/constructor.sol index 5f6ed4782..7f46e6e50 100644 --- a/examples/erc1155/src/constructor.sol +++ b/examples/erc1155/src/constructor.sol @@ -6,7 +6,7 @@ contract Erc1155Example { mapping(address => mapping(address => bool)) private _isApprovedForAll; string private _uri; - bool _paused; + bool private _paused; constructor(string memory uri_) { _uri = uri_; diff --git a/examples/erc1155/src/lib.rs b/examples/erc1155/src/lib.rs index 67af5c6bf..4c2a11ad7 100644 --- a/examples/erc1155/src/lib.rs +++ b/examples/erc1155/src/lib.rs @@ -107,4 +107,12 @@ impl Erc1155Example { Erc1155::supports_interface(interface_id) || Erc1155MetadataUri::supports_interface(interface_id) } + + pub fn pause(&mut self) -> Result<(), Vec> { + self.pausable.pause().map_err(|e| e.into()) + } + + pub fn unpause(&mut self) -> Result<(), Vec> { + self.pausable.unpause().map_err(|e| e.into()) + } } diff --git a/examples/erc1155/tests/abi/mod.rs b/examples/erc1155/tests/abi/mod.rs index 4d3b5b26f..804effd93 100644 --- a/examples/erc1155/tests/abi/mod.rs +++ b/examples/erc1155/tests/abi/mod.rs @@ -27,6 +27,8 @@ sol!( error ERC1155InvalidReceiver(address receiver); error ERC1155MissingApprovalForAll(address operator, address owner); error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); + error EnforcedPause(); + error ExpectedPause(); #[derive(Debug, PartialEq)] event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); @@ -36,5 +38,10 @@ sol!( event ApprovalForAll(address indexed account, address indexed operator, bool approved); #[derive(Debug, PartialEq)] event URI(string value, uint256 indexed id); + #[derive(Debug, PartialEq)] + event Paused(address account); + #[derive(Debug, PartialEq)] + event Unpaused(address account); + } ); diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index d30766225..d30c8d79d 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -2177,3 +2177,291 @@ async fn support_interface(alice: Account) -> eyre::Result<()> { Ok(()) } + +// ============================================================================ +// Integration Tests: ERC-1155 Pausable Extension +// ============================================================================ + +#[e2e::test] +async fn pauses(alice: Account) -> eyre::Result<()> { + let contract_addr = alice.as_deployer().deploy().await?.address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let receipt = receipt!(contract.pause())?; + + assert!(receipt.emits(Erc1155::Paused { account: alice.address() })); + + let paused = contract.paused().call().await?.paused; + + assert!(paused); + + Ok(()) +} + +#[e2e::test] +async fn unpauses(alice: Account) -> eyre::Result<()> { + let contract_addr = alice.as_deployer().deploy().await?.address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let _ = watch!(contract.pause())?; + + let receipt = receipt!(contract.unpause())?; + + assert!(receipt.emits(Erc1155::Unpaused { account: alice.address() })); + + let paused = contract.paused().call().await?.paused; + + assert_eq!(false, paused); + + Ok(()) +} + +#[e2e::test] +async fn mint_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let alice_addr = alice.address(); + let token_id = random_token_ids(1)[0]; + let value = random_values(1)[0]; + + let _ = watch!(contract.pause())?; + + let err = send!(contract.mint( + alice_addr, + token_id, + value, + vec![0, 1, 2, 3].into() + )) + .expect_err("should return EnforcedPause"); + + assert!(err.reverted_with(Erc1155::EnforcedPause {})); + + Ok(()) +} + +#[e2e::test] +async fn mint_batch_reverts_in_paused_state( + alice: Account, + bob: Account, + dave: Account, +) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let alice_addr = alice.address(); + let bob_addr = bob.address(); + let dave_addr = dave.address(); + let token_ids = random_token_ids(3); + let values = random_values(3); + + let accounts = vec![alice_addr, bob_addr, dave_addr]; + let _ = watch!(contract.pause())?; + + for account in accounts { + let err = send!(contract.mintBatch( + account, + token_ids.clone(), + values.clone(), + vec![0, 1, 2, 3].into() + )) + .expect_err("should return EnforcedPause"); + + assert!(err.reverted_with(Erc1155::EnforcedPause {})); + } + Ok(()) +} + +#[e2e::test] +async fn burn_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let alice_addr = alice.address(); + let token_ids = random_token_ids(1); + let values = random_values(1); + + let _ = watch!(contract.mint( + alice_addr, + token_ids[0], + values[0], + vec![].into() + )); + + let _ = watch!(contract.pause())?; + + let err = send!(contract.burn(alice_addr, token_ids[0], values[0])) + .expect_err("should return EnforcedPause"); + + assert!(err.reverted_with(Erc1155::EnforcedPause {})); + + Ok(()) +} + +#[e2e::test] +async fn burn_batch_reverts_in_paused_state( + alice: Account, +) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let alice_addr = alice.address(); + let token_ids = random_token_ids(4); + let values = random_values(4); + + let _ = watch!(contract.mintBatch( + alice_addr, + token_ids.clone(), + values.clone(), + vec![].into() + )); + + let _ = watch!(contract.pause())?; + + let err = send!(contract.burnBatch( + alice_addr, + token_ids.clone(), + values.clone() + )) + .expect_err("should return EnforcedPause"); + + assert!(err.reverted_with(Erc1155::EnforcedPause {})); + + Ok(()) +} + +#[e2e::test] +async fn safe_transfer_from_reverts_in_paused_state( + alice: Account, + bob: Account, +) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let alice_addr = alice.address(); + let bob_addr = bob.address(); + let token_id = random_token_ids(1)[0]; + let value = random_values(1)[0]; + let _ = watch!(contract.mint( + alice_addr, + token_id, + value, + vec![0, 1, 2, 3].into() + )); + + let _ = watch!(contract.pause())?; + + let err = send!(contract.safeTransferFrom( + alice_addr, + bob_addr, + token_id, + value, + vec![].into() + )) + .expect_err("should return EnforcedPause"); + + assert!(err.reverted_with(Erc1155::EnforcedPause {})); + + Ok(()) +} + +#[e2e::test] +async fn safe_batch_transfer_from_reverts_in_paused_state( + alice: Account, + bob: Account, +) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract_alice = Erc1155::new(contract_addr, &alice.wallet); + + let alice_addr = alice.address(); + let bob_addr = bob.address(); + let token_ids = random_token_ids(2); + let values = random_values(2); + + let _ = watch!(contract_alice.mintBatch( + alice_addr, + token_ids.clone(), + values.clone(), + vec![].into() + )); + + let _ = watch!(contract_alice.pause())?; + + let err = send!(contract_alice.safeBatchTransferFrom( + alice_addr, + bob_addr, + token_ids.clone(), + values.clone(), + vec![].into() + )) + .expect_err("should return EnforcedPause"); + + assert!(err.reverted_with(Erc1155::EnforcedPause {})); + + Ok(()) +} + +#[e2e::test] +async fn set_approval_for_all_does_not_revert_in_paused_state( + alice: Account, + bob: Account, +) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let alice_addr = alice.address(); + let bob_addr = bob.address(); + + let _ = watch!(contract.pause())?; + + let approved_value = true; + let receipt = + receipt!(contract.setApprovalForAll(bob_addr, approved_value))?; + + assert!(receipt.emits(Erc1155::ApprovalForAll { + account: alice_addr, + operator: bob_addr, + approved: approved_value, + })); + + let Erc1155::isApprovedForAllReturn { approved } = + contract.isApprovedForAll(alice_addr, bob_addr).call().await?; + assert_eq!(approved_value, approved); + + Ok(()) +} From 7d3c9e1cf8582c70f233d163f086159848b67749 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 3 Dec 2024 18:03:07 +0100 Subject: [PATCH 05/17] docs: update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37157c83f..9bbfb8011 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- `Erc1155Pausable`extension. #432 - `VestingWallet` contract. #402 - `Erc1155Burnable` extension. #417 - `Erc1155MetadataUri` extension. #416 From f0497f495b90e158494348d7df7d28a704c6c6c6 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 3 Dec 2024 18:05:53 +0100 Subject: [PATCH 06/17] fix: fix E2E tests for Erc1155Pausable --- examples/erc1155/tests/erc1155.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index d30c8d79d..ca14539c0 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -2184,7 +2184,13 @@ async fn support_interface(alice: Account) -> eyre::Result<()> { #[e2e::test] async fn pauses(alice: Account) -> eyre::Result<()> { - let contract_addr = alice.as_deployer().deploy().await?.address()?; + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); let receipt = receipt!(contract.pause())?; @@ -2200,7 +2206,13 @@ async fn pauses(alice: Account) -> eyre::Result<()> { #[e2e::test] async fn unpauses(alice: Account) -> eyre::Result<()> { - let contract_addr = alice.as_deployer().deploy().await?.address()?; + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + let contract = Erc1155::new(contract_addr, &alice.wallet); let _ = watch!(contract.pause())?; From 9d5f49869f13c9a0f49d292b60b54b5227e6b95d Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Thu, 5 Dec 2024 14:08:33 +0100 Subject: [PATCH 07/17] ref: better formatting Co-authored-by: Nenad --- examples/erc1155/tests/erc1155.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index ca14539c0..5d3f22863 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -2291,6 +2291,7 @@ async fn mint_batch_reverts_in_paused_state( assert!(err.reverted_with(Erc1155::EnforcedPause {})); } + Ok(()) } From b855853097c52bc0443bcc7af725fc512b863636 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Thu, 5 Dec 2024 14:09:15 +0100 Subject: [PATCH 08/17] ref: better expect msg Co-authored-by: Nenad --- examples/erc1155/tests/erc1155.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index 5d3f22863..fa61c7b0f 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -2250,7 +2250,7 @@ async fn mint_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { value, vec![0, 1, 2, 3].into() )) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc1155::EnforcedPause {})); From b5f483c2b5f1aa0fdd77ed50599e04d3e476f8ec Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Thu, 5 Dec 2024 14:09:40 +0100 Subject: [PATCH 09/17] ref: improve tests Co-authored-by: Nenad --- examples/erc1155/tests/erc1155.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index fa61c7b0f..60240faef 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -54,7 +54,7 @@ async fn constructs(alice: Account) -> eyre::Result<()> { let paused = contract.paused().call().await?.paused; - assert_eq!(false, paused); + assert!(!paused); Ok(()) } From b6957dc5e8db91916e23f9d0c20f03eaf528b2eb Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Thu, 5 Dec 2024 14:15:18 +0100 Subject: [PATCH 10/17] docs: improve docs --- docs/modules/ROOT/pages/erc1155-pausable.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/erc1155-pausable.adoc b/docs/modules/ROOT/pages/erc1155-pausable.adoc index b7cba3651..c59dbd2b5 100644 --- a/docs/modules/ROOT/pages/erc1155-pausable.adoc +++ b/docs/modules/ROOT/pages/erc1155-pausable.adoc @@ -1,13 +1,13 @@ = ERC-1155 Pausable -ERC1155 token with pausable token transfers, minting, and burning. +xref:erc1155.adoc[ERC-1155] token with pausable token transfers, minting, and burning. Useful for scenarios such as preventing trades until the end of an evaluation period, or having an emergency switch for freezing all token transfers in the event of a large bug. [[usage]] == Usage -In order to make your ERC1155 token `pausable`, you need to use the https://docs.rs/openzeppelin-stylus/0.2.0-alpha.2/openzeppelin_stylus/utils/pausable/index.html[`Pausable`] contract and apply its mechanisms to ERC1155 token functions as follows: +In order to make your xref:erc1155.adoc[ERC-1155] token `pausable`, you need to use the https://docs.rs/openzeppelin-stylus/0.2.0-alpha.2/openzeppelin_stylus/utils/pausable/index.html[`Pausable`] contract and apply its mechanisms to ERC1155 token functions as follows: [source,rust] ---- From 45d48c2b59d19ba363b450c434dcaeea30495a78 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Fri, 6 Dec 2024 14:23:31 +0100 Subject: [PATCH 11/17] test: add test for reverts on Pausable --- examples/erc1155/tests/erc1155.rs | 46 ++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index 60240faef..0ba1f6516 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -2204,6 +2204,27 @@ async fn pauses(alice: Account) -> eyre::Result<()> { Ok(()) } +#[e2e::test] +async fn pause_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let _ = watch!(contract.pause())?; + + let err = + send!(contract.pause()).expect_err("should return `EnforcedPause`"); + + assert!(err.reverted_with(Erc1155::EnforcedPause {})); + + Ok(()) +} + #[e2e::test] async fn unpauses(alice: Account) -> eyre::Result<()> { let contract_addr = alice @@ -2223,7 +2244,30 @@ async fn unpauses(alice: Account) -> eyre::Result<()> { let paused = contract.paused().call().await?.paused; - assert_eq!(false, paused); + assert!(!paused); + + Ok(()) +} + +#[e2e::test] +async fn unpause_reverts_in_unpaused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + + let contract = Erc1155::new(contract_addr, &alice.wallet); + + let paused = contract.paused().call().await?.paused; + + assert!(!paused); + + let err = + send!(contract.unpause()).expect_err("should return `ExpectedPause`"); + + assert!(err.reverted_with(Erc1155::ExpectedPause {})); Ok(()) } From 8332d26c0c07aa639c36b7fd53f752c47aaa25e3 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Fri, 6 Dec 2024 14:32:25 +0100 Subject: [PATCH 12/17] ref: remove redundant loop in E2E tests for Erc1155::mint_batch --- examples/erc1155/tests/erc1155.rs | 86 +++++++++++++------------------ 1 file changed, 36 insertions(+), 50 deletions(-) diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index 0ba1f6516..7427cd48b 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -354,11 +354,7 @@ async fn errors_when_invalid_receiver_contract_in_mint( } #[e2e::test] -async fn mint_batch( - alice: Account, - bob: Account, - dave: Account, -) -> eyre::Result<()> { +async fn mint_batch(alice: Account) -> eyre::Result<()> { let contract_addr = alice .as_deployer() .with_default_constructor::() @@ -368,42 +364,39 @@ async fn mint_batch( let contract = Erc1155::new(contract_addr, &alice.wallet); let alice_addr = alice.address(); - let bob_addr = bob.address(); - let dave_addr = dave.address(); let token_ids = random_token_ids(3); let values = random_values(3); - let accounts = vec![alice_addr, bob_addr, dave_addr]; + let receipt = receipt!(contract.mintBatch( + alice_addr, + token_ids.clone(), + values.clone(), + vec![0, 1, 2, 3].into() + ))?; - for account in accounts { - let receipt = receipt!(contract.mintBatch( - account, - token_ids.clone(), - values.clone(), - vec![0, 1, 2, 3].into() - ))?; - - assert!(receipt.emits(Erc1155::TransferBatch { - operator: alice_addr, - from: Address::ZERO, - to: account, - ids: token_ids.clone(), - values: values.clone() - })); - - for (token_id, value) in token_ids.iter().zip(values.iter()) { - let Erc1155::balanceOfReturn { balance } = - contract.balanceOf(account, *token_id).call().await?; - assert_eq!(*value, balance); - } - - let Erc1155::balanceOfBatchReturn { balances } = contract - .balanceOfBatch(vec![account, account, account], token_ids.clone()) - .call() - .await?; + assert!(receipt.emits(Erc1155::TransferBatch { + operator: alice_addr, + from: Address::ZERO, + to: alice_addr, + ids: token_ids.clone(), + values: values.clone() + })); - assert_eq!(values, balances); + for (token_id, value) in token_ids.iter().zip(values.iter()) { + let Erc1155::balanceOfReturn { balance } = + contract.balanceOf(alice_addr, *token_id).call().await?; + assert_eq!(*value, balance); } + + let Erc1155::balanceOfBatchReturn { balances } = contract + .balanceOfBatch( + vec![alice_addr, alice_addr, alice_addr], + token_ids.clone(), + ) + .call() + .await?; + + assert_eq!(values, balances); Ok(()) } @@ -2304,8 +2297,6 @@ async fn mint_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { #[e2e::test] async fn mint_batch_reverts_in_paused_state( alice: Account, - bob: Account, - dave: Account, ) -> eyre::Result<()> { let contract_addr = alice .as_deployer() @@ -2316,25 +2307,20 @@ async fn mint_batch_reverts_in_paused_state( let contract = Erc1155::new(contract_addr, &alice.wallet); let alice_addr = alice.address(); - let bob_addr = bob.address(); - let dave_addr = dave.address(); let token_ids = random_token_ids(3); let values = random_values(3); - let accounts = vec![alice_addr, bob_addr, dave_addr]; let _ = watch!(contract.pause())?; - for account in accounts { - let err = send!(contract.mintBatch( - account, - token_ids.clone(), - values.clone(), - vec![0, 1, 2, 3].into() - )) - .expect_err("should return EnforcedPause"); + let err = send!(contract.mintBatch( + alice_addr, + token_ids.clone(), + values.clone(), + vec![0, 1, 2, 3].into() + )) + .expect_err("should return EnforcedPause"); - assert!(err.reverted_with(Erc1155::EnforcedPause {})); - } + assert!(err.reverted_with(Erc1155::EnforcedPause {})); Ok(()) } From aa7be9f2afd4a7609732e2401276f4ac12ca5138 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Fri, 6 Dec 2024 14:47:21 +0100 Subject: [PATCH 13/17] test: add missing E2E tests for Erc20Pausable --- examples/erc20/tests/erc20.rs | 76 ++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/examples/erc20/tests/erc20.rs b/examples/erc20/tests/erc20.rs index a61393c0a..e8f2f0dfc 100644 --- a/examples/erc20/tests/erc20.rs +++ b/examples/erc20/tests/erc20.rs @@ -49,18 +49,20 @@ async fn constructs(alice: Account) -> Result<()> { .address()?; let contract = Erc20::new(contract_addr, &alice.wallet); - let Erc20::nameReturn { name } = contract.name().call().await?; - let Erc20::symbolReturn { symbol } = contract.symbol().call().await?; - let Erc20::capReturn { cap } = contract.cap().call().await?; - let Erc20::decimalsReturn { decimals } = contract.decimals().call().await?; - let Erc20::totalSupplyReturn { totalSupply: total_supply } = - contract.totalSupply().call().await?; + let name = contract.name().call().await?.name; + let symbol = contract.symbol().call().await?.symbol; + let cap = contract.cap().call().await?.cap; + let decimals = contract.decimals().call().await?.decimals; + let total_supply = contract.totalSupply().call().await?.totalSupply; + let paused = contract.paused().call().await?.paused; assert_eq!(name, TOKEN_NAME.to_owned()); assert_eq!(symbol, TOKEN_SYMBOL.to_owned()); assert_eq!(cap, CAP); assert_eq!(decimals, 10); assert_eq!(total_supply, U256::ZERO); + assert!(!paused); + Ok(()) } @@ -1057,9 +1059,30 @@ async fn pauses(alice: Account) -> eyre::Result<()> { assert!(receipt.emits(Erc20::Paused { account: alice.address() })); - let Erc20::pausedReturn { paused } = contract.paused().call().await?; + let paused = contract.paused().call().await?.paused; + + assert!(paused); + + Ok(()) +} + +#[e2e::test] +async fn pause_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + + let contract = Erc20::new(contract_addr, &alice.wallet); + + let _ = watch!(contract.pause())?; + + let err = + send!(contract.pause()).expect_err("should return `EnforcedPause`"); - assert_eq!(true, paused); + assert!(err.reverted_with(Erc20::EnforcedPause {})); Ok(()) } @@ -1080,9 +1103,32 @@ async fn unpauses(alice: Account) -> eyre::Result<()> { assert!(receipt.emits(Erc20::Unpaused { account: alice.address() })); - let Erc20::pausedReturn { paused } = contract.paused().call().await?; + let paused = contract.paused().call().await?.paused; + + assert!(!paused); + + Ok(()) +} + +#[e2e::test] +async fn unpause_reverts_in_unpaused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice + .as_deployer() + .with_default_constructor::() + .deploy() + .await? + .address()?; + + let contract = Erc20::new(contract_addr, &alice.wallet); + + let paused = contract.paused().call().await?.paused; + + assert!(!paused); + + let err = + send!(contract.unpause()).expect_err("should return `ExpectedPause`"); - assert_eq!(false, paused); + assert!(err.reverted_with(Erc20::ExpectedPause {})); Ok(()) } @@ -1111,7 +1157,7 @@ async fn error_when_burn_in_paused_state(alice: Account) -> Result<()> { let _ = watch!(contract.pause())?; let err = - send!(contract.burn(value)).expect_err("should return EnforcedPause"); + send!(contract.burn(value)).expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc20::EnforcedPause {})); let Erc20::balanceOfReturn { balance } = @@ -1162,7 +1208,7 @@ async fn error_when_burn_from_in_paused_state( let _ = watch!(contract_alice.pause())?; let err = send!(contract_bob.burnFrom(alice_addr, value)) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc20::EnforcedPause {})); let Erc20::balanceOfReturn { balance: alice_balance } = @@ -1204,7 +1250,7 @@ async fn error_when_mint_in_paused_state(alice: Account) -> Result<()> { let _ = watch!(contract.pause())?; let err = send!(contract.mint(alice_addr, uint!(1_U256))) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc20::EnforcedPause {})); let Erc20::balanceOfReturn { balance } = @@ -1246,7 +1292,7 @@ async fn error_when_transfer_in_paused_state( let _ = watch!(contract_alice.pause())?; let err = send!(contract_alice.transfer(bob_addr, uint!(1_U256))) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc20::EnforcedPause {})); let Erc20::balanceOfReturn { balance: alice_balance } = @@ -1297,7 +1343,7 @@ async fn error_when_transfer_from(alice: Account, bob: Account) -> Result<()> { let err = send!(contract_bob.transferFrom(alice_addr, bob_addr, uint!(1_U256))) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc20::EnforcedPause {})); let Erc20::balanceOfReturn { balance: alice_balance } = From 379d419417e52fc8f312d5d6215b44b1ae20c0ef Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Fri, 6 Dec 2024 14:51:04 +0100 Subject: [PATCH 14/17] test: add missing E2E tests for Erc721Pausable --- examples/erc721/tests/erc721.rs | 48 ++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/examples/erc721/tests/erc721.rs b/examples/erc721/tests/erc721.rs index 8823e1bc0..82e21c73e 100644 --- a/examples/erc721/tests/erc721.rs +++ b/examples/erc721/tests/erc721.rs @@ -22,9 +22,9 @@ async fn constructs(alice: Account) -> eyre::Result<()> { let contract_addr = alice.as_deployer().deploy().await?.address()?; let contract = Erc721::new(contract_addr, &alice.wallet); - let Erc721::pausedReturn { paused } = contract.paused().call().await?; + let paused = contract.paused().call().await?.paused; - assert_eq!(false, paused); + assert!(!paused); Ok(()) } @@ -1374,6 +1374,22 @@ async fn pauses(alice: Account) -> eyre::Result<()> { Ok(()) } +#[e2e::test] +async fn pause_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice.as_deployer().deploy().await?.address()?; + + let contract = Erc721::new(contract_addr, &alice.wallet); + + let _ = watch!(contract.pause())?; + + let err = + send!(contract.pause()).expect_err("should return `EnforcedPause`"); + + assert!(err.reverted_with(Erc721::EnforcedPause {})); + + Ok(()) +} + #[e2e::test] async fn unpauses(alice: Account) -> eyre::Result<()> { let contract_addr = alice.as_deployer().deploy().await?.address()?; @@ -1392,6 +1408,24 @@ async fn unpauses(alice: Account) -> eyre::Result<()> { Ok(()) } +#[e2e::test] +async fn unpause_reverts_in_unpaused_state(alice: Account) -> eyre::Result<()> { + let contract_addr = alice.as_deployer().deploy().await?.address()?; + + let contract = Erc721::new(contract_addr, &alice.wallet); + + let paused = contract.paused().call().await?.paused; + + assert!(!paused); + + let err = + send!(contract.unpause()).expect_err("should return `ExpectedPause`"); + + assert!(err.reverted_with(Erc721::ExpectedPause {})); + + Ok(()) +} + #[e2e::test] async fn error_when_burn_in_paused_state(alice: Account) -> eyre::Result<()> { let contract_addr = alice.as_deployer().deploy().await?.address()?; @@ -1407,7 +1441,7 @@ async fn error_when_burn_in_paused_state(alice: Account) -> eyre::Result<()> { let _ = watch!(contract.pause()); let err = send!(contract.burn(token_id)) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc721::EnforcedPause {})); @@ -1434,7 +1468,7 @@ async fn error_when_mint_in_paused_state(alice: Account) -> eyre::Result<()> { let _ = watch!(contract.pause()); let err = send!(contract.mint(alice_addr, token_id)) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc721::EnforcedPause {})); let err = contract @@ -1476,7 +1510,7 @@ async fn error_when_transfer_in_paused_state( let _ = watch!(contract.pause()); let err = send!(contract.transferFrom(alice_addr, bob_addr, token_id)) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc721::EnforcedPause {})); let Erc721::ownerOfReturn { ownerOf } = @@ -1518,7 +1552,7 @@ async fn error_when_safe_transfer_in_paused_state( let err = send!(contract.safeTransferFrom_0(alice_addr, bob_addr, token_id)) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc721::EnforcedPause {})); let Erc721::ownerOfReturn { ownerOf } = @@ -1564,7 +1598,7 @@ async fn error_when_safe_transfer_with_data_in_paused_state( token_id, fixed_bytes!("deadbeef").into() )) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc721::EnforcedPause {})); let Erc721::ownerOfReturn { ownerOf } = From c83a94814877741073a63139d559c84180fa2ac7 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Fri, 6 Dec 2024 14:54:09 +0100 Subject: [PATCH 15/17] ref: improve code style in E2E tests --- examples/erc1155/tests/erc1155.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/erc1155/tests/erc1155.rs b/examples/erc1155/tests/erc1155.rs index 7427cd48b..8bed97bd9 100644 --- a/examples/erc1155/tests/erc1155.rs +++ b/examples/erc1155/tests/erc1155.rs @@ -2318,7 +2318,7 @@ async fn mint_batch_reverts_in_paused_state( values.clone(), vec![0, 1, 2, 3].into() )) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc1155::EnforcedPause {})); @@ -2349,7 +2349,7 @@ async fn burn_reverts_in_paused_state(alice: Account) -> eyre::Result<()> { let _ = watch!(contract.pause())?; let err = send!(contract.burn(alice_addr, token_ids[0], values[0])) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc1155::EnforcedPause {})); @@ -2386,7 +2386,7 @@ async fn burn_batch_reverts_in_paused_state( token_ids.clone(), values.clone() )) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc1155::EnforcedPause {})); @@ -2426,7 +2426,7 @@ async fn safe_transfer_from_reverts_in_paused_state( value, vec![].into() )) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc1155::EnforcedPause {})); @@ -2467,7 +2467,7 @@ async fn safe_batch_transfer_from_reverts_in_paused_state( values.clone(), vec![].into() )) - .expect_err("should return EnforcedPause"); + .expect_err("should return `EnforcedPause`"); assert!(err.reverted_with(Erc1155::EnforcedPause {})); From 2438541427fd6bf17a944f7230e74c3f55710c82 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 10 Dec 2024 08:55:22 +0100 Subject: [PATCH 16/17] ref: remove redundant event --- examples/erc1155/tests/abi/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/erc1155/tests/abi/mod.rs b/examples/erc1155/tests/abi/mod.rs index bda0654d1..a5b85f4a3 100644 --- a/examples/erc1155/tests/abi/mod.rs +++ b/examples/erc1155/tests/abi/mod.rs @@ -35,7 +35,6 @@ sol!( event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); #[derive(Debug, PartialEq)] event ApprovalForAll(address indexed account, address indexed operator, bool approved); - event URI(string value, uint256 indexed id); #[derive(Debug, PartialEq)] event Paused(address account); #[derive(Debug, PartialEq)] From 93ca2d642acd84fdf3e57c338a6675f69020d1c1 Mon Sep 17 00:00:00 2001 From: Daniel Bigos Date: Tue, 10 Dec 2024 09:28:05 +0100 Subject: [PATCH 17/17] docs: remove pub from antora docs example --- docs/modules/ROOT/pages/erc1155-pausable.adoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/modules/ROOT/pages/erc1155-pausable.adoc b/docs/modules/ROOT/pages/erc1155-pausable.adoc index c59dbd2b5..4d9dcd633 100644 --- a/docs/modules/ROOT/pages/erc1155-pausable.adoc +++ b/docs/modules/ROOT/pages/erc1155-pausable.adoc @@ -29,7 +29,7 @@ sol_storage! { #[public] #[inherit(Erc1155, Pausable)] impl Erc1155Example { - pub fn mint( + fn mint( &mut self, to: Address, token_id: U256, @@ -43,7 +43,7 @@ impl Erc1155Example { Ok(()) } - pub fn mint_batch( + fn mint_batch( &mut self, to: Address, token_ids: Vec, @@ -57,7 +57,7 @@ impl Erc1155Example { Ok(()) } - pub fn burn( + fn burn( &mut self, account: Address, token_id: U256, @@ -70,7 +70,7 @@ impl Erc1155Example { Ok(()) } - pub fn burn_batch( + fn burn_batch( &mut self, account: Address, token_ids: Vec, @@ -83,7 +83,7 @@ impl Erc1155Example { Ok(()) } - pub fn safe_transfer_from( + fn safe_transfer_from( &mut self, from: Address, to: Address, @@ -98,7 +98,7 @@ impl Erc1155Example { Ok(()) } - pub fn safe_batch_transfer_from( + fn safe_batch_transfer_from( &mut self, from: Address, to: Address,