@artblocks/contracts 1.3.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -312,6 +312,8 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
312
312
  ProjectConfig storage projectConfig = projectConfigs[coreContract][
313
313
  ABHelpers.tokenIdToProjectId(tokenId)
314
314
  ];
315
+ // preallocate memory for auth addresses of each pmpInput
316
+ address[] memory authAddresses = new address[](pmpInputs.length);
315
317
  // assign each pmpInput to the token
316
318
  // @dev pmpInputs processed sequentially in order of input
317
319
  for (uint256 i = 0; i < pmpInputs.length; i++) {
@@ -322,8 +324,8 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
322
324
  ];
323
325
  PMPConfigStorage storage pmpConfigStorage = projectConfig
324
326
  .pmpConfigsStorage[pmpKeyHash];
325
- // validate pmpInput
326
- _validatePMPInputAndAuth({
327
+ // validate pmpInput + record the authenticated address used to configure the pmpInput
328
+ authAddresses[i] = _validatePMPInputAndAuth({
327
329
  tokenId: tokenId,
328
330
  coreContract: coreContract,
329
331
  pmpInput: pmpInput,
@@ -360,7 +362,8 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
360
362
  emit TokenParamsConfigured({
361
363
  coreContract: coreContract,
362
364
  tokenId: tokenId,
363
- pmpInputs: pmpInputs
365
+ pmpInputs: pmpInputs,
366
+ authAddresses: authAddresses
364
367
  });
365
368
  }
366
369
 
@@ -479,20 +482,19 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
479
482
  * @param wallet The wallet address to check.
480
483
  * @param coreContract The address of the core contract to call.
481
484
  * @param tokenId The tokenId of the token to check.
482
- * @return isTokenOwnerOrDelegate True if the wallet is the owner or a delegate of the token,
485
+ * @return isTokenOwnerOrDelegate_ True if the wallet is the owner or a delegate of the token,
483
486
  * false otherwise.
484
487
  */
485
488
  function isTokenOwnerOrDelegate(
486
489
  address wallet,
487
490
  address coreContract,
488
491
  uint256 tokenId
489
- ) external view returns (bool) {
490
- return
491
- _isTokenOwnerOrDelegate({
492
- tokenId: tokenId,
493
- coreContract: coreContract,
494
- sender: wallet
495
- });
492
+ ) external view returns (bool isTokenOwnerOrDelegate_) {
493
+ (isTokenOwnerOrDelegate_, ) = _isTokenOwnerOrDelegate({
494
+ tokenId: tokenId,
495
+ coreContract: coreContract,
496
+ sender: wallet
497
+ });
496
498
  }
497
499
 
498
500
  /**
@@ -707,6 +709,7 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
707
709
  * @param pmpInput The parameter input to validate.
708
710
  * @param pmpConfigStorage The project's configuration storage for this parameter.
709
711
  * @param projectConfigNonce The project's current configuration nonce.
712
+ * @return permissionedAddress the address used to make the update, accounting for delegation.
710
713
  */
711
714
  function _validatePMPInputAndAuth(
712
715
  uint256 tokenId,
@@ -714,7 +717,7 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
714
717
  PMPInput memory pmpInput,
715
718
  PMPConfigStorage storage pmpConfigStorage,
716
719
  uint8 projectConfigNonce
717
- ) internal view {
720
+ ) internal view returns (address permissionedAddress) {
718
721
  // check that the param is part of the project's most recently configured PMP params
719
722
  // @dev use config nonce to check if param is part of most recently configured PMP params
720
723
  require(
@@ -733,88 +736,79 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
733
736
  );
734
737
 
735
738
  // ensure caller has appropriate auth
739
+ bool isAuthenticated;
736
740
  {
737
- // @dev block scope to reduce stack depth
741
+ AuthOption authOption = pmpConfigStorage.authOption;
742
+ // if artist may configure, check and authenticate if not already authenticated
743
+ if (
744
+ authOption == AuthOption.Artist ||
745
+ authOption == AuthOption.ArtistAndAddress ||
746
+ authOption == AuthOption.ArtistAndTokenOwner ||
747
+ authOption == AuthOption.ArtistAndTokenOwnerAndAddress
748
+ ) {
749
+ bool isArtist;
750
+ (isArtist, permissionedAddress) = _isArtist({
751
+ tokenId: tokenId,
752
+ coreContract: coreContract,
753
+ sender: msg.sender
754
+ });
755
+ isAuthenticated = isArtist;
756
+ }
757
+ // if address may configure, check and authenticate if not already authenticated
758
+ if (
759
+ !isAuthenticated &&
760
+ (authOption == AuthOption.Address ||
761
+ authOption == AuthOption.TokenOwnerAndAddress ||
762
+ authOption == AuthOption.ArtistAndAddress ||
763
+ authOption == AuthOption.ArtistAndTokenOwnerAndAddress)
764
+ ) {
765
+ permissionedAddress = pmpConfigStorage.authAddress;
766
+ isAuthenticated = permissionedAddress == msg.sender;
767
+ }
768
+ // if token owner or delegate may configure, check and authenticate
769
+ // @dev check token ownerlast to enable pre-mint PMP configuration by non-token-owner
770
+ if (
771
+ !isAuthenticated &&
772
+ (authOption == AuthOption.TokenOwner ||
773
+ authOption == AuthOption.ArtistAndTokenOwner ||
774
+ authOption == AuthOption.TokenOwnerAndAddress ||
775
+ authOption == AuthOption.ArtistAndTokenOwnerAndAddress)
776
+ ) {
777
+ bool isTokenOwnerOrDelegate_;
778
+ (
779
+ isTokenOwnerOrDelegate_,
780
+ permissionedAddress
781
+ ) = _isTokenOwnerOrDelegate({
782
+ tokenId: tokenId,
783
+ coreContract: coreContract,
784
+ sender: msg.sender
785
+ });
786
+ isAuthenticated = isTokenOwnerOrDelegate_;
787
+ }
788
+ }
789
+ // if not authenticated, revert with appropriate auth error
790
+ if (!isAuthenticated) {
738
791
  AuthOption authOption = pmpConfigStorage.authOption;
739
792
  if (authOption == AuthOption.Artist) {
740
- require(
741
- _isArtist({
742
- tokenId: tokenId,
743
- coreContract: coreContract,
744
- sender: msg.sender
745
- }),
746
- "PMP: artist auth required"
747
- );
793
+ revert("PMP: artist auth required");
748
794
  } else if (authOption == AuthOption.TokenOwner) {
749
- require(
750
- _isTokenOwnerOrDelegate({
751
- tokenId: tokenId,
752
- coreContract: coreContract,
753
- sender: msg.sender
754
- }),
755
- "PMP: token owner auth required"
756
- );
795
+ revert("PMP: token owner auth required");
757
796
  } else if (authOption == AuthOption.ArtistAndTokenOwner) {
758
- // @dev check token owner or delegate last to enable pre-mint configuration by non-token-owner
759
- require(
760
- _isArtist({
761
- tokenId: tokenId,
762
- coreContract: coreContract,
763
- sender: msg.sender
764
- }) ||
765
- _isTokenOwnerOrDelegate({
766
- tokenId: tokenId,
767
- coreContract: coreContract,
768
- sender: msg.sender
769
- }),
770
- "PMP: artist and token owner auth required"
771
- );
797
+ revert("PMP: artist and token owner auth required");
772
798
  } else if (authOption == AuthOption.Address) {
773
- require(
774
- msg.sender == pmpConfigStorage.authAddress,
775
- "PMP: address auth required"
776
- );
799
+ revert("PMP: address auth required");
777
800
  } else if (authOption == AuthOption.ArtistAndTokenOwnerAndAddress) {
778
- // @dev check token owner or delegate last to enable pre-mint configuration by non-token-owner
779
- require(
780
- _isArtist({
781
- tokenId: tokenId,
782
- coreContract: coreContract,
783
- sender: msg.sender
784
- }) ||
785
- msg.sender == pmpConfigStorage.authAddress ||
786
- _isTokenOwnerOrDelegate({
787
- tokenId: tokenId,
788
- coreContract: coreContract,
789
- sender: msg.sender
790
- }),
791
- "PMP: artist and token owner and address auth required"
792
- );
801
+ revert("PMP: artist and token owner and address auth required");
793
802
  } else if (authOption == AuthOption.ArtistAndAddress) {
794
- require(
795
- _isArtist({
796
- tokenId: tokenId,
797
- coreContract: coreContract,
798
- sender: msg.sender
799
- }) || msg.sender == pmpConfigStorage.authAddress,
800
- "PMP: artist and address auth required"
801
- );
803
+ revert("PMP: artist and address auth required");
802
804
  } else if (authOption == AuthOption.TokenOwnerAndAddress) {
803
- // @dev check token owner or delegate last to enable pre-mint configuration by non-token-owner
804
- require(
805
- msg.sender == pmpConfigStorage.authAddress ||
806
- _isTokenOwnerOrDelegate({
807
- tokenId: tokenId,
808
- coreContract: coreContract,
809
- sender: msg.sender
810
- }),
811
- "PMP: token owner and address auth required"
812
- );
805
+ revert("PMP: token owner and address auth required");
813
806
  } else {
814
807
  // @dev no coverage, this should never be reached
815
808
  revert("PMP: invalid authOption");
816
809
  }
817
810
  }
811
+ // @dev auth check is complete
818
812
 
819
813
  // ensure properly configured value
820
814
  ParamType paramType = pmpConfigStorage.paramType;
@@ -875,12 +869,13 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
875
869
  // require artist is caller if configuring artist string
876
870
  if (pmpInput.configuringArtistString) {
877
871
  // require artist is caller
872
+ (bool isArtist, ) = _isArtist({
873
+ tokenId: tokenId,
874
+ coreContract: coreContract,
875
+ sender: msg.sender
876
+ });
878
877
  require(
879
- _isArtist({
880
- tokenId: tokenId,
881
- coreContract: coreContract,
882
- sender: msg.sender
883
- }),
878
+ isArtist,
884
879
  "PMP: artist auth required to configure artist string"
885
880
  );
886
881
  }
@@ -1020,17 +1015,18 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
1020
1015
  * @param tokenId The token ID to get the project ID from.
1021
1016
  * @param coreContract The address of the core contract.
1022
1017
  * @param sender The address to check if it's the artist.
1023
- * @return Returns true if the sender is the artist, false otherwise.
1018
+ * @return isArtist true if the sender is the artist, false otherwise.
1019
+ * @return artistAddress the address of the artist.
1024
1020
  */
1025
1021
  function _isArtist(
1026
1022
  uint256 tokenId,
1027
1023
  address coreContract,
1028
1024
  address sender
1029
- ) internal view returns (bool) {
1025
+ ) internal view returns (bool isArtist, address artistAddress) {
1030
1026
  uint256 projectId = ABHelpers.tokenIdToProjectId(tokenId);
1031
- return
1032
- IGenArt721CoreContractV3_Base(coreContract)
1033
- .projectIdToArtistAddress(projectId) == sender;
1027
+ artistAddress = IGenArt721CoreContractV3_Base(coreContract)
1028
+ .projectIdToArtistAddress(projectId);
1029
+ isArtist = artistAddress == sender;
1034
1030
  }
1035
1031
 
1036
1032
  /**
@@ -1041,21 +1037,19 @@ contract PMPV0 is IPMPV0, Web3Call, ReentrancyGuard {
1041
1037
  * @param tokenId The token ID to check ownership for.
1042
1038
  * @param coreContract The address of the core contract.
1043
1039
  * @param sender The address to check if it's the token owner.
1044
- * @return Returns true if the sender is the token owner, false otherwise.
1040
+ * @return isTokenOwnerOrDelegate_ true if the sender is the token owner or delegate of the token owner, false otherwise.
1041
+ * @return tokenOwner the address of the token owner.
1045
1042
  * @dev Always execute within a nonReentrant context.
1046
1043
  */
1047
1044
  function _isTokenOwnerOrDelegate(
1048
1045
  uint256 tokenId,
1049
1046
  address coreContract,
1050
1047
  address sender
1051
- ) internal view returns (bool) {
1048
+ ) internal view returns (bool isTokenOwnerOrDelegate_, address tokenOwner) {
1052
1049
  // @dev leading interaction - only execute within a nonReentrant context
1053
- address tokenOwner = IERC721(coreContract).ownerOf(tokenId);
1054
- if (tokenOwner == sender) {
1055
- return true;
1056
- }
1057
- // @dev delegate.xyz v2 support
1058
- return
1050
+ tokenOwner = IERC721(coreContract).ownerOf(tokenId);
1051
+ isTokenOwnerOrDelegate_ =
1052
+ (tokenOwner == sender) ||
1059
1053
  delegateRegistry.checkDelegateForERC721({
1060
1054
  to: sender, // hot wallet
1061
1055
  from: tokenOwner, // vault
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artblocks/contracts",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "Smart contracts used by Art Blocks",
5
5
  "files": [
6
6
  "/contracts/**/*.sol",
@@ -90,7 +90,7 @@
90
90
  "@nomiclabs/hardhat-web3": "^2.0.0",
91
91
  "@openzeppelin/hardhat-upgrades": "^1.28.0",
92
92
  "@openzeppelin/test-helpers": "^0.5.16",
93
- "@remix-project/remixd": "^0.6.37",
93
+ "@remix-project/remixd": "^0.6.46",
94
94
  "@safe-global/api-kit": "^1.3.1",
95
95
  "@safe-global/protocol-kit": "1.3.0",
96
96
  "@safe-global/safe-core-sdk-types": "2.3.0",