@ballkidz/defifa 0.0.2 → 0.0.3

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.
@@ -156,24 +156,19 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
156
156
  // ------------------------- external views -------------------------- //
157
157
  //*********************************************************************//
158
158
 
159
- /// @notice The cashOut weight for each tier.
160
- /// @return The array of weights, indexed by tier.
161
- function tierCashOutWeights() external view override returns (uint256[128] memory) {
162
- return _tierCashOutWeights;
163
- }
159
+ /// @notice The first owner of each token ID, which corresponds to the address that originally contributed to the
160
+ /// project to receive the NFT.
161
+ /// @param tokenId The ID of the token to get the first owner of.
162
+ /// @return The first owner of the token.
163
+ function firstOwnerOf(uint256 tokenId) external view override returns (address) {
164
+ // Get a reference to the first owner.
165
+ address _storedFirstOwner = _firstOwnerOf[tokenId];
164
166
 
165
- /// @notice Returns the delegate of an account for specific tier.
166
- /// @param account The account to check for a delegate of.
167
- /// @param tier The tier to check within.
168
- function getTierDelegateOf(address account, uint256 tier) external view override returns (address) {
169
- return _tierDelegation[account][tier];
170
- }
167
+ // If the stored first owner is set, return it.
168
+ if (_storedFirstOwner != address(0)) return _storedFirstOwner;
171
169
 
172
- /// @notice Returns the current attestation power of an address for a specific tier.
173
- /// @param account The address to check.
174
- /// @param tier The tier to check within.
175
- function getTierAttestationUnitsOf(address account, uint256 tier) external view override returns (uint256) {
176
- return _delegateTierCheckpoints[account][tier].latest();
170
+ // Otherwise, the first owner must be the current owner.
171
+ return _owners[tokenId];
177
172
  }
178
173
 
179
174
  /// @notice Returns the past attestation units of a specific address for a specific tier.
@@ -193,12 +188,6 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
193
188
  return _delegateTierCheckpoints[account][tier].upperLookup(timestamp);
194
189
  }
195
190
 
196
- /// @notice Returns the total amount of attestation units that exists for a tier.
197
- /// @param tier The tier to check.
198
- function getTierTotalAttestationUnitsOf(uint256 tier) external view override returns (uint256) {
199
- return _totalTierCheckpoints[tier].latest();
200
- }
201
-
202
191
  /// @notice Returns the total amount of attestation units that has existed for a tier.
203
192
  /// @param tier The tier to check.
204
193
  /// @param timestamp The timestamp to check the total attestation units at.
@@ -214,19 +203,30 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
214
203
  return _totalTierCheckpoints[tier].upperLookup(timestamp);
215
204
  }
216
205
 
