Skip to content

Commit c8b3758

Browse files
committed
chore: copying back name change to selfMintingOffset
1 parent ed7f384 commit c8b3758

File tree

2 files changed

+80
-86
lines changed

2 files changed

+80
-86
lines changed

packages/issuance/contracts/allocate/IssuanceAllocator.sol

Lines changed: 55 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ import { ERC165Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/int
8282
* This provides protection against potential issues if the multi-sig governor role were to have known
8383
* signatures that could be exploited by malicious actors to trigger reentrant calls.
8484
*
85-
* The `distributeIssuance()` function intentionally does NOT have reentrancy protection to allow
85+
* The `distributeIssuance()` function intentionally does NOT have a reentrancy guard to allow
8686
* legitimate use cases where targets call it during notifications (e.g., to claim pending issuance
8787
* before allocation changes). This is safe because distributeIssuance() has built-in block-tracking
8888
* protection (preventing double-distribution in the same block), makes no external calls that could
@@ -109,7 +109,7 @@ contract IssuanceAllocator is
109109
/// @param issuancePerBlock Total issuance per block across all targets
110110
/// @param lastDistributionBlock Last block when allocator-minting issuance was distributed
111111
/// @param lastSelfMintingBlock Last block when self-minting was advanced
112-
/// @param accumulatedSelfMinting Accumulated self-minting during undistributed periods
112+
/// @param selfMintingOffset Self-minting that offsets allocator-minting budget (accumulates during pause, clears on distribution)
113113
/// @param allocationTargets Mapping of target addresses to their allocation data
114114
/// @param targetAddresses Array of all target addresses (including default target at index 0)
115115
/// @param totalSelfMintingRate Total self-minting rate (tokens per block) across all targets
@@ -122,7 +122,7 @@ contract IssuanceAllocator is
122122
uint256 issuancePerBlock;
123123
uint256 lastDistributionBlock;
124124
uint256 lastSelfMintingBlock;
125-
uint256 accumulatedSelfMinting;
125+
uint256 selfMintingOffset;
126126
mapping(address => AllocationTarget) allocationTargets;
127127
address[] targetAddresses;
128128
uint256 totalSelfMintingRate;
@@ -239,10 +239,11 @@ contract IssuanceAllocator is
239239
* @param _governor Address that will have the GOVERNOR_ROLE
240240
* @dev Initializes with a default target at index 0 set to address(0)
241241
* @dev default target will receive all unallocated issuance (initially 0 until rate is set)
242-
* @dev Security: lastDistributionBlock and lastSelfMintingBlock default to 0. First distribution
242+
* @dev Accounting: lastDistributionBlock and lastSelfMintingBlock default to 0. First distribution
243243
* call will calculate for all blocks from 0 to block.number, which is safe because issuancePerBlock
244244
* is 0 at initialization. Once setIssuancePerBlock() is called, it triggers _distributeIssuance()
245245
* which updates lastDistributionBlock to current block, preventing large block ranges in future calls.
246+
* Governance must exercise caution when changing issuancePerBlock while paused to ensure applied to correct block range, see setIssuancePerBlock() documentation.
246247
*/
247248
function initialize(address _governor) external virtual initializer {
248249
__BaseUpgradeable_init(_governor);
@@ -317,7 +318,7 @@ contract IssuanceAllocator is
317318
// Once accumulation starts (during pause), continue through any unpaused periods
318319
// until distribution clears the accumulation. This is conservative and allows
319320
// better recovery when distribution is delayed through pause/unpause cycles.
320-
if (paused() || 0 < $.accumulatedSelfMinting) $.accumulatedSelfMinting += $.totalSelfMintingRate * blocks;
321+
if (paused() || 0 < $.selfMintingOffset) $.selfMintingOffset += $.totalSelfMintingRate * blocks;
321322
$.lastSelfMintingBlock = block.number;
322323

323324
// Emit self-minting allowance events
@@ -350,7 +351,7 @@ contract IssuanceAllocator is
350351

351352
if (paused()) return $.lastDistributionBlock;
352353

353-
if (0 < $.accumulatedSelfMinting) return _distributePendingIssuance(block.number);
354+
if (0 < $.selfMintingOffset) return _distributePendingIssuance(block.number);
354355
else return _performNormalDistribution();
355356
}
356357

@@ -439,9 +440,9 @@ contract IssuanceAllocator is
439440
// ~1e33, well below uint256 max (~1e77). Similar multiplications throughout this contract operate
440441
// under the same range assumptions.
441442
uint256 totalForPeriod = $.issuancePerBlock * blocks;
442-
uint256 accumulatedSelfMinting = $.accumulatedSelfMinting;
443+
uint256 selfMintingOffset = $.selfMintingOffset;
443444

444-
uint256 available = accumulatedSelfMinting < totalForPeriod ? totalForPeriod - accumulatedSelfMinting : 0;
445+
uint256 available = selfMintingOffset < totalForPeriod ? totalForPeriod - selfMintingOffset : 0;
445446

446447
if (0 < available) {
447448
// Calculate non-default allocated rate using the allocation invariant.
@@ -463,11 +464,8 @@ contract IssuanceAllocator is
463464
// Update accumulated self-minting after distribution.
464465
// Subtract the period budget used (min of accumulated and totalForPeriod).
465466
// When caught up to current block, clear all since nothing remains to distribute.
466-
if (toBlockNumber == block.number) $.accumulatedSelfMinting = 0;
467-
else
468-
$.accumulatedSelfMinting = totalForPeriod < accumulatedSelfMinting
469-
? accumulatedSelfMinting - totalForPeriod
470-
: 0;
467+
if (toBlockNumber == block.number) $.selfMintingOffset = 0;
468+
else $.selfMintingOffset = totalForPeriod < selfMintingOffset ? selfMintingOffset - totalForPeriod : 0;
471469

472470
return toBlockNumber;
473471
}
@@ -725,36 +723,8 @@ contract IssuanceAllocator is
725723
return _setTargetAllocation(address(target), allocatorMintingRate, selfMintingRate, minDistributedBlock);
726724
}
727725

