@@ -18,9 +18,9 @@ contract CampaignRegistry is Initializable, UUPSUpgradeable, AccessControlledUpg
1818 using ERC165Checker for address ;
1919 using EnumerableSet for EnumerableSet.AddressSet;
2020
21+ uint256 private constant MIN_EXPIRE_AT = 1 hours ;
2122 /// @dev The interface ID for ICampaign, used to verify that a campaign contract implements the correct interface.
2223 bytes4 private constant INTERFACE_CAMPAIGN = type (ICampaign).interfaceId;
23- uint256 private constant MIN_EXPIRE_AT = 1 hours ;
2424 /// @dev Maps a campaign reference to its associated scope, which defines the entity the campaign operates on.
2525 mapping (bytes32 => address ) private _scopes;
2626
@@ -67,30 +67,29 @@ contract CampaignRegistry is Initializable, UUPSUpgradeable, AccessControlledUpg
6767 /// @return The address of the associated campaign if found, otherwise `address(0)`.
6868 function getCampaign (address account , address policy ) external view returns (address ) {
6969 // Compute the unique identifier for the campaign association
70- bytes32 scopeId = _computeComposedKey (account, policy);
71- return _scopes[scopeId]; // Return the campaign address if it exists, else return address(0)
70+ return _scopes[_computeComposedKey (account, policy)];
7271 }
7372
7473 /// @notice Creates and registers a new campaign by cloning a given template contract.
7574 /// @dev The provided template must be a valid campaign contract.
7675 /// @param template The address of the campaign contract to clone.
7776 /// @param policy The policy the campaign is linked to.
78- /// @param expireAt The timestamp when the campaign expires.
77+ /// @param expiration The timestamp when the campaign expires.
7978 /// @param description A brief description of the campaign.
8079 /// @return The address of the newly created campaign.
8180 function createCampaign (
8281 address template ,
8382 address policy ,
84- uint256 expireAt ,
83+ uint256 expiration ,
8584 string calldata description
8685 ) external onlyValidCampaigns (template) returns (address ) {
8786 // minimum 1 hour to set as expire at
88- if (expireAt < MIN_EXPIRE_AT) {
87+ if (expiration < MIN_EXPIRE_AT) {
8988 revert InvalidInput ();
9089 }
9190
92- bytes32 salt = keccak256 ( abi.encodePacked ( msg . sender , template, expireAt)) ;
93- address clone = template. cloneDeterministic (salt );
91+ uint expireAt = block . timestamp + expiration ;
92+ address clone = _clone (template, expireAt );
9493 address campaign = _setup (clone, expireAt);
9594 // store "linked" owner + scope + campaign
9695 // this is useful during campaign retrieval from scope context
@@ -114,7 +113,6 @@ contract CampaignRegistry is Initializable, UUPSUpgradeable, AccessControlledUpg
114113 return campaign;
115114 }
116115
117- /// @notice Associates a scope with a campaign.
118116 /// @dev Creates a unique identifier for the scope based on the owner's address
119117 /// and the scope address. The generated scope ID is mapped to the campaign
120118 /// in the `_scopes` mapping, allowing efficient retrieval.
@@ -128,6 +126,12 @@ contract CampaignRegistry is Initializable, UUPSUpgradeable, AccessControlledUpg
128126 return scopeId;
129127 }
130128
129+ /// @dev Deploy a new minimal-proxy (EIP-1167) based on the specified campaign template.
130+ function _clone (address template , uint256 expireAt ) private returns (address ) {
131+ bytes32 salt = keccak256 (abi.encodePacked (msg .sender , template, expireAt));
132+ return template.cloneDeterministic (salt);
133+ }
134+
131135 /// @notice Computes a unique key by combining a scope and an account address.
132136 /// @param account The address of the user for whom the key is being generated.
133137 /// @param scope The address representing the scope.
0 commit comments