217
- /// @notice The first owner of each token ID, which corresponds to the address that originally contributed to the
218
- /// project to receive the NFT.
219
- /// @param tokenId The ID of the token to get the first owner of.
220
- /// @return The first owner of the token.
221
- function firstOwnerOf(uint256 tokenId) external view override returns (address) {
222
- // Get a reference to the first owner.
223
- address _storedFirstOwner = _firstOwnerOf[tokenId];
206
+ /// @notice Returns the current attestation power of an address for a specific tier.
207
+ /// @param account The address to check.
208
+ /// @param tier The tier to check within.
209
+ function getTierAttestationUnitsOf(address account, uint256 tier) external view override returns (uint256) {
210
+ return _delegateTierCheckpoints[account][tier].latest();
211
+ }
224
212
 
225
- // If the stored first owner is set, return it.
226
- if (_storedFirstOwner != address(0)) return _storedFirstOwner;
213
+ /// @notice Returns the delegate of an account for specific tier.
214
+ /// @param account The account to check for a delegate of.
215
+ /// @param tier The tier to check within.
216
+ function getTierDelegateOf(address account, uint256 tier) external view override returns (address) {
217
+ return _tierDelegation[account][tier];
218
+ }
227
219
 
228
- // Otherwise, the first owner must be the current owner.
229
- return _owners[tokenId];
220
+ /// @notice Returns the total amount of attestation units that exists for a tier.
221
+ /// @param tier The tier to check.
222
+ function getTierTotalAttestationUnitsOf(uint256 tier) external view override returns (uint256) {
223
+ return _totalTierCheckpoints[tier].latest();
224
+ }
225
+
226
+ /// @notice The cashOut weight for each tier.
227
+ /// @return The array of weights, indexed by tier.
228
+ function tierCashOutWeights() external view override returns (uint256[128] memory) {
229
+ return _tierCashOutWeights;
230
230
  }
231
231
 
232
232
  /// @notice The name of the tier with the specified ID.
@@ -239,72 +239,6 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
239
239
  // -------------------------- public views --------------------------- //
240
240
  //*********************************************************************//
241
241
 
242
- /// @notice The metadata URI of the provided token ID.
243
- /// @dev Defer to the tokenUriResolver if set, otherwise, use the tokenUri set with the token's tier.
244
- /// @param tokenId The ID of the token to get the tier URI for.
245
- /// @return The token URI corresponding with the tier or the tokenUriResolver URI.
246
- function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
247
- // Use the resolver.
248
- return store.tokenUriResolverOf(address(this)).tokenUriOf(address(this), tokenId);
249
- }
250
-
251
- /// @notice The cumulative weight the given token IDs have in cashOuts compared to the `totalCashOutWeight`.
252
- /// @param tokenIds The IDs of the tokens to get the cumulative cashOut weight of.
253
- /// @return cumulativeWeight The weight.
254
- function cashOutWeightOf(uint256[] memory tokenIds)
255
- public
256
- view
257
- virtual
258
- override
259
- returns (uint256 cumulativeWeight)
260
- {
261
- cumulativeWeight = DefifaHookLib.computeCashOutWeightBatch({
262
- tokenIds: tokenIds,
263
- _store: store,
264
- hook: address(this),
265
- tierCashOutWeights: _tierCashOutWeights,
266
- tokensRedeemedFrom: tokensRedeemedFrom
267
- });
268
- }
269
-
270
- /// @notice The weight the given token ID has in cashOuts.
271
- /// @param tokenId The ID of the token to get the cashOut weight of.
272
- /// @return The weight.
273
- function cashOutWeightOf(uint256 tokenId) public view override returns (uint256) {
274
- return DefifaHookLib.computeCashOutWeight({
275
- tokenId: tokenId,
276
- _store: store,
277
- hook: address(this),
278
- tierCashOutWeights: _tierCashOutWeights,
279
- tokensRedeemedFrom: tokensRedeemedFrom
280
- });
281
- }
282
-
283
- /// @notice The amount of tokens of a tier that are currently in circulation.
284
- /// @param tierId The ID of the tier to get the current supply of.
285
- function currentSupplyOfTier(uint256 tierId) public view returns (uint256) {
286
- return DefifaHookLib.computeCurrentSupply({_store: store, hook: address(this), tierId: tierId});
287
- }
288
-
289
- /// @notice The combined cash out weight of all outstanding NFTs.
290
- /// @dev An NFT's cash out weight is its price.
291
- /// @return The total cash out weight.
292
- function totalCashOutWeight() public view virtual override returns (uint256) {
293
- return TOTAL_CASHOUT_WEIGHT;
294
- }
295
-
296
- /// @notice The amount of $DEFIFA and $BASE_PROTOCOL tokens this game was allocated from paying the network fee.
297
- /// @return defifaTokenAllocation The $DEFIFA token allocation.
298
- /// @return baseProtocolTokenAllocation The $BASE_PROTOCOL token allocation.
299
- function tokenAllocations()
300
- public
301
- view
302
- returns (uint256 defifaTokenAllocation, uint256 baseProtocolTokenAllocation)
303
- {
304
- defifaTokenAllocation = defifaToken.balanceOf(address(this));
305
- baseProtocolTokenAllocation = baseProtocolToken.balanceOf(address(this));
306
- }
307
-
308
242
  /// @notice The data calculated before a cash out is recorded in the terminal store. This data is provided to the
309
243
  /// terminal's `cashOutTokensOf(...)` transaction.
310
244
  /// @dev Sets this contract as the cash out hook. Part of `IJBRulesetDataHook`.