728-
/**
729-
* @notice Internal implementation for setting target allocation
730-
* @param target Address of the target to update
731-
* @param allocatorMintingRate Allocator-minting rate for the target (tokens per block)
732-
* @param selfMintingRate Self-minting rate for the target (tokens per block)
733-
* @param minDistributedBlock Minimum block number that distribution must have reached
734-
* @return True if the value is applied (including if already the case), false if not applied due to paused state
735-
*/
736-
function _setTargetAllocation(
737-
address target,
738-
uint256 allocatorMintingRate,
739-
uint256 selfMintingRate,
740-
uint256 minDistributedBlock
741-
) internal returns (bool) {
742-
if (!_validateTargetAllocation(target, allocatorMintingRate, selfMintingRate)) return true;
743-
744-
if (_distributeIssuance() < minDistributedBlock) return false;
745-
746-
_notifyTarget(target);
747-
_validateAndUpdateTotalAllocations(target, allocatorMintingRate, selfMintingRate);
748-
_updateTargetAllocationData(target, allocatorMintingRate, selfMintingRate);
749-
750-
emit TargetAllocationUpdated(target, allocatorMintingRate, selfMintingRate);
751-
return true;
752-
}
753-
754726
/**
755727
* @inheritdoc IIssuanceAllocationAdministration
756-
* @dev Delegates to internal implementation with block.number
757-
* TODO: Intead of talking about implementation, talk about behavior that requires distribution to current block
758728
*/
759729
function setDefaultTarget(
760730
address newAddress
@@ -820,6 +790,42 @@ contract IssuanceAllocator is
820790
return true;
821791
}
822792

