Skip to content

Commit 4cb9e81

Browse files
committed
improve gas efficiency in some places
1 parent adeb468 commit 4cb9e81

File tree

2 files changed

+72
-61
lines changed

2 files changed

+72
-61
lines changed

contracts/src/Payer.sol

+67-57
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ contract Payer is
3737

3838
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
3939
string internal constant USDC_SYMBOL = "USDC";
40+
uint8 private constant PAYER_OPERATOR_ID = 1;
4041
uint64 private constant DEFAULT_MINIMUM_REGISTRATION_AMOUNT_MICRO_DOLLARS = 10_000_000; // 10 USD
4142
uint64 private constant DEFAULT_MINIMUM_DEPOSIT_AMOUNT_MICRO_DOLLARS = 10_000_000; // 10 USD
4243
uint64 private constant DEFAULT_MAX_TOLERABLE_DEBT_AMOUNT_MICRO_DOLLARS = 50_000_000; // 50 USD
@@ -73,6 +74,7 @@ contract Payer is
7374
EnumerableSet.AddressSet activePayers;
7475
EnumerableSet.AddressSet debtPayers;
7576
}
77+
// TODO: pack struct
7678

7779
// keccak256(abi.encode(uint256(keccak256("xmtp.storage.Payer")) - 1)) & ~bytes32(uint256(0xff))
7880
bytes32 internal constant PAYER_STORAGE_LOCATION =
@@ -90,20 +92,16 @@ contract Payer is
9092
/**
9193
* @dev Modifier to check if caller is an active node operator.
9294
*/
93-
modifier onlyNodeOperator() {
94-
if (!_getIsActiveNodeOperator(msg.sender)) {
95-
revert UnauthorizedNodeOperator();
96-
}
95+
modifier onlyNodeOperator(uint256 nodeId) {
96+
require(_getIsActiveNodeOperator(nodeId), UnauthorizedNodeOperator());
9797
_;
9898
}
9999

100100
/**
101101
* @dev Modifier to check if caller is the payer report contract.
102102
*/
103103
modifier onlyPayerReport() {
104-
if (msg.sender != _getPayerStorage().payerReportContract) {
105-
revert Unauthorized();
106-
}
104+
require(msg.sender == _getPayerStorage().payerReportContract, Unauthorized());
107105
_;
108106
}
109107

@@ -158,7 +156,8 @@ contract Payer is
158156
PayerStorage storage $ = _getPayerStorage();
159157

160158
require(amount >= $.minimumRegistrationAmountMicroDollars, InsufficientAmount());
161-
require(!_payerExists(msg.sender), PayerAlreadyRegistered());
159+
160+
if (_payerExists(msg.sender)) revert PayerAlreadyRegistered();
162161

163162
_deposit(msg.sender, amount);
164163

@@ -185,46 +184,30 @@ contract Payer is
185184
* @inheritdoc IPayer
186185
*/
187186
function deposit(uint256 amount) external whenNotPaused nonReentrant onlyPayer(msg.sender) {
188-
PayerStorage storage $ = _getPayerStorage();
189-
190-
require(amount >= $.minimumDepositAmountMicroDollars, InsufficientAmount());
191-
require($.withdrawals[msg.sender].requestTimestamp == 0, PayerInWithdrawal());
192-
193-
_deposit(msg.sender, amount);
194-
195-
_updatePayerBalance(msg.sender, amount);
196-
197-
emit PayerBalanceUpdated(msg.sender, $.payers[msg.sender].balance, $.payers[msg.sender].debtAmount);
187+
_validateAndProcessDeposit(msg.sender, msg.sender, amount);
198188
}
199189

200190
/**
201191
* @inheritdoc IPayer
202192
*/
203193
function donate(address payer, uint256 amount) external whenNotPaused {
204-
require(amount > 0, InsufficientAmount());
205194
_revertIfPayerDoesNotExist(payer);
206195

196+
_validateAndProcessDeposit(msg.sender, payer, amount);
207197
PayerStorage storage $ = _getPayerStorage();
208198

209-
require($.withdrawals[payer].requestTimestamp == 0, PayerInWithdrawal());
210-
211-
_deposit(msg.sender, amount);
212-
213-
_updatePayerBalance(payer, amount);
214-
215199
$.payers[payer].latestDonationTimestamp = block.timestamp;
216200

217-
emit PayerBalanceUpdated(payer, $.payers[payer].balance, $.payers[payer].debtAmount);
218201
emit Donation(msg.sender, payer, amount);
219202
}
220203

221204
/**
222205
* @inheritdoc IPayer
223206
*/
224-
function deactivatePayer(address payer) external whenNotPaused onlyNodeOperator {
207+
function deactivatePayer(uint256 nodeId, address payer) external whenNotPaused onlyNodeOperator(nodeId) {
225208
_revertIfPayerDoesNotExist(payer);
226209

227-
_deactivatePayer(payer);
210+
_deactivatePayer(nodeId, payer);
228211
}
229212

230213
/**
@@ -237,7 +220,9 @@ contract Payer is
237220

238221
require($.withdrawals[payer].requestTimestamp == 0, PayerInWithdrawal());
239222

240-
if ($.payers[payer].balance > 0 || $.payers[payer].debtAmount > 0) {
223+
Payer memory _storedPayer = $.payers[payer];
224+
225+
if (_storedPayer.balance > 0 || _storedPayer.debtAmount > 0) {
241226
revert PayerHasBalanceOrDebt();
242227
}
243228

@@ -259,8 +244,10 @@ contract Payer is
259244

260245
PayerStorage storage $ = _getPayerStorage();
261246

262-
require($.payers[msg.sender].debtAmount == 0, PayerHasDebt());
263-
require($.payers[msg.sender].balance >= amount, InsufficientBalance());
247+
Payer memory _storedPayer = $.payers[msg.sender];
248+
249+
require(_storedPayer.debtAmount == 0, PayerHasDebt());
250+
require(_storedPayer.balance >= amount, InsufficientBalance());
264251

265252
// Balance to be withdrawn is deducted from the payer's balance,
266253
// it can't be used to settle payments.
@@ -318,7 +305,7 @@ contract Payer is
318305
$.usdcToken.safeTransfer(msg.sender, _finalWithdrawalAmount);
319306
}
320307

321-
emit WithdrawalFinalized(msg.sender, _withdrawal.requestTimestamp);
308+
emit WithdrawalFinalized(msg.sender, _withdrawal.requestTimestamp, _finalWithdrawalAmount);
322309
}
323310

324311
/**
@@ -345,25 +332,24 @@ contract Payer is
345332

346333
PayerStorage storage $ = _getPayerStorage();
347334

348-
uint256 _fees = 0;
335+
uint256 _settledFees = 0;
336+
uint256 _pendingFees = $.pendingFees;
349337

350338
for (uint256 i = 0; i < payerList.length; i++) {
351339
address payer = payerList[i];
352340
uint256 usage = usageAmountsList[i];
353341

354342
// This should never happen, as PayerReport has already verified the payers and amounts.
355343
// Payers in payerList should always exist and be active.
356-
if (!_payerExists(payer) || !_payerIsActive(payer)) {
357-
continue;
358-
}
344+
if (!_payerExists(payer) || !_payerIsActive(payer)) continue;
359345

360346
Payer memory _storedPayer = $.payers[payer];
361347

362348
if (_storedPayer.balance < usage) {
363349
uint256 _debt = usage - _storedPayer.balance;
364350

365-
$.pendingFees += _storedPayer.balance;
366-
_fees += _storedPayer.balance;
351+
_settledFees += _storedPayer.balance;
352+
_pendingFees += _storedPayer.balance;
367353

368354
_storedPayer.balance = 0;
369355
_storedPayer.debtAmount = _debt;
@@ -372,15 +358,15 @@ contract Payer is
372358
_addDebtor(payer);
373359
_increaseTotalDebtAmount(_debt);
374360

375-
if (_debt > $.maxTolerableDebtAmountMicroDollars) _deactivatePayer(payer);
361+
if (_debt > $.maxTolerableDebtAmountMicroDollars) _deactivatePayer(PAYER_OPERATOR_ID, payer);
376362

377363
emit PayerBalanceUpdated(payer, _storedPayer.balance, _storedPayer.debtAmount);
378364

379365
continue;
380366
}
381367

382-
$.pendingFees += usage;
383-
_fees += usage;
368+
_settledFees += usage;
369+
_pendingFees += usage;
384370

385371
_storedPayer.balance -= usage;
386372

@@ -389,7 +375,9 @@ contract Payer is
389375
emit PayerBalanceUpdated(payer, _storedPayer.balance, _storedPayer.debtAmount);
390376
}
391377

392-
emit UsageSettled(originatorNode, block.timestamp, _fees);
378+
$.pendingFees = _pendingFees;
379+
380+
emit UsageSettled(originatorNode, block.timestamp, _settledFees);
393381
}
394382

395383
/**
@@ -404,17 +392,17 @@ contract Payer is
404392
// slither-disable-next-line timestamp
405393
require(block.timestamp - $.lastFeeTransferTimestamp >= $.transferFeesPeriod, InsufficientTimePassed());
406394

407-
require($.pendingFees > 0, InsufficientAmount());
395+
uint256 _pendingFeesAmount = $.pendingFees;
408396

409-
uint256 _feesToTransfer = $.pendingFees;
397+
require(_pendingFeesAmount > 0, InsufficientAmount());
410398

411-
$.usdcToken.safeTransfer($.distributionContract, _feesToTransfer);
399+
$.usdcToken.safeTransfer($.distributionContract, _pendingFeesAmount);
412400

413401
$.lastFeeTransferTimestamp = block.timestamp;
414-
$.collectedFees += $.pendingFees;
402+
$.collectedFees += _pendingFeesAmount;
415403
$.pendingFees = 0;
416404

417-
emit FeesTransferred(block.timestamp, _feesToTransfer);
405+
emit FeesTransferred(block.timestamp, _pendingFeesAmount);
418406
}
419407

420408
/* ========== Administrative Functions ========== */
@@ -700,6 +688,24 @@ contract Payer is
700688

701689
/* ============ Internal ============ */
702690

691+
/**
692+
* @notice Validates and processes a deposit or donation
693+
* @param from The address funds are coming from
694+
* @param to The payer account receiving the deposit
695+
* @param amount The amount to deposit
696+
*/
697+
function _validateAndProcessDeposit(address from, address to, uint256 amount) internal {
698+
PayerStorage storage $ = _getPayerStorage();
699+
700+
require(amount >= $.minimumDepositAmountMicroDollars, InsufficientAmount());
701+
require($.withdrawals[to].requestTimestamp == 0, PayerInWithdrawal());
702+
703+
_deposit(from, amount);
704+
_updatePayerBalance(to, amount);
705+
706+
emit PayerBalanceUpdated(to, $.payers[to].balance, $.payers[to].debtAmount);
707+
}
708+
703709
/**
704710
* @notice Deposits USDC from a payer to the contract.
705711
* @param payer The address of the payer.
@@ -720,11 +726,16 @@ contract Payer is
720726
function _updatePayerBalance(address payerAddress, uint256 amount) internal returns (uint256 leftoverAmount) {
721727
PayerStorage storage $ = _getPayerStorage();
722728

723-
if ($.payers[payerAddress].debtAmount > 0) {
729+
Payer memory _payer = $.payers[payerAddress];
730+
731+
if (_payer.debtAmount > 0) {
724732
return _settleDebts(payerAddress, amount);
725733
} else {
726-
$.payers[payerAddress].balance += amount;
734+
_payer.balance += amount;
727735
_increaseTotalAmountDeposited(amount);
736+
737+
$.payers[payerAddress] = _payer;
738+
728739
return amount;
729740
}
730741
}
@@ -787,15 +798,15 @@ contract Payer is
787798
* @notice Deactivates a payer.
788799
* @param payer The address of the payer to deactivate.
789800
*/
790-
function _deactivatePayer(address payer) internal {
801+
function _deactivatePayer(uint256 operatorId, address payer) internal {
791802
PayerStorage storage $ = _getPayerStorage();
792803

793804
$.payers[payer].isActive = false;
794805

795806
// Deactivating a payer only removes them from the active payers set
796807
require($.activePayers.remove(payer), FailedToDeactivatePayer());
797808

798-
emit PayerDeactivated(payer);
809+
emit PayerDeactivated(operatorId, payer);
799810
}
800811

801812
/**
@@ -849,17 +860,16 @@ contract Payer is
849860

850861
/**
851862
* @notice Checks if a given address is an active node operator.
852-
* @param operator The address to check.
863+
* @param nodeId The nodeID of the operator to check.
853864
* @return isActiveNodeOperator True if the address is an active node operator, false otherwise.
854865
*/
855-
function _getIsActiveNodeOperator(address operator) internal view returns (bool isActiveNodeOperator) {
866+
function _getIsActiveNodeOperator(uint256 nodeId) internal view returns (bool isActiveNodeOperator) {
856867
INodes nodes = INodes(_getPayerStorage().nodesContract);
857868

858-
require(address(nodes) != address(0), Unauthorized());
869+
require(msg.sender == nodes.ownerOf(nodeId), Unauthorized());
859870

860-
// TODO: Implement this in Nodes contract
861-
// return nodes.isActiveNodeOperator(operator);
862-
return true;
871+
// TODO: Change for a better filter.
872+
return nodes.getReplicationNodeIsActive(nodeId);
863873
}
864874

865875
/**

contracts/src/interfaces/IPayer.sol

+5-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ interface IPayerEvents {
3333
event PayerBalanceUpdated(address indexed payer, uint256 newBalance, uint256 newDebtAmount);
3434

3535
/// @dev Emitted when a payer is deactivated by an owner.
36-
event PayerDeactivated(address indexed payer);
36+
event PayerDeactivated(uint256 indexed operatorId, address indexed payer);
3737

3838
/// @dev Emitted when a payer is permanently deleted from the system.
3939
event PayerDeleted(address indexed payer, uint256 timestamp);
@@ -60,7 +60,7 @@ interface IPayerEvents {
6060
event WithdrawalCancelled(address indexed payer, uint256 indexed requestTimestamp);
6161

6262
/// @dev Emitted when a payer's withdrawal is finalized.
63-
event WithdrawalFinalized(address indexed payer, uint256 indexed requestTimestamp);
63+
event WithdrawalFinalized(address indexed payer, uint256 indexed requestTimestamp, uint256 amount);
6464

6565
/// @dev Emitted when the withdrawal lock period is updated.
6666
event WithdrawalLockPeriodSet(uint256 oldWithdrawalLockPeriod, uint256 newWithdrawalLockPeriod);
@@ -256,11 +256,12 @@ interface IPayer is IERC165, IPayerEvents, IPayerErrors {
256256
/**
257257
* @notice Deactivates a payer, signaling XMTP nodes they should not accept messages from them.
258258
* Only callable by authorized node operators.
259-
* @param payer The address of the payer to deactivate.
259+
* @param operatorId The ID of the operator calling the function.
260+
* @param payer The address of the payer to deactivate.
260261
*
261262
* Emits `PayerDeactivated`.
262263
*/
263-
function deactivatePayer(address payer) external;
264+
function deactivatePayer(uint256 operatorId, address payer) external;
264265

265266
/**
266267
* @notice Permanently deletes a payer from the system.

0 commit comments

Comments
 (0)