@@ -367,6 +301,72 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
367
301
  cashOutTaxRate = context.cashOutTaxRate;
368
302
  }
369
303
 
304
+ /// @notice The cumulative weight the given token IDs have in cashOuts compared to the `totalCashOutWeight`.
305
+ /// @param tokenIds The IDs of the tokens to get the cumulative cashOut weight of.
306
+ /// @return cumulativeWeight The weight.
307
+ function cashOutWeightOf(uint256[] memory tokenIds)
308
+ public
309
+ view
310
+ virtual
311
+ override
312
+ returns (uint256 cumulativeWeight)
313
+ {
314
+ cumulativeWeight = DefifaHookLib.computeCashOutWeightBatch({
315
+ tokenIds: tokenIds,
316
+ _store: store,
317
+ hook: address(this),
318
+ tierCashOutWeights: _tierCashOutWeights,
319
+ tokensRedeemedFrom: tokensRedeemedFrom
320
+ });
321
+ }
322
+
323
+ /// @notice The weight the given token ID has in cashOuts.
324
+ /// @param tokenId The ID of the token to get the cashOut weight of.
325
+ /// @return The weight.
326
+ function cashOutWeightOf(uint256 tokenId) public view override returns (uint256) {
327
+ return DefifaHookLib.computeCashOutWeight({
328
+ tokenId: tokenId,
329
+ _store: store,
330
+ hook: address(this),
331
+ tierCashOutWeights: _tierCashOutWeights,
332
+ tokensRedeemedFrom: tokensRedeemedFrom
333
+ });
334
+ }
335
+
336
+ /// @notice The amount of tokens of a tier that are currently in circulation.
337
+ /// @param tierId The ID of the tier to get the current supply of.
338
+ function currentSupplyOfTier(uint256 tierId) public view returns (uint256) {
339
+ return DefifaHookLib.computeCurrentSupply({_store: store, hook: address(this), tierId: tierId});
340
+ }
341
+
342
+ /// @notice Indicates if this contract adheres to the specified interface.
343
+ /// @dev See {IERC165-supportsInterface}.
344
+ /// @param interfaceId The ID of the interface to check for adherence to.
345
+ function supportsInterface(bytes4 interfaceId) public view override(JB721Hook, IERC165) returns (bool) {
346
+ return interfaceId == type(IDefifaHook).interfaceId || super.supportsInterface(interfaceId);
347
+ }
348
+
349
+ /// @notice The amount of $DEFIFA and $BASE_PROTOCOL tokens this game was allocated from paying the network fee.
350
+ /// @return defifaTokenAllocation The $DEFIFA token allocation.
351
+ /// @return baseProtocolTokenAllocation The $BASE_PROTOCOL token allocation.
352
+ function tokenAllocations()
353
+ public
354
+ view
355
+ returns (uint256 defifaTokenAllocation, uint256 baseProtocolTokenAllocation)
356
+ {
357
+ defifaTokenAllocation = defifaToken.balanceOf(address(this));
358
+ baseProtocolTokenAllocation = baseProtocolToken.balanceOf(address(this));
359
+ }
360
+
361
+ /// @notice The metadata URI of the provided token ID.
362
+ /// @dev Defer to the tokenUriResolver if set, otherwise, use the tokenUri set with the token's tier.
363
+ /// @param tokenId The ID of the token to get the tier URI for.
364
+ /// @return The token URI corresponding with the tier or the tokenUriResolver URI.
365
+ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
366
+ // Use the resolver.
367
+ return store.tokenUriResolverOf(address(this)).tokenUriOf(address(this), tokenId);
368
+ }
369
+
370
370
  /// @notice The amount of $DEFIFA and $BASE_PROTOCOL tokens claimable for a set of token IDs.
371
371
  /// @param tokenIds The IDs of the tokens that justify a $DEFIFA claim.
372
372
  /// @return defifaTokenAmount The amount of $DEFIFA that can be claimed.
@@ -390,11 +390,11 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
390
390
  });
391
391
  }
392
392
 
