Skip to content

Commit

Permalink
gas optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
d10r committed Dec 5, 2024
1 parent f1d3270 commit 9e93ba5
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1348,8 +1348,7 @@ contract ConstantFlowAgreementV1 is
// do not enforce balance checks during callbacks for the appCreditToken
if (currentContext.callType != ContextDefinitions.CALL_INFO_CALL_TYPE_APP_CALLBACK ||
currentContext.appCreditToken != token) {
(int256 availableBalance,,) = token.realtimeBalanceOf(flowSender, currentContext.timestamp);
if (availableBalance < 0) {
if (! token.hasRealtimeBalanceOfAtLeast(flowSender, currentContext.timestamp, 0)) {
revert CFA_INSUFFICIENT_BALANCE();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,38 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
owedBuffer = 0;
}

function hasRealtimeBalanceOfAtLeast(ISuperfluidToken token, address account, uint256 time, int256 minBalance)
public view override returns (bool)
{
UniversalIndexData memory universalIndexData = _getUIndexData(abi.encode(token), account);

int256 balance;
if (_isPool(token, account)) {
balance = ISuperfluidPool(account).getDisconnectedBalance(uint32(time));
} else {
// this is outflow and can only be negative or 0
balance = Value.unwrap(_getBasicParticleFromUIndex(universalIndexData).rtb(Time.wrap(uint32(time))));
}
// subtract buffer
balance -= universalIndexData.totalBuffer.toInt256();

{
if (balance >= minBalance) {
return true; // it can only increase from here, so we can stop calculating
}
(uint32[] memory slotIds, bytes32[] memory pidList) = _listPoolConnectionIds(token, account);
for (uint256 i = 0; i < slotIds.length; ++i) {
address pool = address(uint160(uint256(pidList[i])));
(bool exist, PoolMemberData memory poolMemberData) =
_getPoolMemberData(token, account, ISuperfluidPool(pool));
assert(exist);
assert(poolMemberData.pool == pool);
balance += ISuperfluidPool(pool).getClaimable(account, uint32(time));
}
}
return balance >= minBalance;
}

/// @dev ISuperAgreement.realtimeBalanceOf implementation
function realtimeBalanceOfNow(ISuperfluidToken token, address account)
external
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,17 @@ abstract contract IGeneralDistributionAgreementV1 is ISuperAgreement {
view
virtual
returns (bool);


function hasRealtimeBalanceOfAtLeast(
ISuperfluidToken token,
address account,
uint256 time,
int256 minAmount
)
external
view
virtual
returns (bool);

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,4 @@ interface ISuperAgreement {
uint256 deposit,
uint256 owedDeposit
);

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ interface ISuperfluidToken {
/**
* @dev Encoded liquidation type data mainly used for handling stack to deep errors
*
* @custom:note
* @custom:note
* - version: 1
* - liquidationType key:
* - 0 = reward account receives reward (PIC period)
Expand Down Expand Up @@ -83,6 +83,10 @@ interface ISuperfluidToken {
uint256 owedDeposit,
uint256 timestamp);

function hasRealtimeBalanceOfAtLeast(address account, uint256 timestamp, int256 minBalance)
external view
returns (bool);

/**
* @notice Check if account is critical
* @dev A critical account is when availableBalance < 0
Expand Down Expand Up @@ -231,7 +235,7 @@ interface ISuperfluidToken {
* @dev Update agreement state slot
* @param account Account to be updated
*
* @custom:note
* @custom:note
* - To clear the storage out, provide zero-ed array of intended length
*/
function updateAgreementStateSlot(
Expand Down Expand Up @@ -274,7 +278,7 @@ interface ISuperfluidToken {
* @param account Account to query.
* @param delta Amount of balance delta to be settled
*
* @custom:modifiers
* @custom:modifiers
* - onlyAgreement
*/
function settleBalance(
Expand All @@ -293,7 +297,7 @@ interface ISuperfluidToken {
* @param rewardAmount The amount the rewarded account will receive
* @param targetAccountBalanceDelta The delta amount the target account balance should change by
*
* @custom:note
* @custom:note
* - If a bailout is required (bailoutAmount > 0)
* - the actual reward (single deposit) goes to the executor,
* - while the reward account becomes the bailout account
Expand All @@ -303,7 +307,7 @@ interface ISuperfluidToken {
* - the targetAccount will pay the rewardAmount
* - the liquidator (reward account in PIC period) will receive the rewardAmount
*
* @custom:modifiers
* @custom:modifiers
* - onlyAgreement
*/
function makeLiquidationPayoutsV2
Expand All @@ -327,7 +331,7 @@ interface ISuperfluidToken {
* @param targetAccountBalanceDelta The amount the sender account balance should change by
* @param liquidationTypeData The encoded liquidation type data including the version (how to decode)
*
* @custom:note
* @custom:note
* Reward account rule:
* - if the agreement is liquidated during the PIC period
* - the rewardAmountReceiver will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount
Expand Down Expand Up @@ -412,7 +416,7 @@ interface ISuperfluidToken {
*
* @custom:deprecated Use AgreementLiquidatedV2 instead
*
* @custom:note
* @custom:note
* Reward account rule:
* - if bailout is equal to 0, then
* - the bondAccount will get the rewardAmount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
ISuperfluid,
ISuperAgreement,
ISuperfluidGovernance,
ISuperfluidToken
ISuperfluidToken,
IGeneralDistributionAgreementV1
} from "../interfaces/superfluid/ISuperfluid.sol";
import { FixedSizeData } from "../libs/FixedSizeData.sol";

Expand Down Expand Up @@ -105,6 +106,49 @@ abstract contract SuperfluidToken is ISuperfluidToken
}
}

function hasRealtimeBalanceOfAtLeast(
address account,
uint256 timestamp,
int256 minBalance
)
public view virtual override
returns (bool)
{
int256 availableBalance = _sharedSettledBalances[account];
ISuperAgreement[] memory activeAgreements = getAccountActiveAgreements(account);
IGeneralDistributionAgreementV1 gda;
for (uint256 i = 0; i < activeAgreements.length; ++i) {
if (activeAgreements[i].agreementType() ==
keccak256("org.superfluid-finance.agreements.GeneralDistributionAgreement.v1"))
{
gda = IGeneralDistributionAgreementV1(address(activeAgreements[i]));
continue;
} else {
(
int256 agreementDynamicBalance,
uint256 agreementDeposit,
uint256 agreementOwedDeposit) = activeAgreements[i]
.realtimeBalanceOf(
this,
account,
timestamp
);

availableBalance = availableBalance
+ agreementDynamicBalance
- (
agreementDeposit > agreementOwedDeposit ?
(agreementDeposit - agreementOwedDeposit) : 0
).toInt256();
}
}
if (address(gda) != address(0)) {
return gda.hasRealtimeBalanceOfAtLeast(this, account, timestamp, minBalance - availableBalance);
}

return availableBalance >= minBalance;
}

/// @dev ISuperfluidToken.realtimeBalanceOfNow implementation
function realtimeBalanceOfNow(
address account
Expand Down Expand Up @@ -211,8 +255,7 @@ abstract contract SuperfluidToken is ISuperfluidToken
)
internal
{
(int256 availableBalance,,) = realtimeBalanceOf(from, _host.getNow());
if (availableBalance < amount) {
if (! hasRealtimeBalanceOfAtLeast(from, _host.getNow(), amount)) {
revert SF_TOKEN_MOVE_INSUFFICIENT_BALANCE();
}
_sharedSettledBalances[from] = _sharedSettledBalances[from] - amount;
Expand Down

0 comments on commit 9e93ba5

Please sign in to comment.