793+
/**
794+
* @notice Internal implementation for setting target allocation
795+
* @param target Address of the target to update
796+
* @param allocatorMintingRate Allocator-minting rate for the target (tokens per block)
797+
* @param selfMintingRate Self-minting rate for the target (tokens per block)
798+
* @param minDistributedBlock Minimum block number that distribution must have reached
799+
* @return True if the value is applied (including if already the case), false if not applied due to paused state
800+
*/
801+
function _setTargetAllocation(
802+
address target,
803+
uint256 allocatorMintingRate,
804+
uint256 selfMintingRate,
805+
uint256 minDistributedBlock
806+
) internal returns (bool) {
807+
if (!_validateTargetAllocation(target, allocatorMintingRate, selfMintingRate)) return true;
808+
809+
if (_distributeIssuance() < minDistributedBlock) return false;
810+
811+
_notifyTarget(target);
812+
813+
// Total allocation calculation and check is delayed until after notifications.
814+
// Distributing and notifying unnecessarily is harmless, but we need to prevent
815+
// reentrancy from looping and changing allocations mid-calculation.
816+
// (Would not be likely to be exploitable due to only governor being able to
817+
// make a call to set target allocation, but better to be paranoid.)
818+
// Validate totals and auto-adjust default allocation BEFORE updating target data
819+
// so we can read the old allocation values
820+
_validateAndUpdateTotalAllocations(target, allocatorMintingRate, selfMintingRate);
821+
822+
// Then update the target's allocation data
823+
_updateTargetAllocationData(target, allocatorMintingRate, selfMintingRate);
824+
825+
emit TargetAllocationUpdated(target, allocatorMintingRate, selfMintingRate);
826+
return true;
827+
}
828+
823829
/**
824830
* @notice Validates target address and interface support, returns false if allocation is unchanged
825831
* @param target Address of the target to validate
@@ -963,7 +969,7 @@ contract IssuanceAllocator is
963969
DistributionState({
964970
lastDistributionBlock: $.lastDistributionBlock,
965971
lastSelfMintingBlock: $.lastSelfMintingBlock,
966-
accumulatedSelfMinting: $.accumulatedSelfMinting
972+
selfMintingOffset: $.selfMintingOffset
967973
});
968974
}
969975

@@ -1039,27 +1045,15 @@ contract IssuanceAllocator is
10391045
* @dev When default is a real address: returns issuancePerBlock
10401046
* @dev Note: Internally, the contract always maintains 100% allocation invariant, even when default is address(0)
10411047
*/
1042-
function getTotalAllocation() external view override returns (Allocation memory) {
1048+
function getTotalAllocation() external view override returns (Allocation memory allocation) {
10431049
IssuanceAllocatorData storage $ = _getIssuanceAllocatorStorage();
10441050

1045-
uint256 totalAllocatorMinting = $.issuancePerBlock - $.totalSelfMintingRate;
1046-
uint256 totalAllocation = $.issuancePerBlock;
1047-
10481051
// If default is address(0), exclude its allocation from reported totals
1049-
// since it doesn't actually receive minting (effectively unallocated)
1050-
address defaultAddress = $.targetAddresses[0];
1051-
if (defaultAddress == address(0)) {
1052-
AllocationTarget storage defaultTarget = $.allocationTargets[defaultAddress];
1053-
uint256 defaultAllocation = defaultTarget.allocatorMintingRate;
1054-
totalAllocatorMinting -= defaultAllocation;
1055-
totalAllocation -= defaultAllocation;
1056-
}
1057-
1058-
return
1059-
Allocation({
1060-
totalAllocationRate: totalAllocation,
1061-
allocatorMintingRate: totalAllocatorMinting,
1062-
selfMintingRate: $.totalSelfMintingRate
1063-
});
1052+
// since it doe not receive minting (so it is considered unallocated).
1053+
// Address(0) will only have non-zero allocation when it is the default target,
1054+
// so we can directly subtract zero address allocation.
1055+
allocation.totalAllocationRate = $.issuancePerBlock - $.allocationTargets[address(0)].allocatorMintingRate;
1056+
allocation.selfMintingRate = $.totalSelfMintingRate;
1057+
allocation.allocatorMintingRate = allocation.totalAllocationRate - allocation.selfMintingRate;
10641058
}
10651059
}

0 commit comments

Comments
 (0)