393
- /// @notice Indicates if this contract adheres to the specified interface.
394
- /// @dev See {IERC165-supportsInterface}.
395
- /// @param interfaceId The ID of the interface to check for adherence to.
396
- function supportsInterface(bytes4 interfaceId) public view override(JB721Hook, IERC165) returns (bool) {
397
- return interfaceId == type(IDefifaHook).interfaceId || super.supportsInterface(interfaceId);
393
+ /// @notice The combined cash out weight of all outstanding NFTs.
394
+ /// @dev An NFT's cash out weight is its price.
395
+ /// @return The total cash out weight.
396
+ function totalCashOutWeight() public view virtual override returns (uint256) {
397
+ return TOTAL_CASHOUT_WEIGHT;
398
398
  }
399
399
 
400
400
  //*********************************************************************//
@@ -594,31 +594,6 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
594
594
  // ---------------------- external transactions ---------------------- //
595
595
  //*********************************************************************//
596
596
 
597
- /// @notice Stores the cashOut weights that should be used in the end game phase.
598
- /// @dev Only this contract's owner can set tier cashOut weights.
599
- /// @param tierWeights The tier weights to set.
600
- function setTierCashOutWeightsTo(DefifaTierCashOutWeight[] memory tierWeights) external override onlyOwner {
601
- // Get a reference to the game phase.
602
- DefifaGamePhase _gamePhase = gamePhaseReporter.currentGamePhaseOf(PROJECT_ID);
603
-
604
- // Make sure the game has ended.
605
- if (_gamePhase != DefifaGamePhase.SCORING) {
606
- revert DefifaHook_GameIsntScoringYet();
607
- }
608
-
609
- // Make sure the cashOut weights haven't already been set.
610
- if (cashOutWeightIsSet) revert DefifaHook_CashoutWeightsAlreadySet();
611
-
612
- // Validate weights and build the array. Reverts on invalid input.
613
- _tierCashOutWeights =
614
- DefifaHookLib.validateAndBuildWeights({tierWeights: tierWeights, _store: store, hook: address(this)});
615
-
616
- // Mark the cashOut weight as set.
617
- cashOutWeightIsSet = true;
618
-
619
- emit TierCashOutWeightsSet(tierWeights, msg.sender);
620
- }
621
-
622
597
  /// @notice Burns the specified NFTs upon token holder cash out, reclaiming funds from the project's balance for
623
598
  /// `context.beneficiary`. Part of `IJBCashOutHook`.
624
599
  /// @dev Reverts if the calling contract is not one of the project's terminals.
@@ -722,33 +697,29 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
722
697
  }
723
698
  }
724
699
 
725
- /// @notice Delegate attestations.
726
- /// @param delegations An array of tiers to set delegates for.
727
- function setTierDelegatesTo(DefifaDelegation[] memory delegations) external virtual override {
728
- // Make sure the current game phase is the minting phase.
729
- if (gamePhaseReporter.currentGamePhaseOf(PROJECT_ID) != DefifaGamePhase.MINT) {
730
- revert DefifaHook_DelegateChangesUnavailableInThisPhase();
731
- }
700
+ /// @notice Stores the cashOut weights that should be used in the end game phase.
701
+ /// @dev Only this contract's owner can set tier cashOut weights.
702
+ /// @param tierWeights The tier weights to set.
703
+ function setTierCashOutWeightsTo(DefifaTierCashOutWeight[] memory tierWeights) external override onlyOwner {
704
+ // Get a reference to the game phase.
705
+ DefifaGamePhase _gamePhase = gamePhaseReporter.currentGamePhaseOf(PROJECT_ID);
732
706
 
733
- // Keep a reference to the number of tier delegates.
734
- uint256 _numberOfTierDelegates = delegations.length;
707
+ // Make sure the game has ended.
708
+ if (_gamePhase != DefifaGamePhase.SCORING) {
709
+ revert DefifaHook_GameIsntScoringYet();
710
+ }
735
711
 
736
- // Keep a reference to the data being iterated on.
737
- DefifaDelegation memory _data;
712
+ // Make sure the cashOut weights haven't already been set.
713
+ if (cashOutWeightIsSet) revert DefifaHook_CashoutWeightsAlreadySet();
738
714
 
739
- for (uint256 _i; _i < _numberOfTierDelegates;) {
740
- // Reference the data being iterated on.
741
- _data = delegations[_i];
742
-
743
- // Make sure a delegate is specified.
744
- if (_data.delegatee == address(0)) revert DefifaHook_DelegateAddressZero();
715
+ // Validate weights and build the array. Reverts on invalid input.
716
+ _tierCashOutWeights =
717
+ DefifaHookLib.validateAndBuildWeights({tierWeights: tierWeights, _store: store, hook: address(this)});
745
718
 
746
- _delegateTier({_account: msg.sender, _delegatee: _data.delegatee, _tierId: _data.tierId});
719
+ // Mark the cashOut weight as set.
720
+ cashOutWeightIsSet = true;
747
721
 
748
- unchecked {
749
- ++_i;
750
- }
751
- }
722
+ emit TierCashOutWeightsSet(tierWeights, msg.sender);
752
723
  }
753
724
 
754
725
  /// @notice Delegate attestations.
@@ -763,10 +734,176 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
763
734
  _delegateTier({_account: msg.sender, _delegatee: delegatee, _tierId: tierId});
764
735
  }
