From ea7ef0ef61c8173a3744aab660eb2a899c2a6ff5 Mon Sep 17 00:00:00 2001 From: r4bbit <445106+0x-r4bbit@users.noreply.github.com> Date: Fri, 6 Oct 2023 10:21:27 +0200 Subject: [PATCH] feat: introduce custom `StatusMint()` events (#18) --- .gas-snapshot | 21 +++++++++++---------- contracts/tokens/BaseToken.sol | 10 ++++++++++ contracts/tokens/CommunityERC20.sol | 10 ++++++++++ test/CollectibleV1.t.sol | 6 ++++++ test/CommunityERC20.t.sol | 22 ++++++++++++++++++++++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index ed3bd99..676e4df 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -5,8 +5,8 @@ AddEntryTest:test_RevertWhen_SenderIsNotTokenDeployer() (gas: 14827) CollectibleV1Test:test_Deployment() (gas: 36386) CommunityERC20Test:test_Deployment() (gas: 27659) CommunityTokenDeployerTest:test_Deployment() (gas: 14805) -CreateTest:test_Create() (gas: 2251272) -CreateTest:test_Create() (gas: 2548179) +CreateTest:test_Create() (gas: 2269916) +CreateTest:test_Create() (gas: 2568994) CreateTest:test_RevertWhen_InvalidOwnerTokenAddress() (gas: 15523) CreateTest:test_RevertWhen_InvalidReceiverAddress() (gas: 15656) CreateTest:test_RevertWhen_InvalidSignerPublicKey() (gas: 17057) @@ -16,14 +16,14 @@ CreateTest:test_RevertWhen_SenderIsNotTokenDeployer() (gas: 16421) CreateTest:test_RevertWhen_SenderIsNotTokenDeployer() (gas: 16524) DeployContracts:test() (gas: 120) DeployOwnerAndMasterToken:test() (gas: 120) -DeployTest:test_Deploy() (gas: 4872105) +DeployTest:test_Deploy() (gas: 4911563) DeployTest:test_Deployment() (gas: 14947) -DeployTest:test_RevertWhen_AlreadyDeployed() (gas: 4868335) +DeployTest:test_RevertWhen_AlreadyDeployed() (gas: 4907793) DeployTest:test_RevertWhen_InvalidCommunityAddress() (gas: 51385) DeployTest:test_RevertWhen_InvalidDeployerAddress() (gas: 55272) DeployTest:test_RevertWhen_InvalidDeploymentSignature() (gas: 65617) DeployTest:test_RevertWhen_InvalidSignerPublicKey() (gas: 53433) -DeployTest:test_RevertWhen_InvalidTokenMetadata() (gas: 2671695) +DeployTest:test_RevertWhen_InvalidTokenMetadata() (gas: 2692510) DeploymentTest:test_Deployment() (gas: 14671) DeploymentTest:test_Deployment() (gas: 14671) DeploymentTest:test_Deployment() (gas: 17295) @@ -31,16 +31,17 @@ GetEntryTest:test_ReturnZeroAddressIfEntryDoesNotExist() (gas: 11906) MintToTest:test_Deployment() (gas: 27681) MintToTest:test_Deployment() (gas: 36386) MintToTest:test_Deployment() (gas: 83220) -MintToTest:test_MintTo() (gas: 506888) +MintToTest:test_MintTo() (gas: 178173) +MintToTest:test_MintTo() (gas: 526242) MintToTest:test_RevertWhen_AddressesAndAmountsAreNotEqualLength() (gas: 29695) MintToTest:test_RevertWhen_MaxSupplyIsReached() (gas: 20653) -MintToTest:test_RevertWhen_MaxSupplyIsReached() (gas: 502655) -MintToTest:test_RevertWhen_MaxSupplyReached() (gas: 128905) +MintToTest:test_RevertWhen_MaxSupplyIsReached() (gas: 511039) +MintToTest:test_RevertWhen_MaxSupplyReached() (gas: 134821) MintToTest:test_RevertWhen_SenderIsNotOwner() (gas: 31544) OwnerTokenTest:test_Deployment() (gas: 83220) RemoteBurnTest:test_Deployment() (gas: 36386) RemoteBurnTest:test_Deployment() (gas: 83242) -RemoteBurnTest:test_RemoteBurn() (gas: 450780) +RemoteBurnTest:test_RemoteBurn() (gas: 459164) RemoteBurnTest:test_RevertWhen_RemoteBurn() (gas: 14768) RemoteBurnTest:test_RevertWhen_SenderIsNotOwner() (gas: 20379) SetCommunityTokenDeployerAddressTest:test_RevertWhen_InvalidTokenDeployerAddress() (gas: 12941) @@ -57,7 +58,7 @@ SetMasterTokenFactoryAddressTest:test_SetOwnerTokenFactoryAddress() (gas: 22861) SetMaxSupplyTest:test_Deployment() (gas: 27659) SetMaxSupplyTest:test_Deployment() (gas: 83242) SetMaxSupplyTest:test_RevertWhen_CalledBecauseMaxSupplyIsLocked() (gas: 14327) -SetMaxSupplyTest:test_RevertWhen_MaxSupplyLowerThanTotalSupply() (gas: 155732) +SetMaxSupplyTest:test_RevertWhen_MaxSupplyLowerThanTotalSupply() (gas: 163620) SetMaxSupplyTest:test_RevertWhen_SenderIsNotOwner() (gas: 12527) SetMaxSupplyTest:test_RevertWhen_SenderIsNotOwner() (gas: 21402) SetMaxSupplyTest:test_SetMaxSupply() (gas: 23955) diff --git a/contracts/tokens/BaseToken.sol b/contracts/tokens/BaseToken.sol index f9019e0..7ff2e0b 100644 --- a/contracts/tokens/BaseToken.sol +++ b/contracts/tokens/BaseToken.sol @@ -16,6 +16,15 @@ abstract contract BaseToken is Context, ERC721Enumerable, CommunityOwnable { error BaseToken_NotRemoteBurnable(); error BaseToken_NotTransferable(); + /// @notice Emits a custom mint event for Status applications to listen to + /// @dev This is doubling the {Transfer} event from ERC721 but we need to emit this + /// so Status applications have a way to easily distinguish between transactions that have + /// a similar event footprint but are semantically different. + /// @param from The address that minted the token + /// @param to The address that received the token + /// @param tokenId The token ID that was minted + event StatusMint(address indexed from, address indexed to, uint256 indexed tokenId); + // State variables Counters.Counter private _tokenIdTracker; @@ -119,6 +128,7 @@ abstract contract BaseToken is Context, ERC721Enumerable, CommunityOwnable { // can be burned so we use a separate counter. for (uint256 i = 0; i < addresses.length; i++) { _safeMint(addresses[i], _tokenIdTracker.current(), ""); + emit StatusMint(address(0), addresses[i], _tokenIdTracker.current()); _tokenIdTracker.increment(); } } diff --git a/contracts/tokens/CommunityERC20.sol b/contracts/tokens/CommunityERC20.sol index 20416bd..a94cb26 100644 --- a/contracts/tokens/CommunityERC20.sol +++ b/contracts/tokens/CommunityERC20.sol @@ -11,6 +11,15 @@ contract CommunityERC20 is Context, Ownable, ERC20, CommunityOwnable { error CommunityERC20_MaxSupplyReached(); error CommunityERC20_MismatchingAddressesAndAmountsLengths(); + /// @notice Emits a custom mint event for Status applications to listen to + /// @dev This is doubling the {Transfer} event from ERC20 but we need to emit this + /// so Status applications have a way to easily distinguish between transactions that have + /// a similar event footprint but are semantically different. + /// @param from The address that minted the token + /// @param to The address that received the token + /// @param amount The amount that was minted + event StatusMint(address indexed from, address indexed to, uint256 indexed amount); + /** * If we want unlimited total supply we should set maxSupply to 2^256-1. */ @@ -60,6 +69,7 @@ contract CommunityERC20 is Context, Ownable, ERC20, CommunityOwnable { revert CommunityERC20_MaxSupplyReached(); } _mint(addresses[i], amount); + emit StatusMint(address(0), addresses[i], amount); } } diff --git a/test/CollectibleV1.t.sol b/test/CollectibleV1.t.sol index fba2a6e..dab5974 100644 --- a/test/CollectibleV1.t.sol +++ b/test/CollectibleV1.t.sol @@ -56,6 +56,8 @@ contract CollectibleV1Test is Test { } contract MintToTest is CollectibleV1Test { + event StatusMint(address indexed from, address indexed to, uint256 indexed tokenId); + function setUp() public virtual override { CollectibleV1Test.setUp(); } @@ -84,6 +86,10 @@ contract MintToTest is CollectibleV1Test { assertEq(collectibleV1.balanceOf(accounts[i]), 0); } vm.prank(deployer); + for (uint8 i = 0; i < length; i++) { + vm.expectEmit(true, true, true, true); + emit StatusMint(address(0), accounts[i], i); + } collectibleV1.mintTo(accounts); for (uint8 i = 0; i < length; i++) { assertEq(collectibleV1.balanceOf(accounts[i]), 1); diff --git a/test/CommunityERC20.t.sol b/test/CommunityERC20.t.sol index de20eb4..7efd11a 100644 --- a/test/CommunityERC20.t.sol +++ b/test/CommunityERC20.t.sol @@ -84,6 +84,8 @@ contract SetMaxSupplyTest is CommunityERC20Test { } contract MintToTest is CommunityERC20Test { + event StatusMint(address indexed from, address indexed to, uint256 indexed amount); + function setUp() public virtual override { CommunityERC20Test.setUp(); } @@ -110,4 +112,24 @@ contract MintToTest is CommunityERC20Test { vm.prank(deployer); communityToken.mintTo(accounts, amounts); } + + function test_MintTo() public { + uint256[] memory amounts = new uint256[](4); + amounts[0] = 50; + amounts[1] = 25; + amounts[2] = 20; + amounts[3] = 5; + + vm.startPrank(deployer); + for (uint8 i = 0; i < accounts.length; i++) { + vm.expectEmit(true, true, true, true); + emit StatusMint(address(0), accounts[i], amounts[i]); + } + communityToken.mintTo(accounts, amounts); + + assertEq(communityToken.balanceOf(accounts[0]), 50); + assertEq(communityToken.balanceOf(accounts[1]), 25); + assertEq(communityToken.balanceOf(accounts[2]), 20); + assertEq(communityToken.balanceOf(accounts[3]), 5); + } }