765
736
 
737
+ /// @notice Delegate attestations.
738
+ /// @param delegations An array of tiers to set delegates for.
739
+ function setTierDelegatesTo(DefifaDelegation[] memory delegations) external virtual override {
740
+ // Make sure the current game phase is the minting phase.
741
+ if (gamePhaseReporter.currentGamePhaseOf(PROJECT_ID) != DefifaGamePhase.MINT) {
742
+ revert DefifaHook_DelegateChangesUnavailableInThisPhase();
743
+ }
744
+
745
+ // Keep a reference to the number of tier delegates.
746
+ uint256 _numberOfTierDelegates = delegations.length;
747
+
748
+ // Keep a reference to the data being iterated on.
749
+ DefifaDelegation memory _data;
750
+
751
+ for (uint256 _i; _i < _numberOfTierDelegates;) {
752
+ // Reference the data being iterated on.
753
+ _data = delegations[_i];
754
+
755
+ // Make sure a delegate is specified.
756
+ if (_data.delegatee == address(0)) revert DefifaHook_DelegateAddressZero();
757
+
758
+ _delegateTier({_account: msg.sender, _delegatee: _data.delegatee, _tierId: _data.tierId});
759
+
760
+ unchecked {
761
+ ++_i;
762
+ }
763
+ }
764
+ }
765
+
766
766
  //*********************************************************************//
767
767
  // ------------------------ internal functions ----------------------- //
768
768
  //*********************************************************************//
769
769
 
770
+ /// @notice Claims the defifa and base protocol tokens for a beneficiary.
771
+ /// @param _beneficiary The address to claim tokens for.
772
+ /// @param shareToBeneficiary The share relative to the `outOfTotal` to send the user.
773
+ /// @param outOfTotal The total share that the `shareToBeneficiary` is relative to.
774
+ /// @return beneficiaryReceivedTokens A flag indicating if the beneficiary received any tokens.
775
+ function _claimTokensFor(
776
+ address _beneficiary,
777
+ uint256 shareToBeneficiary,
778
+ uint256 outOfTotal
779
+ )
780
+ internal
781
+ returns (bool beneficiaryReceivedTokens)
782
+ {
783
+ return DefifaHookLib.claimTokensFor({
784
+ _beneficiary: _beneficiary,
785
+ shareToBeneficiary: shareToBeneficiary,
786
+ outOfTotal: outOfTotal,
787
+ _defifaToken: defifaToken,
788
+ _baseProtocolToken: baseProtocolToken
789
+ });
790
+ }
791
+
792
+ /// @notice Delegate all attestation units for the specified tier.
793
+ /// @param _account The account delegating tier attestation units.
794
+ /// @param _delegatee The account to delegate tier attestation units to.
795
+ /// @param _tierId The ID of the tier for which attestation units are being transferred.
796
+ function _delegateTier(address _account, address _delegatee, uint256 _tierId) internal virtual {
797
+ // Get the current delegatee
798
+ address _oldDelegate = _tierDelegation[_account][_tierId];
799
+
800
+ // Store the new delegatee
801
+ _tierDelegation[_account][_tierId] = _delegatee;
802
+
803
+ emit DelegateChanged(_account, _oldDelegate, _delegatee);
804
+
805
+ // Move the attestations.
806
+ _moveTierDelegateAttestations({
807
+ _from: _oldDelegate,
808
+ _to: _delegatee,
809
+ _tierId: _tierId,
810
+ _amount: _getTierAttestationUnits({_account: _account, _tierId: _tierId})
811
+ });
812
+ }
813
+
814
+ /// @notice A function that will run when tokens are burned via cashOut.
815
+ /// @param _tokenIds The IDs of the tokens that were burned.
816
+ function _didBurn(uint256[] memory _tokenIds) internal virtual override {
817
+ // Add to burned counter.
818
+ store.recordBurn(_tokenIds);
819
+ }
820
+
821
+ /// @notice Gets the amount of attestation units an address has for a particular tier.
822
+ /// @param _account The account to get attestation units for.
823
+ /// @param _tierId The ID of the tier to get attestation units for.
824
+ /// @return The attestation units.
825
+ function _getTierAttestationUnits(address _account, uint256 _tierId) internal view virtual returns (uint256) {
826
+ return store.tierVotingUnitsOf({hook: address(this), account: _account, tierId: _tierId});
827
+ }
828
+
829
+ /// @notice Mints a token in all provided tiers.
830
+ /// @param _amount The amount to base the mints on. All mints' price floors must fit in this amount.
831
+ /// @param _mintTierIds An array of tier IDs that are intended to be minted.
832
+ /// @param _beneficiary The address to mint for.
833
+ /// @return leftoverAmount The amount leftover after the mint.
834
+ function _mintAll(
835
+ uint256 _amount,
836
+ uint16[] memory _mintTierIds,
837
+ address _beneficiary
838
+ )
839
+ internal
840
+ returns (uint256 leftoverAmount)
841
+ {
842
+ // Keep a reference to the token ID.
843
+ uint256[] memory _tokenIds;
844
+
845
+ // Record the mint. The returned token IDs correspond to the tiers passed in.
846
+ (_tokenIds, leftoverAmount) = store.recordMint({
847
+ amount: _amount,
848
+ tierIds: _mintTierIds,
849
+ isOwnerMint: false // Not a manual mint
850
+ });
851
+
852
+ // Get a reference to the number of mints.
853
+ uint256 _mintsLength = _tokenIds.length;
854
+
855
+ // Keep a reference to the token ID being iterated on.
856
+ uint256 _tokenId;
857
+
858
+ // Increment the paid mint cost.
859
+ _totalMintCost += _amount;
860
+
861
+ // Loop through each token ID and mint.
862
+ for (uint256 _i; _i < _mintsLength;) {
863
+ // Get a reference to the tier being iterated on.
864
+ _tokenId = _tokenIds[_i];
865
+
866
+ // Mint the tokens.
867
+ _mint(_beneficiary, _tokenId);
868
+
869
+ emit Mint(_tokenId, _mintTierIds[_i], _beneficiary, _amount, msg.sender);
870
+
871
+ unchecked {
872
+ ++_i;
873
+ }
874
+ }
875
+ }
876
+
877
+ /// @notice Moves delegated tier attestations from one delegate to another.
878
+ /// @param _from The account to transfer tier attestation units from.
879
+ /// @param _to The account to transfer tier attestation units to.
880
+ /// @param _tierId The ID of the tier for which attestation units are being transferred.
881
+ /// @param _amount The amount of attestation units to delegate.
882
+ function _moveTierDelegateAttestations(address _from, address _to, uint256 _tierId, uint256 _amount) internal {
883
+ // Nothing to do if moving to the same account, or no amount is being moved.
884
+ if (_from == _to || _amount == 0) return;
885
+
886
+ // If not moving from the zero address, update the checkpoints to subtract the amount.
887
+ if (_from != address(0)) {
888
+ // Get the current amount for the sending delegate.
889
+ uint208 _current = _delegateTierCheckpoints[_from][_tierId].latest();
890
+ // Set the new amount for the sending delegate.
891
+ (uint256 _oldValue, uint256 _newValue) =
892
+ _delegateTierCheckpoints[_from][_tierId].push(uint48(block.timestamp), _current - uint208(_amount));
893
+ emit TierDelegateAttestationsChanged(_from, _tierId, _oldValue, _newValue, msg.sender);
894
+ }
895
+
896
+ // If not moving to the zero address, update the checkpoints to add the amount.
897
+ if (_to != address(0)) {
898
+ // Get the current amount for the receiving delegate.
899
+ uint208 _current = _delegateTierCheckpoints[_to][_tierId].latest();
900
+ // Set the new amount for the receiving delegate.
901
+ (uint256 _oldValue, uint256 _newValue) =
902
+ _delegateTierCheckpoints[_to][_tierId].push(uint48(block.timestamp), _current + uint208(_amount));
903
+ emit TierDelegateAttestationsChanged(_to, _tierId, _oldValue, _newValue, msg.sender);
904
+ }
905
+ }
906
+
770
907
  /// @notice Process an incoming payment.
771
908
  /// @param context The Juicebox standard project payment data.
772
909
  function _processPayment(JBAfterPayRecordedContext calldata context) internal override {
@@ -827,36 +964,6 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
827
964
  if (_leftoverAmount != 0) revert DefifaHook_Overspending();
828
965
  }
829
966
 
830
- /// @notice Gets the amount of attestation units an address has for a particular tier.
831
- /// @param _account The account to get attestation units for.
832
- /// @param _tierId The ID of the tier to get attestation units for.
833
- /// @return The attestation units.
834
- function _getTierAttestationUnits(address _account, uint256 _tierId) internal view virtual returns (uint256) {
835
- return store.tierVotingUnitsOf({hook: address(this), account: _account, tierId: _tierId});
836
- }
837
-
838
- /// @notice Delegate all attestation units for the specified tier.
839
- /// @param _account The account delegating tier attestation units.
840
- /// @param _delegatee The account to delegate tier attestation units to.
841
- /// @param _tierId The ID of the tier for which attestation units are being transferred.
842
- function _delegateTier(address _account, address _delegatee, uint256 _tierId) internal virtual {
843
- // Get the current delegatee
844
- address _oldDelegate = _tierDelegation[_account][_tierId];
845
-
846
- // Store the new delegatee
847
- _tierDelegation[_account][_tierId] = _delegatee;
848
-
849
- emit DelegateChanged(_account, _oldDelegate, _delegatee);
850
-
851
- // Move the attestations.
852
- _moveTierDelegateAttestations({
853
- _from: _oldDelegate,
854
- _to: _delegatee,
855
- _tierId: _tierId,
856
- _amount: _getTierAttestationUnits({_account: _account, _tierId: _tierId})
857
- });
858
- }
859
-
860
967
  /// @notice Transfers, mints, or burns tier attestation units. To register a mint, `_from` should be zero. To
861
968
  /// register a burn, `_to` should be zero. Total supply of attestation units will be adjusted with mints and burns.
862
969
  /// @param _from The account to transfer tier attestation units from.
@@ -898,113 +1005,6 @@ contract DefifaHook is JB721Hook, Ownable, IDefifaHook {
898
1005
  });
899
1006
  }
900
1007
 
901
- /// @notice Moves delegated tier attestations from one delegate to another.
902
- /// @param _from The account to transfer tier attestation units from.
903
- /// @param _to The account to transfer tier attestation units to.
904
- /// @param _tierId The ID of the tier for which attestation units are being transferred.
905
- /// @param _amount The amount of attestation units to delegate.
906
- function _moveTierDelegateAttestations(address _from, address _to, uint256 _tierId, uint256 _amount) internal {
907
- // Nothing to do if moving to the same account, or no amount is being moved.
908
- if (_from == _to || _amount == 0) return;
909
-
910
- // If not moving from the zero address, update the checkpoints to subtract the amount.
911
- if (_from != address(0)) {
912
- // Get the current amount for the sending delegate.
913
- uint208 _current = _delegateTierCheckpoints[_from][_tierId].latest();
914
- // Set the new amount for the sending delegate.
915
- (uint256 _oldValue, uint256 _newValue) =
916
- _delegateTierCheckpoints[_from][_tierId].push(uint48(block.timestamp), _current - uint208(_amount));
917
- emit TierDelegateAttestationsChanged(_from, _tierId, _oldValue, _newValue, msg.sender);
918
- }
919
-
920
- // If not moving to the zero address, update the checkpoints to add the amount.
921
- if (_to != address(0)) {
922
- // Get the current amount for the receiving delegate.
923
- uint208 _current = _delegateTierCheckpoints[_to][_tierId].latest();
924
- // Set the new amount for the receiving delegate.
925
- (uint256 _oldValue, uint256 _newValue) =
926
- _delegateTierCheckpoints[_to][_tierId].push(uint48(block.timestamp), _current + uint208(_amount));
927
- emit TierDelegateAttestationsChanged(_to, _tierId, _oldValue, _newValue, msg.sender);
928
- }
929
- }
930
-
931
- /// @notice A function that will run when tokens are burned via cashOut.
932
- /// @param _tokenIds The IDs of the tokens that were burned.
933
- function _didBurn(uint256[] memory _tokenIds) internal virtual override {
934
- // Add to burned counter.
935
- store.recordBurn(_tokenIds);
936
- }
937
-
938
- /// @notice Mints a token in all provided tiers.
939
- /// @param _amount The amount to base the mints on. All mints' price floors must fit in this amount.
940
- /// @param _mintTierIds An array of tier IDs that are intended to be minted.
941
- /// @param _beneficiary The address to mint for.
942
- /// @return leftoverAmount The amount leftover after the mint.
943
- function _mintAll(
944
- uint256 _amount,
945
- uint16[] memory _mintTierIds,
946
- address _beneficiary
947
- )
948
- internal
949
- returns (uint256 leftoverAmount)
950
- {
951
- // Keep a reference to the token ID.
952
- uint256[] memory _tokenIds;
953
-
954
- // Record the mint. The returned token IDs correspond to the tiers passed in.
955
- (_tokenIds, leftoverAmount) = store.recordMint({
956
- amount: _amount,
957
- tierIds: _mintTierIds,
958
- isOwnerMint: false // Not a manual mint
959
- });
960
-
961
- // Get a reference to the number of mints.
962
- uint256 _mintsLength = _tokenIds.length;
963
-
964
- // Keep a reference to the token ID being iterated on.
965
- uint256 _tokenId;
966
-
967
- // Increment the paid mint cost.
968
- _totalMintCost += _amount;
969
-
970
- // Loop through each token ID and mint.
971
- for (uint256 _i; _i < _mintsLength;) {
972
- // Get a reference to the tier being iterated on.
973
- _tokenId = _tokenIds[_i];
974
-
975
- // Mint the tokens.
976
- _mint(_beneficiary, _tokenId);
977
-
978
- emit Mint(_tokenId, _mintTierIds[_i], _beneficiary, _amount, msg.sender);
979
-
980
- unchecked {
981
- ++_i;
982
- }
983
- }
984
- }
985
-
986
- /// @notice Claims the defifa and base protocol tokens for a beneficiary.
987
- /// @param _beneficiary The address to claim tokens for.
988
- /// @param shareToBeneficiary The share relative to the `outOfTotal` to send the user.
989
- /// @param outOfTotal The total share that the `shareToBeneficiary` is relative to.
990
- /// @return beneficiaryReceivedTokens A flag indicating if the beneficiary received any tokens.
991
- function _claimTokensFor(
992
- address _beneficiary,
993
- uint256 shareToBeneficiary,
994
- uint256 outOfTotal
995
- )
996
- internal
997
- returns (bool beneficiaryReceivedTokens)
998
- {
999
- return DefifaHookLib.claimTokensFor({
1000
- _beneficiary: _beneficiary,
1001
- shareToBeneficiary: shareToBeneficiary,
1002
- outOfTotal: outOfTotal,
1003
- _defifaToken: defifaToken,
1004
- _baseProtocolToken: baseProtocolToken
1005
- });
1006
- }
1007
-
1008
1008
  /// @notice Before transferring an NFT, register its first owner (if necessary).
1009
1009
  /// @param to The address the NFT is being transferred to.
1010
1010
  /// @param tokenId The token ID of the NFT being transferred.