Contract
0xA794C9ee519FD31BbCE643e8D8138f735E97D1DB
8
Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xee701d9f9131d75cacbb983c498f54c4b5f1fc486614c29b6a76da6fc092e2c2 | Castrate | 27384679 | 128 days 12 hrs ago | 0xd15d5d0f5b1b56a4daef75cfe108cb825e97d015 | IN | 0xa794c9ee519fd31bbce643e8d8138f735e97d1db | 0 ETH | 0.00031444 | |
0xe55b3f6cbed7b51724cbf3eabdae3ddbee981562a22f21bfe30477a83bcad5d6 | 0x60a06040 | 23778375 | 148 days 7 hrs ago | 0xd15d5d0f5b1b56a4daef75cfe108cb825e97d015 | IN | Create: InstantDistributionAgreementV1 | 0 ETH | 0.06733046 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
InstantDistributionAgreementV1
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.16; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { IInstantDistributionAgreementV1, ISuperfluidToken, SuperfluidErrors } from "../interfaces/agreements/IInstantDistributionAgreementV1.sol"; import { ISuperfluid, ISuperfluidGovernance, ISuperApp, SuperAppDefinitions } from "../interfaces/superfluid/ISuperfluid.sol"; import { AgreementBase } from "./AgreementBase.sol"; import { SlotsBitmapLibrary } from "../libs/SlotsBitmapLibrary.sol"; import { AgreementLibrary } from "./AgreementLibrary.sol"; /** * @title InstantDistributionAgreementV1 contract * @author Superfluid * @dev Please read IInstantDistributionAgreementV1 for implementation notes. * @dev For more technical notes, please visit protocol-monorepo wiki area. * */ contract InstantDistributionAgreementV1 is AgreementBase, IInstantDistributionAgreementV1 { using SafeCast for uint256; address public constant SLOTS_BITMAP_LIBRARY_ADDRESS = address(SlotsBitmapLibrary); /// @dev Subscriber state slot id for storing subs bitmap uint256 private constant _SUBSCRIBER_SUBS_BITMAP_STATE_SLOT_ID = 0; /// @dev Publisher state slot id for storing its deposit amount uint256 private constant _PUBLISHER_DEPOSIT_STATE_SLOT_ID = 1 << 32; /// @dev Subscriber state slot id starting ptoint for subscription data uint256 private constant _SUBSCRIBER_SUB_DATA_STATE_SLOT_ID_START = 1 << 128; /// @dev Maximum number of subscriptions a subscriber can have uint32 private constant _MAX_NUM_SUBS = 256; /// @dev A special id that indicating the subscription is not approved yet uint32 private constant _UNALLOCATED_SUB_ID = type(uint32).max; // solhint-disable-next-line no-empty-blocks constructor(ISuperfluid host) AgreementBase(address(host)) {} /// @dev Agreement data for the index struct IndexData { uint128 indexValue; uint128 totalUnitsApproved; uint128 totalUnitsPending; } /// @dev Agreement data for the subscription struct SubscriptionData { uint32 subId; address publisher; uint32 indexId; uint128 indexValue; uint128 units; } /************************************************************************** * ISuperAgreement interface *************************************************************************/ /// @dev ISuperAgreement.realtimeBalanceOf implementation function realtimeBalanceOf( ISuperfluidToken token, address account, uint256 /*time*/ ) external view override returns ( int256 dynamicBalance, uint256 deposit, uint256 owedDeposit ) { // as a subscriber // read all subs and calculate the real-time balance uint32[] memory slotIds; bytes32[] memory sidList; (slotIds, sidList) = _listSubscriptionIds(token, account); for (uint32 i = 0; i < sidList.length; ++i) { bool exist; SubscriptionData memory sdata; bytes32 iId; { uint32 subId = slotIds[i]; (exist, sdata) = _getSubscriptionData(token, sidList[i]); assert(exist); assert(sdata.subId == subId); iId = token.getAgreementStateSlot( address(this), account, _SUBSCRIBER_SUB_DATA_STATE_SLOT_ID_START + subId, 1)[0]; } { IndexData memory idata; (exist, idata) = _getIndexData(token, iId); assert(exist); dynamicBalance = dynamicBalance + ( // NOTE casting these values to int256 is okay because the original values // are uint128 int256(uint256(idata.indexValue - sdata.indexValue)) * int256(uint256(sdata.units)) ); } } // as a publisher // calculate the deposits due to pending subscriptions deposit = _getPublisherDeposit(token, account); owedDeposit = 0; } /************************************************************************** * Index operations *************************************************************************/ /// @dev IInstantDistributionAgreementV1.createIndex implementation function createIndex( ISuperfluidToken token, uint32 indexId, bytes calldata ctx ) external override returns(bytes memory newCtx) { ISuperfluid.Context memory context = AgreementLibrary.authorizeTokenAccess(token, ctx); address publisher = context.msgSender; bytes32 iId = _getPublisherId(publisher, indexId); if (_hasIndexData(token, iId)) { revert SuperfluidErrors.ALREADY_EXISTS(SuperfluidErrors.IDA_INDEX_ALREADY_EXISTS); } token.createAgreement(iId, _encodeIndexData(IndexData(0, 0, 0))); emit IndexCreated(token, publisher, indexId, context.userData); // nothing to be recorded so far newCtx = ctx; } /// @dev IInstantDistributionAgreementV1.getIndex implementation function getIndex( ISuperfluidToken token, address publisher, uint32 indexId ) external view override returns ( bool exist, uint128 indexValue, uint128 totalUnitsApproved, uint128 totalUnitsPending) { IndexData memory idata; bytes32 iId = _getPublisherId(publisher, indexId); (exist, idata) = _getIndexData(token, iId); if (exist) { indexValue = idata.indexValue; totalUnitsApproved = idata.totalUnitsApproved; totalUnitsPending = idata.totalUnitsPending; } } /// @dev IInstantDistributionAgreementV1.calculateDistribution implementation function calculateDistribution( ISuperfluidToken token, address publisher, uint32 indexId, uint256 amount ) external view override returns( uint256 actualAmount, uint128 newIndexValue) { bytes32 iId = _getPublisherId(publisher, indexId); (bool exist, IndexData memory idata) = _getIndexData(token, iId); if (!exist) revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.IDA_INDEX_DOES_NOT_EXIST); uint256 totalUnits = uint256(idata.totalUnitsApproved + idata.totalUnitsPending); uint128 indexDelta = (amount / totalUnits).toUint128(); newIndexValue = idata.indexValue + indexDelta; actualAmount = uint256(indexDelta) * totalUnits; } /// @dev IInstantDistributionAgreementV1.updateIndex implementation function updateIndex( ISuperfluidToken token, uint32 indexId, uint128 indexValue, bytes calldata ctx ) external override returns(bytes memory newCtx) { ISuperfluid.Context memory context = AgreementLibrary.authorizeTokenAccess(token, ctx); address publisher = context.msgSender; (bytes32 iId, IndexData memory idata) = _loadIndexData(token, publisher, indexId); if (indexValue < idata.indexValue) revert IDA_INDEX_SHOULD_GROW(); _updateIndex(token, publisher, indexId, iId, idata, indexValue, context.userData); // nothing to be recorded so far newCtx = ctx; } /// @dev IInstantDistributionAgreementV1.distribute implementation function distribute( ISuperfluidToken token, uint32 indexId, uint256 amount, bytes calldata ctx ) external override returns(bytes memory newCtx) { ISuperfluid.Context memory context = AgreementLibrary.authorizeTokenAccess(token, ctx); address publisher = context.msgSender; (bytes32 iId, IndexData memory idata) = _loadIndexData(token, publisher, indexId); uint256 totalUnits = uint256(idata.totalUnitsApproved + idata.totalUnitsPending); if (totalUnits > 0) { uint128 indexDelta = (amount / totalUnits).toUint128(); _updateIndex(token, publisher, indexId, iId, idata, idata.indexValue + indexDelta, context.userData); } // nothing to be recorded so far newCtx = ctx; } function _updateIndex( ISuperfluidToken token, address publisher, uint32 indexId, bytes32 iId, IndexData memory idata, uint128 newIndexValue, bytes memory userData ) private { // - settle the publisher balance INSTANT-ly (ding ding ding, IDA) // - adjust static balance directly token.settleBalance(publisher, // NOTE casting these values to int256 is okay because the original values // are uint128 (-int256(uint256(newIndexValue - idata.indexValue))) * int256(uint256(idata.totalUnitsApproved))); // - adjust the publisher's deposit amount _adjustPublisherDeposit(token, publisher, // NOTE casting these values to int256 is okay because the original values // are uint128 int256(uint256(newIndexValue - idata.indexValue)) * int256(uint256(idata.totalUnitsPending))); // adjust the publisher's index data uint128 oldIndexValue = idata.indexValue; idata.indexValue = newIndexValue; token.updateAgreementData(iId, _encodeIndexData(idata)); emit IndexUpdated( token, publisher, indexId, oldIndexValue, newIndexValue, idata.totalUnitsPending, idata.totalUnitsApproved, userData); // check account solvency if (token.isAccountCriticalNow(publisher)) { revert SuperfluidErrors.INSUFFICIENT_BALANCE(SuperfluidErrors.IDA_INSUFFICIENT_BALANCE); } } function _loadIndexData( ISuperfluidToken token, address publisher, uint32 indexId) private view returns ( bytes32 iId, IndexData memory idata ) { bool exist; iId = _getPublisherId(publisher, indexId); (exist, idata) = _getIndexData(token, iId); if (!exist) revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.IDA_INDEX_DOES_NOT_EXIST); } /************************************************************************** * Subscription operations *************************************************************************/ // Stack variables to avoid stack too deep errors in some functions // solhint-disable-next-line contract-name-camelcase struct _SubscriptionOperationVars { bytes32 iId; bool subscriptionExists; bytes32 sId; IndexData idata; SubscriptionData sdata; bytes cbdata; } /// @dev IInstantDistributionAgreementV1.approveSubscription implementation function approveSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx ) external override returns(bytes memory newCtx) { _SubscriptionOperationVars memory vars; AgreementLibrary.CallbackInputs memory cbStates; address subscriber; bytes memory userData; { ISuperfluid.Context memory context = AgreementLibrary.authorizeTokenAccess(token, ctx); subscriber = context.msgSender; userData = context.userData; } ( vars.iId, vars.sId, vars.idata, vars.subscriptionExists, vars.sdata ) = _loadAllData(token, publisher, subscriber, indexId, false); if (vars.subscriptionExists) { // required condition check if (vars.sdata.subId != _UNALLOCATED_SUB_ID) { revert SuperfluidErrors.ALREADY_EXISTS(SuperfluidErrors.IDA_SUBSCRIPTION_ALREADY_APPROVED); } } newCtx = ctx; cbStates = AgreementLibrary.createCallbackInputs( token, publisher, vars.sId, ""); if (!vars.subscriptionExists) { cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_CREATED_NOOP; vars.cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, newCtx); vars.sdata = SubscriptionData({ publisher: publisher, indexId: indexId, subId: 0, units: 0, indexValue: vars.idata.indexValue }); // add to subscription list of the subscriber vars.sdata.subId = _findAndFillSubsBitmap(token, subscriber, vars.iId); token.createAgreement(vars.sId, _encodeSubscriptionData(vars.sdata)); cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_CREATED_NOOP; (, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, vars.cbdata, newCtx); } else { cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_UPDATED_NOOP; vars.cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, newCtx); // NOTE casting these values to int256 is okay because the original values // are uint128 int balanceDelta = int256(uint256(vars.idata.indexValue - vars.sdata.indexValue)) * int256(uint256(vars.sdata.units)); // update publisher data and adjust publisher's deposits vars.idata.totalUnitsApproved += vars.sdata.units; vars.idata.totalUnitsPending -= vars.sdata.units; token.updateAgreementData(vars.iId, _encodeIndexData(vars.idata)); _adjustPublisherDeposit(token, publisher, -balanceDelta); token.settleBalance(publisher, -balanceDelta); // update subscription data and adjust subscriber's balance token.settleBalance(subscriber, balanceDelta); vars.sdata.indexValue = vars.idata.indexValue; vars.sdata.subId = _findAndFillSubsBitmap(token, subscriber, vars.iId); token.updateAgreementData(vars.sId, _encodeSubscriptionData(vars.sdata)); cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_UPDATED_NOOP; (, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, vars.cbdata, newCtx); } // can index up to three words, hence splitting into two events from publisher or subscriber's view. emit IndexSubscribed(token, publisher, indexId, subscriber, userData); emit SubscriptionApproved(token, subscriber, publisher, indexId, userData); } /// @dev IInstantDistributionAgreementV1.revokeSubscription implementation function revokeSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx ) external override returns(bytes memory newCtx) { _SubscriptionOperationVars memory vars; AgreementLibrary.CallbackInputs memory cbStates; address subscriber; bytes memory userData; { ISuperfluid.Context memory context = AgreementLibrary.authorizeTokenAccess(token, ctx); subscriber = context.msgSender; userData = context.userData; } ( vars.iId, vars.sId, vars.idata, , vars.sdata ) = _loadAllData(token, publisher, subscriber, indexId, true); // should not revoke an pending(un-approved) subscription if (vars.sdata.subId == _UNALLOCATED_SUB_ID) { revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.IDA_SUBSCRIPTION_IS_NOT_APPROVED); } cbStates = AgreementLibrary.createCallbackInputs( token, publisher, vars.sId, ""); newCtx = ctx; cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP; vars.cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, newCtx); // NOTE downcasting these values to int256 is okay because the original values // are uint128 int256 balanceDelta = int256(uint256(vars.idata.indexValue - vars.sdata.indexValue)) * int256(uint256(vars.sdata.units)); vars.idata.totalUnitsApproved = vars.idata.totalUnitsApproved - vars.sdata.units; vars.idata.totalUnitsPending = vars.idata.totalUnitsPending + vars.sdata.units; token.updateAgreementData(vars.iId, _encodeIndexData(vars.idata)); // remove subscription from subscriber's bitmap _clearSubsBitmap(token, subscriber, vars.sdata.subId); // sync pending distributions vars.sdata.indexValue = vars.idata.indexValue; // unlink publisher and subscriber vars.sdata.subId = _UNALLOCATED_SUB_ID; token.updateAgreementData(vars.sId, _encodeSubscriptionData(vars.sdata)); // settle subscriber static balance as a result to keep balance unchanged token.settleBalance(subscriber, balanceDelta); cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP; (, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, vars.cbdata, newCtx); emit IndexUnsubscribed(token, publisher, indexId, subscriber, userData); emit SubscriptionRevoked(token, subscriber, publisher, indexId, userData); } /// @dev IInstantDistributionAgreementV1.updateSubscription implementation function updateSubscription( ISuperfluidToken token, uint32 indexId, address subscriber, uint128 units, bytes calldata ctx ) external override returns(bytes memory newCtx) { if (subscriber == address(0)) { revert SuperfluidErrors.ZERO_ADDRESS(SuperfluidErrors.IDA_ZERO_ADDRESS_SUBSCRIBER); } _SubscriptionOperationVars memory vars; AgreementLibrary.CallbackInputs memory cbStates; bytes memory userData; address publisher; { ISuperfluid.Context memory context = AgreementLibrary.authorizeTokenAccess(token, ctx); userData = context.userData; publisher = context.msgSender; } ( vars.iId, vars.sId, vars.idata, vars.subscriptionExists, vars.sdata ) = _loadAllData(token, publisher, subscriber, indexId, false); cbStates = AgreementLibrary.createCallbackInputs( token, subscriber, vars.sId, ""); newCtx = ctx; // before-hook callback if (vars.subscriptionExists) { cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_UPDATED_NOOP; vars.cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, newCtx); } else { cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_CREATED_NOOP; vars.cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, newCtx); } // update publisher data if (vars.subscriptionExists && vars.sdata.subId != _UNALLOCATED_SUB_ID) { // if the subscription exist and not approved, update the approved units amount // update total units vars.idata.totalUnitsApproved = ( uint256(vars.idata.totalUnitsApproved) + uint256(units) - uint256(vars.sdata.units) ).toUint128(); token.updateAgreementData(vars.iId, _encodeIndexData(vars.idata)); } else if (vars.subscriptionExists) { // if the subscription exists and approved, update the pending units amount // update pending subscription units of the publisher vars.idata.totalUnitsPending = ( uint256(vars.idata.totalUnitsPending) + uint256(units) - uint256(vars.sdata.units) ).toUint128(); token.updateAgreementData(vars.iId, _encodeIndexData(vars.idata)); } else { // if the subscription does not exist, create it and then update the pending units amount // create unallocated subscription vars.sdata = SubscriptionData({ publisher: publisher, indexId: indexId, subId: _UNALLOCATED_SUB_ID, units: units, indexValue: vars.idata.indexValue }); token.createAgreement(vars.sId, _encodeSubscriptionData(vars.sdata)); vars.idata.totalUnitsPending = vars.idata.totalUnitsPending + units; token.updateAgreementData(vars.iId, _encodeIndexData(vars.idata)); } // NOTE casting these values to int256 is okay because the original values // are uint128 int256 balanceDelta = int256(uint256(vars.idata.indexValue - vars.sdata.indexValue)) * int256(uint256(vars.sdata.units)); // adjust publisher's deposit and balances if subscription is pending if (vars.sdata.subId == _UNALLOCATED_SUB_ID) { _adjustPublisherDeposit(token, publisher, -balanceDelta); token.settleBalance(publisher, -balanceDelta); } // settle subscriber static balance token.settleBalance(subscriber, balanceDelta); // update subscription data if necessary if (vars.subscriptionExists) { vars.sdata.indexValue = vars.idata.indexValue; vars.sdata.units = units; token.updateAgreementData(vars.sId, _encodeSubscriptionData(vars.sdata)); } // after-hook callback if (vars.subscriptionExists) { cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_UPDATED_NOOP; (, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, vars.cbdata, newCtx); } else { cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_CREATED_NOOP; (, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, vars.cbdata, newCtx); } emit IndexUnitsUpdated(token, publisher, indexId, subscriber, units, userData); emit SubscriptionUnitsUpdated(token, subscriber, publisher, indexId, units, userData); } /// @dev IInstantDistributionAgreementV1.getSubscription implementation function getSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber ) external view override returns ( bool exist, bool approved, uint128 units, uint256 pendingDistribution ) { bytes32 iId; bytes32 sId; IndexData memory idata; SubscriptionData memory sdata; ( iId, sId, idata, exist, sdata ) = _loadAllData(token, publisher, subscriber, indexId, false); if (!exist) return (false, false, 0, 0); approved = sdata.subId != _UNALLOCATED_SUB_ID; units = sdata.units; pendingDistribution = approved ? 0 : uint256(idata.indexValue - sdata.indexValue) * uint256(sdata.units); } /// @dev IInstantDistributionAgreementV1.getSubscriptionByID implementation function getSubscriptionByID( ISuperfluidToken token, bytes32 agreementId ) external view override returns( address publisher, uint32 indexId, bool approved, uint128 units, uint256 pendingDistribution ) { bool exist; bytes32 iId; IndexData memory idata; SubscriptionData memory sdata; (exist, sdata) = _getSubscriptionData(token, agreementId); if (!exist) { revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.IDA_SUBSCRIPTION_DOES_NOT_EXIST); } publisher = sdata.publisher; indexId = sdata.indexId; iId = _getPublisherId(publisher, indexId); (exist, idata) = _getIndexData(token, iId); assert(exist); approved = sdata.subId != _UNALLOCATED_SUB_ID; units = sdata.units; pendingDistribution = approved ? 0 : uint256(idata.indexValue - sdata.indexValue) * uint256(sdata.units); } /// @dev IInstantDistributionAgreementV1.listSubscriptions implementation function listSubscriptions( ISuperfluidToken token, address subscriber ) external view override returns( address[] memory publishers, uint32[] memory indexIds, uint128[] memory unitsList) { uint32[] memory slotIds; bytes32[] memory sidList; (slotIds, sidList) = _listSubscriptionIds(token, subscriber); bool exist; SubscriptionData memory sdata; publishers = new address[](sidList.length); indexIds = new uint32[](sidList.length); unitsList = new uint128[](sidList.length); for (uint32 i = 0; i < sidList.length; ++i) { uint32 subId = slotIds[i]; bytes32 sId = sidList[i]; (exist, sdata) = _getSubscriptionData(token, sId); assert(exist); assert(sdata.subId == subId); publishers[i] = sdata.publisher; indexIds[i] = sdata.indexId; unitsList[i] = sdata.units; } } /// @dev IInstantDistributionAgreementV1.deleteSubscription implementation function deleteSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx ) external override returns(bytes memory newCtx) { _SubscriptionOperationVars memory vars; AgreementLibrary.CallbackInputs memory cbStates; address sender; bytes memory userData; { ISuperfluid.Context memory context = AgreementLibrary.authorizeTokenAccess(token, ctx); sender = context.msgSender; userData = context.userData; } if (subscriber == address(0)) { revert SuperfluidErrors.ZERO_ADDRESS(SuperfluidErrors.IDA_ZERO_ADDRESS_SUBSCRIBER); } // only publisher can delete a subscription // follows from the invariant that only the publisher // has the ability to modify the units a subscriber has if (sender != publisher) revert IDA_OPERATION_NOT_ALLOWED(); ( vars.iId, vars.sId, vars.idata, , vars.sdata ) = _loadAllData(token, publisher, subscriber, indexId, true); cbStates = AgreementLibrary.createCallbackInputs( token, subscriber, vars.sId, ""); newCtx = ctx; cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP; vars.cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, newCtx); // NOTE casting these values to int256 is okay because the original values // are uint128 int256 balanceDelta = int256(uint256(vars.idata.indexValue - vars.sdata.indexValue)) * int256(uint256(vars.sdata.units)); // update publisher index agreement data if (vars.sdata.subId != _UNALLOCATED_SUB_ID) { vars.idata.totalUnitsApproved = vars.idata.totalUnitsApproved - vars.sdata.units; } else { vars.idata.totalUnitsPending = vars.idata.totalUnitsPending - vars.sdata.units; } token.updateAgreementData(vars.iId, _encodeIndexData(vars.idata)); // remove subscription from subscriber's bitmap if (vars.sdata.subId != _UNALLOCATED_SUB_ID) { _clearSubsBitmap(token, subscriber, vars.sdata.subId); } // move from publisher's deposit to static balance if (vars.sdata.subId == _UNALLOCATED_SUB_ID) { _adjustPublisherDeposit(token, publisher, -balanceDelta); token.settleBalance(publisher, -balanceDelta); } // terminate subscription agreement data token.terminateAgreement(vars.sId, 2); // settle subscriber static balance token.settleBalance(subscriber, balanceDelta); cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP; (, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, vars.cbdata, newCtx); emit IndexUnsubscribed(token, publisher, indexId, subscriber, userData); emit SubscriptionRevoked(token, subscriber, publisher, indexId, userData); emit IndexUnitsUpdated(token, publisher, indexId, subscriber, 0, userData); emit SubscriptionUnitsUpdated(token, subscriber, publisher, indexId, 0, userData); } function claim( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx ) external override returns(bytes memory newCtx) { AgreementLibrary.authorizeTokenAccess(token, ctx); if (subscriber == address(0)) { revert SuperfluidErrors.ZERO_ADDRESS(SuperfluidErrors.IDA_ZERO_ADDRESS_SUBSCRIBER); } _SubscriptionOperationVars memory vars; AgreementLibrary.CallbackInputs memory cbStates; ( vars.iId, vars.sId, vars.idata, , vars.sdata ) = _loadAllData(token, publisher, subscriber, indexId, true); // required condition check if (vars.sdata.subId != _UNALLOCATED_SUB_ID) { revert SuperfluidErrors.ALREADY_EXISTS(SuperfluidErrors.IDA_SUBSCRIPTION_ALREADY_APPROVED); } uint256 pendingDistribution = uint256(vars.idata.indexValue - vars.sdata.indexValue) * uint256(vars.sdata.units); cbStates = AgreementLibrary.createCallbackInputs( token, publisher, vars.sId, ""); newCtx = ctx; if (pendingDistribution > 0) { cbStates.noopBit = SuperAppDefinitions.BEFORE_AGREEMENT_UPDATED_NOOP; vars.cbdata = AgreementLibrary.callAppBeforeCallback(cbStates, newCtx); // adjust publisher's deposits _adjustPublisherDeposit(token, publisher, -int256(pendingDistribution)); token.settleBalance(publisher, -int256(pendingDistribution)); // update subscription data and adjust subscriber's balance vars.sdata.indexValue = vars.idata.indexValue; token.updateAgreementData(vars.sId, _encodeSubscriptionData(vars.sdata)); token.settleBalance(subscriber, int256(pendingDistribution)); emit IndexDistributionClaimed(token, publisher, indexId, subscriber, pendingDistribution); emit SubscriptionDistributionClaimed(token, subscriber, publisher, indexId, pendingDistribution); cbStates.noopBit = SuperAppDefinitions.AFTER_AGREEMENT_UPDATED_NOOP; (, newCtx) = AgreementLibrary.callAppAfterCallback(cbStates, vars.cbdata, newCtx); } else { // nothing to be recorded in this case newCtx = ctx; } } function _loadAllData( ISuperfluidToken token, address publisher, address subscriber, uint32 indexId, bool requireSubscriptionExisting ) private view returns ( bytes32 iId, bytes32 sId, IndexData memory idata, bool subscriptionExists, SubscriptionData memory sdata ) { bool indexExists; iId = _getPublisherId(publisher, indexId); sId = _getSubscriptionId(subscriber, iId); (indexExists, idata) = _getIndexData(token, iId); if (!indexExists) revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.IDA_INDEX_DOES_NOT_EXIST); (subscriptionExists, sdata) = _getSubscriptionData(token, sId); if (requireSubscriptionExisting) { if (!subscriptionExists) { revert SuperfluidErrors.DOES_NOT_EXIST(SuperfluidErrors.IDA_SUBSCRIPTION_DOES_NOT_EXIST); } // sanity check assert(sdata.publisher == publisher); assert(sdata.indexId == indexId); } } /************************************************************************** * internal helpers *************************************************************************/ function _getPublisherId( address publisher, uint32 indexId ) private pure returns (bytes32 iId) { return keccak256(abi.encodePacked("publisher", publisher, indexId)); } function _getSubscriptionId( address subscriber, bytes32 iId ) private pure returns (bytes32 sId) { return keccak256(abi.encodePacked("subscription", subscriber, iId)); } // # Index data operations // // Data packing: // // WORD 1: | existence bit | indexValue | // | 128b | 128b | // WORD 2: | totalUnitsPending | totalUnitsApproved | // | 128b | 12b | function _encodeIndexData( IndexData memory idata ) private pure returns (bytes32[] memory data) { data = new bytes32[](2); data[0] = bytes32( uint256(1 << 128) /* existance bit */ | uint256(idata.indexValue) ); data[1] = bytes32( (uint256(idata.totalUnitsApproved)) | (uint256(idata.totalUnitsPending) << 128) ); } function _hasIndexData( ISuperfluidToken token, bytes32 iId ) private view returns (bool exist) { bytes32[] memory adata = token.getAgreementData(address(this), iId, 2); uint256 a = uint256(adata[0]); exist = a > 0; } function _getIndexData( ISuperfluidToken token, bytes32 iId ) private view returns (bool exist, IndexData memory idata) { bytes32[] memory adata = token.getAgreementData(address(this), iId, 2); uint256 a = uint256(adata[0]); uint256 b = uint256(adata[1]); exist = a > 0; if (exist) { // NOTE We will do an unsafe downcast from uint256 => uint128 // as we know this is safe // see https://gist.github.com/0xdavinchee/9834dc689543f19ec07872ad7d766b09 idata.indexValue = uint128(a); idata.totalUnitsApproved = uint128(b); idata.totalUnitsPending = uint128(b >> 128); } } // # Publisher's deposit amount // // It is stored in state slot in one word function _getPublisherDeposit( ISuperfluidToken token, address publisher ) private view returns (uint256) { bytes32[] memory data = token.getAgreementStateSlot( address(this), publisher, _PUBLISHER_DEPOSIT_STATE_SLOT_ID, 1); return uint256(data[0]); } function _adjustPublisherDeposit( ISuperfluidToken token, address publisher, int256 delta ) private { if (delta == 0) return; bytes32[] memory data = token.getAgreementStateSlot( address(this), publisher, _PUBLISHER_DEPOSIT_STATE_SLOT_ID, 1); data[0] = bytes32(uint256(uint256(data[0]).toInt256() + delta)); token.updateAgreementStateSlot( publisher, _PUBLISHER_DEPOSIT_STATE_SLOT_ID, data); } // # Subscription data operations // // Data packing: // // WORD 1: | publisher | RESERVED | indexId | subId | // | 160b | 32b | 32b | 32b | // WORD 2: | units | indexValue | // | 128b | 128b | function _encodeSubscriptionData( SubscriptionData memory sdata ) private pure returns (bytes32[] memory data) { data = new bytes32[](2); data[0] = bytes32( (uint256(uint160(sdata.publisher)) << (12*8)) | (uint256(sdata.indexId) << 32) | uint256(sdata.subId) ); data[1] = bytes32( uint256(sdata.indexValue) | (uint256(sdata.units) << 128) ); } function _getSubscriptionData( ISuperfluidToken token, bytes32 sId ) private view returns (bool exist, SubscriptionData memory sdata) { bytes32[] memory adata = token.getAgreementData(address(this), sId, 2); uint256 a = uint256(adata[0]); uint256 b = uint256(adata[1]); exist = a > 0; if (exist) { sdata.publisher = address(uint160(a >> (12*8))); sdata.indexId = uint32((a >> 32) & type(uint32).max); sdata.subId = uint32(a & type(uint32).max); // NOTE We will do an unsafe downcast from uint256 => uint128 // as we know this is safe // see https://gist.github.com/0xdavinchee/9834dc689543f19ec07872ad7d766b09 sdata.indexValue = uint128(b); sdata.units = uint128(b >> 128); } } // # Subscription bitmap operations // // ## Subscription bitmap state slot // // slotId: _SUBSCRIBER_SUBS_BITMAP_STATE_SLOT_ID) // // Subscriber can store up to _MAX_NUM_SUBS amount of subscriptions. // For each subscription approved it allocated with a subId with a value in [0, _MAX_NUM_SUBS). // The allocation is to fill one bit in the subscription bitmap. // // ## Subscription reference state slots // // slotId: _SUBSCRIBER_SUB_DATA_STATE_SLOT_ID_START + subId) // // It stores the index data ID. function _findAndFillSubsBitmap( ISuperfluidToken token, address subscriber, bytes32 iId ) private returns (uint32 subId) { return SlotsBitmapLibrary.findEmptySlotAndFill( token, subscriber, _SUBSCRIBER_SUBS_BITMAP_STATE_SLOT_ID, _SUBSCRIBER_SUB_DATA_STATE_SLOT_ID_START, iId); } function _clearSubsBitmap( ISuperfluidToken token, address subscriber, uint32 subId ) private { SlotsBitmapLibrary.clearSlot( token, subscriber, _SUBSCRIBER_SUBS_BITMAP_STATE_SLOT_ID, subId); } function _listSubscriptionIds( ISuperfluidToken token, address subscriber ) private view returns ( uint32[] memory slotIds, bytes32[] memory sidList) { (slotIds, sidList) = SlotsBitmapLibrary.listData( token, subscriber, _SUBSCRIBER_SUBS_BITMAP_STATE_SLOT_ID, _SUBSCRIBER_SUB_DATA_STATE_SLOT_ID_START); // map data to subId for (uint i = 0; i < sidList.length; ++i) { sidList[i] = _getSubscriptionId(subscriber, sidList[i]); } } }
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.16; /** * @title UUPS (Universal Upgradeable Proxy Standard) Shared Library */ library UUPSUtils { /** * @dev Implementation slot constant. * Using https://eips.ethereum.org/EIPS/eip-1967 standard * Storage slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc * (obtained as bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)). */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /// @dev Get implementation address. function implementation() internal view returns (address impl) { assembly { // solium-disable-line impl := sload(_IMPLEMENTATION_SLOT) } } /// @dev Set new implementation address. function setImplementation(address codeAddress) internal { assembly { // solium-disable-line sstore( _IMPLEMENTATION_SLOT, codeAddress ) } } }
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.16; import { UUPSUtils } from "./UUPSUtils.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; /** * @title UUPS (Universal Upgradeable Proxy Standard) Proxiable contract. */ abstract contract UUPSProxiable is Initializable { /** * @dev Get current implementation code address. */ function getCodeAddress() public view returns (address codeAddress) { return UUPSUtils.implementation(); } function updateCode(address newAddress) external virtual; // allows to mark logic contracts as initialized in order to reduce the attack surface // solhint-disable-next-line no-empty-blocks function castrate() external initializer { } /** * @dev Proxiable UUID marker function, this would help to avoid wrong logic * contract to be used for upgrading. * * NOTE: The semantics of the UUID deviates from the actual UUPS standard, * where it is equivalent of _IMPLEMENTATION_SLOT. */ function proxiableUUID() public view virtual returns (bytes32); /** * @dev Update code address function. * It is internal, so the derived contract could setup its own permission logic. */ function _updateCodeAddress(address newAddress) internal { // require UUPSProxy.initializeProxy first require(UUPSUtils.implementation() != address(0), "UUPSProxiable: not upgradable"); require( proxiableUUID() == UUPSProxiable(newAddress).proxiableUUID(), "UUPSProxiable: not compatible logic" ); require( address(this) != newAddress, "UUPSProxiable: proxy loop" ); UUPSUtils.setImplementation(newAddress); emit CodeUpdated(proxiableUUID(), newAddress); } event CodeUpdated(bytes32 uuid, address codeAddress); }
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.16; import {ISuperfluidToken} from "../interfaces/superfluid/ISuperfluidToken.sol"; /** * @title Slots Bitmap library * @author Superfluid * @dev A library implements slots bitmap on Superfluid Token storage * NOTE: * - A slots bitmap allows you to iterate through a list of data efficiently. * - A data slot can be enabled or disabled with the help of bitmap. * - MAX_NUM_SLOTS is 256 in this implementation (using one uint256) * - Superfluid token storage usage: * - getAgreementStateSlot(bitmapStateSlotId) stores the bitmap of enabled data slots * - getAgreementStateSlot(dataStateSlotIDStart + stotId) stores the data of the slot */ library SlotsBitmapLibrary { uint32 internal constant _MAX_NUM_SLOTS = 256; function findEmptySlotAndFill( ISuperfluidToken token, address account, uint256 bitmapStateSlotId, uint256 dataStateSlotIDStart, bytes32 data ) public returns (uint32 slotId) { uint256 subsBitmap = uint256(token.getAgreementStateSlot( address(this), account, bitmapStateSlotId, 1)[0]); for (slotId = 0; slotId < _MAX_NUM_SLOTS; ++slotId) { if ((uint256(subsBitmap >> slotId) & 1) == 0) { // update slot data bytes32[] memory slotData = new bytes32[](1); slotData[0] = data; token.updateAgreementStateSlot( account, dataStateSlotIDStart + slotId, slotData); // update slot map slotData[0] = bytes32(subsBitmap | (1 << uint256(slotId))); token.updateAgreementStateSlot( account, bitmapStateSlotId, slotData); // update the slots break; } } require(slotId < _MAX_NUM_SLOTS, "SlotBitmap out of bound"); } function clearSlot( ISuperfluidToken token, address account, uint256 bitmapStateSlotId, uint32 slotId ) public { uint256 subsBitmap = uint256(token.getAgreementStateSlot( address(this), account, bitmapStateSlotId, 1)[0]); bytes32[] memory slotData = new bytes32[](1); // [SECURITY] NOTE: We do not allow clearing of nonexistent slots assert(subsBitmap & (1 << uint256(slotId)) != 0); slotData[0] = bytes32(subsBitmap & ~(1 << uint256(slotId))); // zero the data token.updateAgreementStateSlot( account, bitmapStateSlotId, slotData); } function listData( ISuperfluidToken token, address account, uint256 bitmapStateSlotId, uint256 dataStateSlotIDStart ) public view returns ( uint32[] memory slotIds, bytes32[] memory dataList) { uint256 subsBitmap = uint256(token.getAgreementStateSlot( address(this), account, bitmapStateSlotId, 1)[0]); slotIds = new uint32[](_MAX_NUM_SLOTS); dataList = new bytes32[](_MAX_NUM_SLOTS); // read all slots uint nSlots; for (uint32 slotId = 0; slotId < _MAX_NUM_SLOTS; ++slotId) { if ((uint256(subsBitmap >> slotId) & 1) == 0) continue; slotIds[nSlots] = slotId; dataList[nSlots] = token.getAgreementStateSlot( address(this), account, dataStateSlotIDStart + slotId, 1)[0]; ++nSlots; } // resize memory arrays assembly { mstore(slotIds, nSlots) mstore(dataList, nSlots) } } }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; /** * @title ERC20 token info interface * @author Superfluid * @dev ERC20 standard interface does not specify these functions, but * often the token implementations have them. */ interface TokenInfo { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { TokenInfo } from "./TokenInfo.sol"; /** * @title ERC20 token with token info interface * @author Superfluid * @dev Using abstract contract instead of interfaces because old solidity * does not support interface inheriting other interfaces * solhint-disable-next-line no-empty-blocks * */ // solhint-disable-next-line no-empty-blocks abstract contract ERC20WithTokenInfo is IERC20, TokenInfo {}
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { SuperfluidErrors } from "./Definitions.sol"; /** * @title Superfluid token interface * @author Superfluid */ interface ISuperfluidToken { /************************************************************************** * Basic information *************************************************************************/ /** * @dev Get superfluid host contract address */ function getHost() external view returns(address host); /** * @dev Encoded liquidation type data mainly used for handling stack to deep errors * * @custom:note * - version: 1 * - liquidationType key: * - 0 = reward account receives reward (PIC period) * - 1 = liquidator account receives reward (Pleb period) * - 2 = liquidator account receives reward (Pirate period/bailout) */ struct LiquidationTypeData { uint256 version; uint8 liquidationType; } /************************************************************************** * Real-time balance functions *************************************************************************/ /** * @dev Calculate the real balance of a user, taking in consideration all agreements of the account * @param account for the query * @param timestamp Time of balance * @return availableBalance Real-time balance * @return deposit Account deposit * @return owedDeposit Account owed Deposit */ function realtimeBalanceOf( address account, uint256 timestamp ) external view returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit); /** * @notice Calculate the realtime balance given the current host.getNow() value * @dev realtimeBalanceOf with timestamp equals to block timestamp * @param account for the query * @return availableBalance Real-time balance * @return deposit Account deposit * @return owedDeposit Account owed Deposit */ function realtimeBalanceOfNow( address account ) external view returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit, uint256 timestamp); /** * @notice Check if account is critical * @dev A critical account is when availableBalance < 0 * @param account The account to check * @param timestamp The time we'd like to check if the account is critical (should use future) * @return isCritical Whether the account is critical */ function isAccountCritical( address account, uint256 timestamp ) external view returns(bool isCritical); /** * @notice Check if account is critical now (current host.getNow()) * @dev A critical account is when availableBalance < 0 * @param account The account to check * @return isCritical Whether the account is critical */ function isAccountCriticalNow( address account ) external view returns(bool isCritical); /** * @notice Check if account is solvent * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance * @param account The account to check * @param timestamp The time we'd like to check if the account is solvent (should use future) * @return isSolvent True if the account is solvent, false otherwise */ function isAccountSolvent( address account, uint256 timestamp ) external view returns(bool isSolvent); /** * @notice Check if account is solvent now * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance * @param account The account to check * @return isSolvent True if the account is solvent, false otherwise */ function isAccountSolventNow( address account ) external view returns(bool isSolvent); /** * @notice Get a list of agreements that is active for the account * @dev An active agreement is one that has state for the account * @param account Account to query * @return activeAgreements List of accounts that have non-zero states for the account */ function getAccountActiveAgreements(address account) external view returns(ISuperAgreement[] memory activeAgreements); /************************************************************************** * Super Agreement hosting functions *************************************************************************/ /** * @dev Create a new agreement * @param id Agreement ID * @param data Agreement data */ function createAgreement( bytes32 id, bytes32[] calldata data ) external; /** * @dev Agreement created event * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param data Agreement data */ event AgreementCreated( address indexed agreementClass, bytes32 id, bytes32[] data ); /** * @dev Get data of the agreement * @param agreementClass Contract address of the agreement * @param id Agreement ID * @return data Data of the agreement */ function getAgreementData( address agreementClass, bytes32 id, uint dataLength ) external view returns(bytes32[] memory data); /** * @dev Create a new agreement * @param id Agreement ID * @param data Agreement data */ function updateAgreementData( bytes32 id, bytes32[] calldata data ) external; /** * @dev Agreement updated event * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param data Agreement data */ event AgreementUpdated( address indexed agreementClass, bytes32 id, bytes32[] data ); /** * @dev Close the agreement * @param id Agreement ID */ function terminateAgreement( bytes32 id, uint dataLength ) external; /** * @dev Agreement terminated event * @param agreementClass Contract address of the agreement * @param id Agreement ID */ event AgreementTerminated( address indexed agreementClass, bytes32 id ); /** * @dev Update agreement state slot * @param account Account to be updated * * @custom:note * - To clear the storage out, provide zero-ed array of intended length */ function updateAgreementStateSlot( address account, uint256 slotId, bytes32[] calldata slotData ) external; /** * @dev Agreement account state updated event * @param agreementClass Contract address of the agreement * @param account Account updated * @param slotId slot id of the agreement state */ event AgreementStateUpdated( address indexed agreementClass, address indexed account, uint256 slotId ); /** * @dev Get data of the slot of the state of an agreement * @param agreementClass Contract address of the agreement * @param account Account to query * @param slotId slot id of the state * @param dataLength length of the state data */ function getAgreementStateSlot( address agreementClass, address account, uint256 slotId, uint dataLength ) external view returns (bytes32[] memory slotData); /** * @notice Settle balance from an account by the agreement * @dev The agreement needs to make sure that the balance delta is balanced afterwards * @param account Account to query. * @param delta Amount of balance delta to be settled * * @custom:modifiers * - onlyAgreement */ function settleBalance( address account, int256 delta ) external; /** * @dev Make liquidation payouts (v2) * @param id Agreement ID * @param liquidationTypeData Data regarding the version of the liquidation schema and the type * @param liquidatorAccount Address of the executor of the liquidation * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount * @param targetAccount Account to be liquidated * @param rewardAmount The amount the rewarded account will receive * @param targetAccountBalanceDelta The delta amount the target account balance should change by * * @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 * - total bailout include: bailout amount + reward amount * - the targetAccount will be bailed out * - If a bailout is not required * - the targetAccount will pay the rewardAmount * - the liquidator (reward account in PIC period) will receive the rewardAmount * * @custom:modifiers * - onlyAgreement */ function makeLiquidationPayoutsV2 ( bytes32 id, bytes memory liquidationTypeData, address liquidatorAccount, bool useDefaultRewardAccount, address targetAccount, uint256 rewardAmount, int256 targetAccountBalanceDelta ) external; /** * @dev Agreement liquidation event v2 (including agent account) * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param liquidatorAccount Address of the executor of the liquidation * @param targetAccount Account of the stream sender * @param rewardAmountReceiver Account that collects the reward or bails out insolvent accounts * @param rewardAmount The amount the reward recipient account balance should change by * @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 * Reward account rule: * - if the agreement is liquidated during the PIC period * - the rewardAmountReceiver will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount * - the targetAccount will pay for the rewardAmount * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent * - the rewardAmountReceiver will get the rewardAmount (remaining deposit) * - the targetAccount will pay for the rewardAmount * - if the targetAccount is insolvent * - the liquidatorAccount will get the rewardAmount (single deposit) * - the default reward account (governance) will pay for both the rewardAmount and bailoutAmount * - the targetAccount will receive the bailoutAmount */ event AgreementLiquidatedV2( address indexed agreementClass, bytes32 id, address indexed liquidatorAccount, address indexed targetAccount, address rewardAmountReceiver, uint256 rewardAmount, int256 targetAccountBalanceDelta, bytes liquidationTypeData ); /************************************************************************** * Function modifiers for access control and parameter validations * * While they cannot be explicitly stated in function definitions, they are * listed in function definition comments instead for clarity. * * NOTE: solidity-coverage not supporting it *************************************************************************/ /// @dev The msg.sender must be host contract //modifier onlyHost() virtual; /// @dev The msg.sender must be a listed agreement. //modifier onlyAgreement() virtual; /************************************************************************** * DEPRECATED *************************************************************************/ /** * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy) * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param penaltyAccount Account of the agreement to be penalized * @param rewardAccount Account that collect the reward * @param rewardAmount Amount of liquidation reward * * @custom:deprecated Use AgreementLiquidatedV2 instead */ event AgreementLiquidated( address indexed agreementClass, bytes32 id, address indexed penaltyAccount, address indexed rewardAccount, uint256 rewardAmount ); /** * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy) * @param bailoutAccount Account that bailout the penalty account * @param bailoutAmount Amount of account bailout * * @custom:deprecated Use AgreementLiquidatedV2 instead */ event Bailout( address indexed bailoutAccount, uint256 bailoutAmount ); /** * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2) * @param liquidatorAccount Account of the agent that performed the liquidation. * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param penaltyAccount Account of the agreement to be penalized * @param bondAccount Account that collect the reward or bailout accounts * @param rewardAmount Amount of liquidation reward * @param bailoutAmount Amount of liquidation bailouot * * @custom:deprecated Use AgreementLiquidatedV2 instead * * @custom:note * Reward account rule: * - if bailout is equal to 0, then * - the bondAccount will get the rewardAmount, * - the penaltyAccount will pay for the rewardAmount. * - if bailout is larger than 0, then * - the liquidatorAccount will get the rewardAmouont, * - the bondAccount will pay for both the rewardAmount and bailoutAmount, * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount. */ event AgreementLiquidatedBy( address liquidatorAccount, address indexed agreementClass, bytes32 id, address indexed penaltyAccount, address indexed bondAccount, uint256 rewardAmount, uint256 bailoutAmount ); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { ISuperToken } from "./ISuperToken.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { ISuperfluid } from "./ISuperfluid.sol"; import { SuperfluidErrors } from "./Definitions.sol"; /** * @title Superfluid governance interface * @author Superfluid */ interface ISuperfluidGovernance { /************************************************************************** * Errors *************************************************************************/ error SF_GOV_ARRAYS_NOT_SAME_LENGTH(); error SF_GOV_INVALID_LIQUIDATION_OR_PATRICIAN_PERIOD(); /** * @dev Replace the current governance with a new governance */ function replaceGovernance( ISuperfluid host, address newGov) external; /** * @dev Register a new agreement class */ function registerAgreementClass( ISuperfluid host, address agreementClass) external; /** * @dev Update logics of the contracts * * @custom:note * - Because they might have inter-dependencies, it is good to have one single function to update them all */ function updateContracts( ISuperfluid host, address hostNewLogic, address[] calldata agreementClassNewLogics, address superTokenFactoryNewLogic ) external; /** * @dev Update supertoken logic contract to the latest that is managed by the super token factory */ function batchUpdateSuperTokenLogic( ISuperfluid host, ISuperToken[] calldata tokens) external; /** * @dev Set configuration as address value */ function setConfig( ISuperfluid host, ISuperfluidToken superToken, bytes32 key, address value ) external; /** * @dev Set configuration as uint256 value */ function setConfig( ISuperfluid host, ISuperfluidToken superToken, bytes32 key, uint256 value ) external; /** * @dev Clear configuration */ function clearConfig( ISuperfluid host, ISuperfluidToken superToken, bytes32 key ) external; /** * @dev Get configuration as address value */ function getConfigAsAddress( ISuperfluid host, ISuperfluidToken superToken, bytes32 key) external view returns (address value); /** * @dev Get configuration as uint256 value */ function getConfigAsUint256( ISuperfluid host, ISuperfluidToken superToken, bytes32 key) external view returns (uint256 value); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperfluidGovernance } from "./ISuperfluidGovernance.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { ISuperToken } from "./ISuperToken.sol"; import { ISuperTokenFactory } from "./ISuperTokenFactory.sol"; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { ISuperApp } from "./ISuperApp.sol"; import { BatchOperation, ContextDefinitions, FlowOperatorDefinitions, SuperAppDefinitions, SuperfluidErrors, SuperfluidGovernanceConfigs } from "./Definitions.sol"; import { TokenInfo } from "../tokens/TokenInfo.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; /** * @title Host interface * @author Superfluid * @notice This is the central contract of the system where super agreement, super app * and super token features are connected. * * The Superfluid host contract is also the entry point for the protocol users, * where batch call and meta transaction are provided for UX improvements. * */ interface ISuperfluid { /************************************************************************** * Errors *************************************************************************/ // Superfluid Custom Errors error HOST_AGREEMENT_CALLBACK_IS_NOT_ACTION(); error HOST_CANNOT_DOWNGRADE_TO_NON_UPGRADEABLE(); error HOST_CALL_AGREEMENT_WITH_CTX_FROM_WRONG_ADDRESS(); error HOST_CALL_APP_ACTION_WITH_CTX_FROM_WRONG_ADDRESS(); error HOST_INVALID_CONFIG_WORD(); error HOST_MAX_256_AGREEMENTS(); error HOST_NON_UPGRADEABLE(); error HOST_NON_ZERO_LENGTH_PLACEHOLDER_CTX(); error HOST_ONLY_GOVERNANCE(); error HOST_UNKNOWN_BATCH_CALL_OPERATION_TYPE(); // App Related Custom Errors error HOST_INVALID_OR_EXPIRED_SUPER_APP_REGISTRATION_KEY(); error HOST_NOT_A_SUPER_APP(); error HOST_NO_APP_REGISTRATION_PERMISSIONS(); error HOST_RECEIVER_IS_NOT_SUPER_APP(); error HOST_SENDER_IS_NOT_SUPER_APP(); error HOST_SOURCE_APP_NEEDS_HIGHER_APP_LEVEL(); error HOST_SUPER_APP_IS_JAILED(); error HOST_SUPER_APP_ALREADY_REGISTERED(); error HOST_UNAUTHORIZED_SUPER_APP_FACTORY(); /************************************************************************** * Time * * > The Oracle: You have the sight now, Neo. You are looking at the world without time. * > Neo: Then why can't I see what happens to her? * > The Oracle: We can never see past the choices we don't understand. * > - The Oracle and Neo conversing about the future of Trinity and the effects of Neo's choices *************************************************************************/ function getNow() external view returns (uint256); /************************************************************************** * Governance *************************************************************************/ /** * @dev Get the current governance address of the Superfluid host */ function getGovernance() external view returns(ISuperfluidGovernance governance); /** * @dev Replace the current governance with a new one */ function replaceGovernance(ISuperfluidGovernance newGov) external; /** * @dev Governance replaced event * @param oldGov Address of the old governance contract * @param newGov Address of the new governance contract */ event GovernanceReplaced(ISuperfluidGovernance oldGov, ISuperfluidGovernance newGov); /************************************************************************** * Agreement Whitelisting *************************************************************************/ /** * @dev Register a new agreement class to the system * @param agreementClassLogic Initial agreement class code * * @custom:modifiers * - onlyGovernance */ function registerAgreementClass(ISuperAgreement agreementClassLogic) external; /** * @notice Agreement class registered event * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param agreementType The agreement type registered * @param code Address of the new agreement */ event AgreementClassRegistered(bytes32 agreementType, address code); /** * @dev Update code of an agreement class * @param agreementClassLogic New code for the agreement class * * @custom:modifiers * - onlyGovernance */ function updateAgreementClass(ISuperAgreement agreementClassLogic) external; /** * @notice Agreement class updated event * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param agreementType The agreement type updated * @param code Address of the new agreement */ event AgreementClassUpdated(bytes32 agreementType, address code); /** * @notice Check if the agreement type is whitelisted * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" */ function isAgreementTypeListed(bytes32 agreementType) external view returns(bool yes); /** * @dev Check if the agreement class is whitelisted */ function isAgreementClassListed(ISuperAgreement agreementClass) external view returns(bool yes); /** * @notice Get agreement class * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" */ function getAgreementClass(bytes32 agreementType) external view returns(ISuperAgreement agreementClass); /** * @dev Map list of the agreement classes using a bitmap * @param bitmap Agreement class bitmap */ function mapAgreementClasses(uint256 bitmap) external view returns (ISuperAgreement[] memory agreementClasses); /** * @notice Create a new bitmask by adding a agreement class to it * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param bitmap Agreement class bitmap */ function addToAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType) external view returns (uint256 newBitmap); /** * @notice Create a new bitmask by removing a agreement class from it * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param bitmap Agreement class bitmap */ function removeFromAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType) external view returns (uint256 newBitmap); /************************************************************************** * Super Token Factory **************************************************************************/ /** * @dev Get the super token factory * @return factory The factory */ function getSuperTokenFactory() external view returns (ISuperTokenFactory factory); /** * @dev Get the super token factory logic (applicable to upgradable deployment) * @return logic The factory logic */ function getSuperTokenFactoryLogic() external view returns (address logic); /** * @dev Update super token factory * @param newFactory New factory logic */ function updateSuperTokenFactory(ISuperTokenFactory newFactory) external; /** * @dev SuperToken factory updated event * @param newFactory Address of the new factory */ event SuperTokenFactoryUpdated(ISuperTokenFactory newFactory); /** * @notice Update the super token logic to the latest * @dev Refer to ISuperTokenFactory.Upgradability for expected behaviours */ function updateSuperTokenLogic(ISuperToken token) external; /** * @dev SuperToken logic updated event * @param code Address of the new SuperToken logic */ event SuperTokenLogicUpdated(ISuperToken indexed token, address code); /************************************************************************** * App Registry *************************************************************************/ /** * @dev Message sender (must be a contract) declares itself as a super app. * @custom:deprecated you should use `registerAppWithKey` or `registerAppByFactory` instead, * because app registration is currently governance permissioned on mainnets. * @param configWord The super app manifest configuration, flags are defined in * `SuperAppDefinitions` */ function registerApp(uint256 configWord) external; /** * @dev App registered event * @param app Address of jailed app */ event AppRegistered(ISuperApp indexed app); /** * @dev Message sender declares itself as a super app. * @param configWord The super app manifest configuration, flags are defined in `SuperAppDefinitions` * @param registrationKey The registration key issued by the governance, needed to register on a mainnet. * @notice See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide * On testnets or in dev environment, a placeholder (e.g. empty string) can be used. * While the message sender must be the super app itself, the transaction sender (tx.origin) * must be the deployer account the registration key was issued for. */ function registerAppWithKey(uint256 configWord, string calldata registrationKey) external; /** * @dev Message sender (must be a contract) declares app as a super app * @param configWord The super app manifest configuration, flags are defined in `SuperAppDefinitions` * @notice On mainnet deployments, only factory contracts pre-authorized by governance can use this. * See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide */ function registerAppByFactory(ISuperApp app, uint256 configWord) external; /** * @dev Query if the app is registered * @param app Super app address */ function isApp(ISuperApp app) external view returns(bool); /** * @dev Query app callbacklevel * @param app Super app address */ function getAppCallbackLevel(ISuperApp app) external view returns(uint8 appCallbackLevel); /** * @dev Get the manifest of the super app * @param app Super app address */ function getAppManifest( ISuperApp app ) external view returns ( bool isSuperApp, bool isJailed, uint256 noopMask ); /** * @dev Query if the app has been jailed * @param app Super app address */ function isAppJailed(ISuperApp app) external view returns (bool isJail); /** * @dev Whitelist the target app for app composition for the source app (msg.sender) * @param targetApp The target super app address */ function allowCompositeApp(ISuperApp targetApp) external; /** * @dev Query if source app is allowed to call the target app as downstream app * @param app Super app address * @param targetApp The target super app address */ function isCompositeAppAllowed( ISuperApp app, ISuperApp targetApp ) external view returns (bool isAppAllowed); /************************************************************************** * Agreement Framework * * Agreements use these function to trigger super app callbacks, updates * app credit and charge gas fees. * * These functions can only be called by registered agreements. *************************************************************************/ /** * @dev (For agreements) StaticCall the app before callback * @param app The super app. * @param callData The call data sending to the super app. * @param isTermination Is it a termination callback? * @param ctx Current ctx, it will be validated. * @return cbdata Data returned from the callback. */ function callAppBeforeCallback( ISuperApp app, bytes calldata callData, bool isTermination, bytes calldata ctx ) external // onlyAgreement // assertValidCtx(ctx) returns(bytes memory cbdata); /** * @dev (For agreements) Call the app after callback * @param app The super app. * @param callData The call data sending to the super app. * @param isTermination Is it a termination callback? * @param ctx Current ctx, it will be validated. * @return newCtx The current context of the transaction. */ function callAppAfterCallback( ISuperApp app, bytes calldata callData, bool isTermination, bytes calldata ctx ) external // onlyAgreement // assertValidCtx(ctx) returns(bytes memory newCtx); /** * @dev (For agreements) Create a new callback stack * @param ctx The current ctx, it will be validated. * @param app The super app. * @param appCreditGranted App credit granted so far. * @param appCreditUsed App credit used so far. * @return newCtx The current context of the transaction. */ function appCallbackPush( bytes calldata ctx, ISuperApp app, uint256 appCreditGranted, int256 appCreditUsed, ISuperfluidToken appCreditToken ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev (For agreements) Pop from the current app callback stack * @param ctx The ctx that was pushed before the callback stack. * @param appCreditUsedDelta App credit used by the app. * @return newCtx The current context of the transaction. * * @custom:security * - Here we cannot do assertValidCtx(ctx), since we do not really save the stack in memory. * - Hence there is still implicit trust that the agreement handles the callback push/pop pair correctly. */ function appCallbackPop( bytes calldata ctx, int256 appCreditUsedDelta ) external // onlyAgreement returns (bytes memory newCtx); /** * @dev (For agreements) Use app credit. * @param ctx The current ctx, it will be validated. * @param appCreditUsedMore See app credit for more details. * @return newCtx The current context of the transaction. */ function ctxUseCredit( bytes calldata ctx, int256 appCreditUsedMore ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev (For agreements) Jail the app. * @param app The super app. * @param reason Jail reason code. * @return newCtx The current context of the transaction. */ function jailApp( bytes calldata ctx, ISuperApp app, uint256 reason ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev Jail event for the app * @param app Address of jailed app * @param reason Reason the app is jailed (see Definitions.sol for the full list) */ event Jail(ISuperApp indexed app, uint256 reason); /************************************************************************** * Contextless Call Proxies * * NOTE: For EOAs or non-app contracts, they are the entry points for interacting * with agreements or apps. * * NOTE: The contextual call data should be generated using * abi.encodeWithSelector. The context parameter should be set to "0x", * an empty bytes array as a placeholder to be replaced by the host * contract. *************************************************************************/ /** * @dev Call agreement function * @param agreementClass The agreement address you are calling * @param callData The contextual call data with placeholder ctx * @param userData Extra user data being sent to the super app callbacks */ function callAgreement( ISuperAgreement agreementClass, bytes calldata callData, bytes calldata userData ) external //cleanCtx //isAgreement(agreementClass) returns(bytes memory returnedData); /** * @notice Call app action * @dev Main use case is calling app action in a batch call via the host * @param callData The contextual call data * * @custom:note See "Contextless Call Proxies" above for more about contextual call data. */ function callAppAction( ISuperApp app, bytes calldata callData ) external //cleanCtx //isAppActive(app) //isValidAppAction(callData) returns(bytes memory returnedData); /************************************************************************** * Contextual Call Proxies and Context Utilities * * For apps, they must use context they receive to interact with * agreements or apps. * * The context changes must be saved and returned by the apps in their * callbacks always, any modification to the context will be detected and * the violating app will be jailed. *************************************************************************/ /** * @dev Context Struct * * @custom:note on backward compatibility: * - Non-dynamic fields are padded to 32bytes and packed * - Dynamic fields are referenced through a 32bytes offset to their "parents" field (or root) * - The order of the fields hence should not be rearranged in order to be backward compatible: * - non-dynamic fields will be parsed at the same memory location, * - and dynamic fields will simply have a greater offset than it was. * - We cannot change the structure of the Context struct because of ABI compatibility requirements */ struct Context { // // Call context // // app callback level uint8 appCallbackLevel; // type of call uint8 callType; // the system timestamp uint256 timestamp; // The intended message sender for the call address msgSender; // // Callback context // // For callbacks it is used to know which agreement function selector is called bytes4 agreementSelector; // User provided data for app callbacks bytes userData; // // App context // // app credit granted uint256 appCreditGranted; // app credit wanted by the app callback uint256 appCreditWantedDeprecated; // app credit used, allowing negative values over a callback session // the appCreditUsed value over a callback sessions is calculated with: // existing flow data owed deposit + sum of the callback agreements // deposit deltas // the final value used to modify the state is determined by the // _adjustNewAppCreditUsed function (in AgreementLibrary.sol) which takes // the appCreditUsed value reached in the callback session and the app // credit granted int256 appCreditUsed; // app address address appAddress; // app credit in super token ISuperfluidToken appCreditToken; } function callAgreementWithContext( ISuperAgreement agreementClass, bytes calldata callData, bytes calldata userData, bytes calldata ctx ) external // requireValidCtx(ctx) // onlyAgreement(agreementClass) returns (bytes memory newCtx, bytes memory returnedData); function callAppActionWithContext( ISuperApp app, bytes calldata callData, bytes calldata ctx ) external // requireValidCtx(ctx) // isAppActive(app) returns (bytes memory newCtx); function decodeCtx(bytes memory ctx) external pure returns (Context memory context); function isCtxValid(bytes calldata ctx) external view returns (bool); /************************************************************************** * Batch call **************************************************************************/ /** * @dev Batch operation data */ struct Operation { // Operation type. Defined in BatchOperation (Definitions.sol) uint32 operationType; // Operation target address target; // Data specific to the operation bytes data; } /** * @dev Batch call function * @param operations Array of batch operations */ function batchCall(Operation[] calldata operations) external; /** * @dev Batch call function for trusted forwarders (EIP-2771) * @param operations Array of batch operations */ function forwardBatchCall(Operation[] calldata operations) external; /************************************************************************** * Function modifiers for access control and parameter validations * * While they cannot be explicitly stated in function definitions, they are * listed in function definition comments instead for clarity. * * TODO: turning these off because solidity-coverage doesn't like it *************************************************************************/ /* /// @dev The current superfluid context is clean. modifier cleanCtx() virtual; /// @dev Require the ctx being valid. modifier requireValidCtx(bytes memory ctx) virtual; /// @dev Assert the ctx being valid. modifier assertValidCtx(bytes memory ctx) virtual; /// @dev The agreement is a listed agreement. modifier isAgreement(ISuperAgreement agreementClass) virtual; // onlyGovernance /// @dev The msg.sender must be a listed agreement. modifier onlyAgreement() virtual; /// @dev The app is registered and not jailed. modifier isAppActive(ISuperApp app) virtual; */ }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperToken } from "./ISuperToken.sol"; import { IERC20, ERC20WithTokenInfo } from "../tokens/ERC20WithTokenInfo.sol"; import { SuperfluidErrors } from "./Definitions.sol"; /** * @title Super token factory interface * @author Superfluid */ interface ISuperTokenFactory { /** * @dev Get superfluid host contract address */ function getHost() external view returns(address host); /// @dev Initialize the contract function initialize() external; /** * @dev Get the current super token logic used by the factory */ function getSuperTokenLogic() external view returns (ISuperToken superToken); /** * @dev Upgradability modes */ enum Upgradability { /// Non upgradable super token, `host.updateSuperTokenLogic` will revert NON_UPGRADABLE, /// Upgradable through `host.updateSuperTokenLogic` operation SEMI_UPGRADABLE, /// Always using the latest super token logic FULL_UPGRADABE } /** * @dev Create new super token wrapper for the underlying ERC20 token * @param underlyingToken Underlying ERC20 token * @param underlyingDecimals Underlying token decimals * @param upgradability Upgradability mode * @param name Super token name * @param symbol Super token symbol */ function createERC20Wrapper( IERC20 underlyingToken, uint8 underlyingDecimals, Upgradability upgradability, string calldata name, string calldata symbol ) external returns (ISuperToken superToken); /** * @dev Create new super token wrapper for the underlying ERC20 token with extra token info * @param underlyingToken Underlying ERC20 token * @param upgradability Upgradability mode * @param name Super token name * @param symbol Super token symbol * * NOTE: * - It assumes token provide the .decimals() function */ function createERC20Wrapper( ERC20WithTokenInfo underlyingToken, Upgradability upgradability, string calldata name, string calldata symbol ) external returns (ISuperToken superToken); function initializeCustomSuperToken( address customSuperTokenProxy ) external; /** * @dev Super token logic created event * @param tokenLogic Token logic address */ event SuperTokenLogicCreated(ISuperToken indexed tokenLogic); /** * @dev Super token created event * @param token Newly created super token address */ event SuperTokenCreated(ISuperToken indexed token); /** * @dev Custom super token created event * @param token Newly created custom super token address */ event CustomSuperTokenCreated(ISuperToken indexed token); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperfluid } from "./ISuperfluid.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { TokenInfo } from "../tokens/TokenInfo.sol"; import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SuperfluidErrors } from "./Definitions.sol"; /** * @title Super token (Superfluid Token + ERC20 + ERC777) interface * @author Superfluid */ interface ISuperToken is ISuperfluidToken, TokenInfo, IERC20, IERC777 { /************************************************************************** * Errors *************************************************************************/ error SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); error SUPER_TOKEN_NOT_ERC777_TOKENS_RECIPIENT(); error SUPER_TOKEN_INFLATIONARY_DEFLATIONARY_NOT_SUPPORTED(); error SUPER_TOKEN_NO_UNDERLYING_TOKEN(); error SUPER_TOKEN_ONLY_SELF(); /** * @dev Initialize the contract */ function initialize( IERC20 underlyingToken, uint8 underlyingDecimals, string calldata n, string calldata s ) external; /************************************************************************** * TokenInfo & ERC777 *************************************************************************/ /** * @dev Returns the name of the token. */ function name() external view override(IERC777, TokenInfo) returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view override(IERC777, TokenInfo) returns (string memory); /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * @custom:note SuperToken always uses 18 decimals. * * This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external view override(TokenInfo) returns (uint8); /************************************************************************** * ERC20 & ERC777 *************************************************************************/ /** * @dev See {IERC20-totalSupply}. */ function totalSupply() external view override(IERC777, IERC20) returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address account) external view override(IERC777, IERC20) returns(uint256 balance); /************************************************************************** * ERC20 *************************************************************************/ /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external override(IERC20) returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * @notice This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external override(IERC20) view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:note Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * @custom:emits an {Approval} event. */ function approve(address spender, uint256 amount) external override(IERC20) returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external override(IERC20) returns (bool); /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * @custom:emits an {Approval} event indicating the updated allowance. * * @custom:requirements * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) external returns (bool); /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * @custom:emits an {Approval} event indicating the updated allowance. * * @custom:requirements * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); /************************************************************************** * ERC777 *************************************************************************/ /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * @custom:note For super token contracts, this value is always 1 */ function granularity() external view override(IERC777) returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * @dev If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * @custom:emits a {Sent} event. * * @custom:requirements * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send(address recipient, uint256 amount, bytes calldata data) external override(IERC777); /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply. * * If a send hook is registered for the caller, the corresponding function * will be called with `data` and empty `operatorData`. See {IERC777Sender}. * * @custom:emits a {Burned} event. * * @custom:requirements * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata data) external override(IERC777); /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external override(IERC777) view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * @custom:emits an {AuthorizedOperator} event. * * @custom:requirements * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external override(IERC777); /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * @custom:emits a {RevokedOperator} event. * * @custom:requirements * - `operator` cannot be calling address. */ function revokeOperator(address operator) external override(IERC777); /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external override(IERC777) view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * @custom:emits a {Sent} event. * * @custom:requirements * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external override(IERC777); /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `data` and `operatorData`. See {IERC777Sender}. * * @custom:emits a {Burned} event. * * @custom:requirements * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata data, bytes calldata operatorData ) external override(IERC777); /************************************************************************** * SuperToken custom token functions *************************************************************************/ /** * @dev Mint new tokens for the account * * @custom:modifiers * - onlySelf */ function selfMint( address account, uint256 amount, bytes memory userData ) external; /** * @dev Burn existing tokens for the account * * @custom:modifiers * - onlySelf */ function selfBurn( address account, uint256 amount, bytes memory userData ) external; /** * @dev Transfer `amount` tokens from the `sender` to `recipient`. * If `spender` isn't the same as `sender`, checks if `spender` has allowance to * spend tokens of `sender`. * * @custom:modifiers * - onlySelf */ function selfTransferFrom( address sender, address spender, address recipient, uint256 amount ) external; /** * @dev Give `spender`, `amount` allowance to spend the tokens of * `account`. * * @custom:modifiers * - onlySelf */ function selfApproveFor( address account, address spender, uint256 amount ) external; /************************************************************************** * SuperToken extra functions *************************************************************************/ /** * @dev Transfer all available balance from `msg.sender` to `recipient` */ function transferAll(address recipient) external; /************************************************************************** * ERC20 wrapping *************************************************************************/ /** * @dev Return the underlying token contract * @return tokenAddr Underlying token address */ function getUnderlyingToken() external view returns(address tokenAddr); /** * @dev Upgrade ERC20 to SuperToken. * @param amount Number of tokens to be upgraded (in 18 decimals) * * @custom:note It will use `transferFrom` to get tokens. Before calling this * function you should `approve` this contract */ function upgrade(uint256 amount) external; /** * @dev Upgrade ERC20 to SuperToken and transfer immediately * @param to The account to received upgraded tokens * @param amount Number of tokens to be upgraded (in 18 decimals) * @param data User data for the TokensRecipient callback * * @custom:note It will use `transferFrom` to get tokens. Before calling this * function you should `approve` this contract */ function upgradeTo(address to, uint256 amount, bytes calldata data) external; /** * @dev Token upgrade event * @param account Account where tokens are upgraded to * @param amount Amount of tokens upgraded (in 18 decimals) */ event TokenUpgraded( address indexed account, uint256 amount ); /** * @dev Downgrade SuperToken to ERC20. * @dev It will call transfer to send tokens * @param amount Number of tokens to be downgraded */ function downgrade(uint256 amount) external; /** * @dev Token downgrade event * @param account Account whose tokens are upgraded * @param amount Amount of tokens downgraded */ event TokenDowngraded( address indexed account, uint256 amount ); /************************************************************************** * Batch Operations *************************************************************************/ /** * @dev Perform ERC20 approve by host contract. * @param account The account owner to be approved. * @param spender The spender of account owner's funds. * @param amount Number of tokens to be approved. * * @custom:modifiers * - onlyHost */ function operationApprove( address account, address spender, uint256 amount ) external; /** * @dev Perform ERC20 transfer from by host contract. * @param account The account to spend sender's funds. * @param spender The account where the funds is sent from. * @param recipient The recipient of thefunds. * @param amount Number of tokens to be transferred. * * @custom:modifiers * - onlyHost */ function operationTransferFrom( address account, address spender, address recipient, uint256 amount ) external; /** * @dev Upgrade ERC20 to SuperToken by host contract. * @param account The account to be changed. * @param amount Number of tokens to be upgraded (in 18 decimals) * * @custom:modifiers * - onlyHost */ function operationUpgrade(address account, uint256 amount) external; /** * @dev Downgrade ERC20 to SuperToken by host contract. * @param account The account to be changed. * @param amount Number of tokens to be downgraded (in 18 decimals) * * @custom:modifiers * - onlyHost */ function operationDowngrade(address account, uint256 amount) external; /************************************************************************** * Function modifiers for access control and parameter validations * * While they cannot be explicitly stated in function definitions, they are * listed in function definition comments instead for clarity. * * NOTE: solidity-coverage not supporting it *************************************************************************/ /// @dev The msg.sender must be the contract itself //modifier onlySelf() virtual }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperToken } from "./ISuperToken.sol"; /** * @title SuperApp interface * @author Superfluid * @dev Be aware of the app being jailed, when the word permitted is used. */ interface ISuperApp { /** * @dev Callback before a new agreement is created. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass * arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Only revert with a "reason" is permitted. */ function beforeAgreementCreated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is created. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Only revert with a "reason" is permitted. */ function afterAgreementCreated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); /** * @dev Callback before a new agreement is updated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass * arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Only revert with a "reason" is permitted. */ function beforeAgreementUpdated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is updated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Only revert with a "reason" is permitted. */ function afterAgreementUpdated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); /** * @dev Callback before a new agreement is terminated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Revert is not permitted. */ function beforeAgreementTerminated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is terminated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Revert is not permitted. */ function afterAgreementTerminated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; /** * @title Super agreement interface * @author Superfluid */ interface ISuperAgreement { /** * @dev Get the type of the agreement class */ function agreementType() external view returns (bytes32); /** * @dev Calculate the real-time balance for the account of this agreement class * @param account Account the state belongs to * @param time Time used for the calculation * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement * @return deposit Account deposit amount of this agreement * @return owedDeposit Account owed deposit amount of this agreement */ function realtimeBalanceOf( ISuperfluidToken token, address account, uint256 time ) external view returns ( int256 dynamicBalance, uint256 deposit, uint256 owedDeposit ); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; /** * @title Super app definitions library * @author Superfluid */ library SuperAppDefinitions { /************************************************************************** / App manifest config word /**************************************************************************/ /* * App level is a way to allow the app to whitelist what other app it can * interact with (aka. composite app feature). * * For more details, refer to the technical paper of superfluid protocol. */ uint256 constant internal APP_LEVEL_MASK = 0xFF; // The app is at the final level, hence it doesn't want to interact with any other app uint256 constant internal APP_LEVEL_FINAL = 1 << 0; // The app is at the second level, it may interact with other final level apps if whitelisted uint256 constant internal APP_LEVEL_SECOND = 1 << 1; function getAppCallbackLevel(uint256 configWord) internal pure returns (uint8) { return uint8(configWord & APP_LEVEL_MASK); } uint256 constant internal APP_JAIL_BIT = 1 << 15; function isAppJailed(uint256 configWord) internal pure returns (bool) { return (configWord & SuperAppDefinitions.APP_JAIL_BIT) > 0; } /************************************************************************** / Callback implementation bit masks /**************************************************************************/ uint256 constant internal AGREEMENT_CALLBACK_NOOP_BITMASKS = 0xFF << 32; uint256 constant internal BEFORE_AGREEMENT_CREATED_NOOP = 1 << (32 + 0); uint256 constant internal AFTER_AGREEMENT_CREATED_NOOP = 1 << (32 + 1); uint256 constant internal BEFORE_AGREEMENT_UPDATED_NOOP = 1 << (32 + 2); uint256 constant internal AFTER_AGREEMENT_UPDATED_NOOP = 1 << (32 + 3); uint256 constant internal BEFORE_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 4); uint256 constant internal AFTER_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 5); /************************************************************************** / App Jail Reasons /**************************************************************************/ uint256 constant internal APP_RULE_REGISTRATION_ONLY_IN_CONSTRUCTOR = 1; uint256 constant internal APP_RULE_NO_REGISTRATION_FOR_EOA = 2; uint256 constant internal APP_RULE_NO_REVERT_ON_TERMINATION_CALLBACK = 10; uint256 constant internal APP_RULE_NO_CRITICAL_SENDER_ACCOUNT = 11; uint256 constant internal APP_RULE_NO_CRITICAL_RECEIVER_ACCOUNT = 12; uint256 constant internal APP_RULE_CTX_IS_READONLY = 20; uint256 constant internal APP_RULE_CTX_IS_NOT_CLEAN = 21; uint256 constant internal APP_RULE_CTX_IS_MALFORMATED = 22; uint256 constant internal APP_RULE_COMPOSITE_APP_IS_NOT_WHITELISTED = 30; uint256 constant internal APP_RULE_COMPOSITE_APP_IS_JAILED = 31; uint256 constant internal APP_RULE_MAX_APP_LEVEL_REACHED = 40; // Validate configWord cleaness for future compatibility, or else may introduce undefined future behavior function isConfigWordClean(uint256 configWord) internal pure returns (bool) { return (configWord & ~(APP_LEVEL_MASK | APP_JAIL_BIT | AGREEMENT_CALLBACK_NOOP_BITMASKS)) == uint256(0); } } /** * @title Context definitions library * @author Superfluid */ library ContextDefinitions { /************************************************************************** / Call info /**************************************************************************/ // app level uint256 constant internal CALL_INFO_APP_LEVEL_MASK = 0xFF; // call type uint256 constant internal CALL_INFO_CALL_TYPE_SHIFT = 32; uint256 constant internal CALL_INFO_CALL_TYPE_MASK = 0xF << CALL_INFO_CALL_TYPE_SHIFT; uint8 constant internal CALL_INFO_CALL_TYPE_AGREEMENT = 1; uint8 constant internal CALL_INFO_CALL_TYPE_APP_ACTION = 2; uint8 constant internal CALL_INFO_CALL_TYPE_APP_CALLBACK = 3; function decodeCallInfo(uint256 callInfo) internal pure returns (uint8 appCallbackLevel, uint8 callType) { appCallbackLevel = uint8(callInfo & CALL_INFO_APP_LEVEL_MASK); callType = uint8((callInfo & CALL_INFO_CALL_TYPE_MASK) >> CALL_INFO_CALL_TYPE_SHIFT); } function encodeCallInfo(uint8 appCallbackLevel, uint8 callType) internal pure returns (uint256 callInfo) { return uint256(appCallbackLevel) | (uint256(callType) << CALL_INFO_CALL_TYPE_SHIFT); } } /** * @title Flow Operator definitions library * @author Superfluid */ library FlowOperatorDefinitions { uint8 constant internal AUTHORIZE_FLOW_OPERATOR_CREATE = uint8(1) << 0; uint8 constant internal AUTHORIZE_FLOW_OPERATOR_UPDATE = uint8(1) << 1; uint8 constant internal AUTHORIZE_FLOW_OPERATOR_DELETE = uint8(1) << 2; uint8 constant internal AUTHORIZE_FULL_CONTROL = AUTHORIZE_FLOW_OPERATOR_CREATE | AUTHORIZE_FLOW_OPERATOR_UPDATE | AUTHORIZE_FLOW_OPERATOR_DELETE; uint8 constant internal REVOKE_FLOW_OPERATOR_CREATE = ~(uint8(1) << 0); uint8 constant internal REVOKE_FLOW_OPERATOR_UPDATE = ~(uint8(1) << 1); uint8 constant internal REVOKE_FLOW_OPERATOR_DELETE = ~(uint8(1) << 2); function isPermissionsClean(uint8 permissions) internal pure returns (bool) { return ( permissions & ~(AUTHORIZE_FLOW_OPERATOR_CREATE | AUTHORIZE_FLOW_OPERATOR_UPDATE | AUTHORIZE_FLOW_OPERATOR_DELETE) ) == uint8(0); } } /** * @title Batch operation library * @author Superfluid */ library BatchOperation { /** * @dev ERC20.approve batch operation type * * Call spec: * ISuperToken(target).operationApprove( * abi.decode(data, (address spender, uint256 amount)) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_APPROVE = 1; /** * @dev ERC20.transferFrom batch operation type * * Call spec: * ISuperToken(target).operationTransferFrom( * abi.decode(data, (address sender, address recipient, uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_TRANSFER_FROM = 2; /** * @dev SuperToken.upgrade batch operation type * * Call spec: * ISuperToken(target).operationUpgrade( * abi.decode(data, (uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_SUPERTOKEN_UPGRADE = 1 + 100; /** * @dev SuperToken.downgrade batch operation type * * Call spec: * ISuperToken(target).operationDowngrade( * abi.decode(data, (uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_SUPERTOKEN_DOWNGRADE = 2 + 100; /** * @dev Superfluid.callAgreement batch operation type * * Call spec: * callAgreement( * ISuperAgreement(target)), * abi.decode(data, (bytes calldata, bytes userdata) * ) */ uint32 constant internal OPERATION_TYPE_SUPERFLUID_CALL_AGREEMENT = 1 + 200; /** * @dev Superfluid.callAppAction batch operation type * * Call spec: * callAppAction( * ISuperApp(target)), * data * ) */ uint32 constant internal OPERATION_TYPE_SUPERFLUID_CALL_APP_ACTION = 2 + 200; } /** * @title Superfluid governance configs library * @author Superfluid */ library SuperfluidGovernanceConfigs { bytes32 constant internal SUPERFLUID_REWARD_ADDRESS_CONFIG_KEY = keccak256("org.superfluid-finance.superfluid.rewardAddress"); bytes32 constant internal CFAV1_PPP_CONFIG_KEY = keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1.PPPConfiguration"); bytes32 constant internal SUPERTOKEN_MINIMUM_DEPOSIT_KEY = keccak256("org.superfluid-finance.superfluid.superTokenMinimumDeposit"); function getTrustedForwarderConfigKey(address forwarder) internal pure returns (bytes32) { return keccak256(abi.encode( "org.superfluid-finance.superfluid.trustedForwarder", forwarder)); } function getAppRegistrationConfigKey(address deployer, string memory registrationKey) internal pure returns (bytes32) { return keccak256(abi.encode( "org.superfluid-finance.superfluid.appWhiteListing.registrationKey", deployer, registrationKey)); } function getAppFactoryConfigKey(address factory) internal pure returns (bytes32) { return keccak256(abi.encode( "org.superfluid-finance.superfluid.appWhiteListing.factory", factory)); } function decodePPPConfig(uint256 pppConfig) internal pure returns (uint256 liquidationPeriod, uint256 patricianPeriod) { liquidationPeriod = (pppConfig >> 32) & type(uint32).max; patricianPeriod = pppConfig & type(uint32).max; } } /** * @title Superfluid Common Custom Errors and Error Codes * @author Superfluid */ library SuperfluidErrors { /************************************************************************** / Shared Custom Errors /**************************************************************************/ error APP_RULE(uint256 _code); // uses SuperAppDefinitions' App Jail Reasons // The Error Code Reference refers to the types of errors within a range, // e.g. ALREADY_EXISTS and DOES_NOT_EXIST error codes will live between // 1000-1099 for Constant Flow Agreement error codes. // Error Code Reference error ALREADY_EXISTS(uint256 _code); // 0 - 99 error DOES_NOT_EXIST(uint256 _code); // 0 - 99 error INSUFFICIENT_BALANCE(uint256 _code); // 100 - 199 error MUST_BE_CONTRACT(uint256 _code); // 200 - 299 error ONLY_LISTED_AGREEMENT(uint256 _code); // 300 - 399 error ONLY_HOST(uint256 _code); // 400 - 499 error ZERO_ADDRESS(uint256 _code); // 500 - 599 /************************************************************************** / Error Codes /**************************************************************************/ // 1000 - 1999 | Constant Flow Agreement uint256 constant internal CFA_FLOW_ALREADY_EXISTS = 1000; uint256 constant internal CFA_FLOW_DOES_NOT_EXIST = 1001; uint256 constant internal CFA_INSUFFICIENT_BALANCE = 1100; uint256 constant internal CFA_ZERO_ADDRESS_SENDER = 1500; uint256 constant internal CFA_ZERO_ADDRESS_RECEIVER = 1501; // 2000 - 2999 | Instant Distribution Agreement uint256 constant internal IDA_INDEX_ALREADY_EXISTS = 2000; uint256 constant internal IDA_INDEX_DOES_NOT_EXIST = 2001; uint256 constant internal IDA_SUBSCRIPTION_DOES_NOT_EXIST = 2002; uint256 constant internal IDA_SUBSCRIPTION_ALREADY_APPROVED = 2003; uint256 constant internal IDA_SUBSCRIPTION_IS_NOT_APPROVED = 2004; uint256 constant internal IDA_INSUFFICIENT_BALANCE = 2100; uint256 constant internal IDA_ZERO_ADDRESS_SUBSCRIBER = 2500; // 3000 - 3999 | Host uint256 constant internal HOST_AGREEMENT_ALREADY_REGISTERED = 3000; uint256 constant internal HOST_AGREEMENT_IS_NOT_REGISTERED = 3001; uint256 constant internal HOST_SUPER_APP_ALREADY_REGISTERED = 3002; uint256 constant internal HOST_MUST_BE_CONTRACT = 3200; uint256 constant internal HOST_ONLY_LISTED_AGREEMENT = 3300; // 4000 - 4999 | Superfluid Governance II uint256 constant internal SF_GOV_MUST_BE_CONTRACT = 4200; // 5000 - 5999 | SuperfluidToken uint256 constant internal SF_TOKEN_AGREEMENT_ALREADY_EXISTS = 5000; uint256 constant internal SF_TOKEN_AGREEMENT_DOES_NOT_EXIST = 5001; uint256 constant internal SF_TOKEN_BURN_INSUFFICIENT_BALANCE = 5100; uint256 constant internal SF_TOKEN_MOVE_INSUFFICIENT_BALANCE = 5101; uint256 constant internal SF_TOKEN_ONLY_LISTED_AGREEMENT = 5300; uint256 constant internal SF_TOKEN_ONLY_HOST = 5400; // 6000 - 6999 | SuperToken uint256 constant internal SUPER_TOKEN_ONLY_HOST = 6400; uint256 constant internal SUPER_TOKEN_APPROVE_FROM_ZERO_ADDRESS = 6500; uint256 constant internal SUPER_TOKEN_APPROVE_TO_ZERO_ADDRESS = 6501; uint256 constant internal SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS = 6502; uint256 constant internal SUPER_TOKEN_MINT_TO_ZERO_ADDRESS = 6503; uint256 constant internal SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS = 6504; uint256 constant internal SUPER_TOKEN_TRANSFER_TO_ZERO_ADDRESS = 6505; // 7000 - 7999 | SuperToken Factory uint256 constant internal SUPER_TOKEN_FACTORY_ONLY_HOST = 7400; uint256 constant internal SUPER_TOKEN_FACTORY_ZERO_ADDRESS = 7500; // 8000 - 8999 | Agreement Base uint256 constant internal AGREEMENT_BASE_ONLY_HOST = 8400; }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol"; import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol"; import { SuperfluidErrors } from "../superfluid/Definitions.sol"; /** * @title Instant Distribution Agreement interface * @author Superfluid * * @notice * - A publisher can create as many as indices as possibly identifiable with `indexId`. * - `indexId` is deliberately limited to 32 bits, to avoid the chance for sha-3 collision. * Despite knowing sha-3 collision is only theoretical. * - A publisher can create a subscription to an index for any subscriber. * - A subscription consists of: * - The index it subscribes to. * - Number of units subscribed. * - An index consists of: * - Current value as `uint128 indexValue`. * - Total units of the approved subscriptions as `uint128 totalUnitsApproved`. * - Total units of the non approved subscription as `uint128 totalUnitsPending`. * - A publisher can update an index with a new value that doesn't decrease. * - A publisher can update a subscription with any number of units. * - A publisher or a subscriber can delete a subscription and reset its units to zero. * - A subscriber must approve the index in order to receive distributions from the publisher * each time the index is updated. * - The amount distributed is $$\Delta{index} * units$$ * - Distributions to a non approved subscription stays in the publisher's deposit until: * - the subscriber approves the subscription (side effect), * - the publisher updates the subscription (side effect), * - the subscriber deletes the subscription even if it is never approved (side effect), * - or the subscriber can explicitly claim them. */ abstract contract IInstantDistributionAgreementV1 is ISuperAgreement { /************************************************************************** * Errors *************************************************************************/ error IDA_INDEX_SHOULD_GROW(); // index value should grow error IDA_OPERATION_NOT_ALLOWED(); // operation not allowed /// @dev ISuperAgreement.agreementType implementation function agreementType() external override pure returns (bytes32) { return keccak256("org.superfluid-finance.agreements.InstantDistributionAgreement.v1"); } /************************************************************************** * Index operations *************************************************************************/ /** * @dev Create a new index for the publisher * @param token Super token address * @param indexId Id of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * None */ function createIndex( ISuperfluidToken token, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index created event * @param token Super token address * @param publisher Index creator and publisher * @param indexId The specified indexId of the newly created index * @param userData The user provided data */ event IndexCreated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, bytes userData); /** * @dev Query the data of a index * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @return exist Does the index exist * @return indexValue Value of the current index * @return totalUnitsApproved Total units approved for the index * @return totalUnitsPending Total units pending approval for the index */ function getIndex( ISuperfluidToken token, address publisher, uint32 indexId) external view virtual returns( bool exist, uint128 indexValue, uint128 totalUnitsApproved, uint128 totalUnitsPending); /** * @dev Calculate actual distribution amount * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param amount The amount of tokens desired to be distributed * @return actualAmount The amount to be distributed after ensuring no rounding errors * @return newIndexValue The index value given the desired amount of tokens to be distributed */ function calculateDistribution( ISuperfluidToken token, address publisher, uint32 indexId, uint256 amount) external view virtual returns( uint256 actualAmount, uint128 newIndexValue); /** * @dev Update index value of an index * @param token Super token address * @param indexId Id of the index * @param indexValue Value of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * None */ function updateIndex( ISuperfluidToken token, uint32 indexId, uint128 indexValue, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index updated event * @param token Super token address * @param publisher Index updater and publisher * @param indexId The specified indexId of the updated index * @param oldIndexValue The previous index value * @param newIndexValue The updated index value * @param totalUnitsPending The total units pending when the indexValue was updated * @param totalUnitsApproved The total units approved when the indexValue was updated * @param userData The user provided data */ event IndexUpdated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, uint128 oldIndexValue, uint128 newIndexValue, uint128 totalUnitsPending, uint128 totalUnitsApproved, bytes userData); /** * @dev Distribute tokens through the index * @param token Super token address * @param indexId Id of the index * @param amount The amount of tokens desired to be distributed * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:note * - This is a convenient version of updateIndex. It adds to the index * a delta that equals to `amount / totalUnits` * - The actual amount distributed could be obtained via * `calculateDistribution`. This is due to precision error with index * value and units data range * * @custom:callbacks * None */ function distribute( ISuperfluidToken token, uint32 indexId, uint256 amount, bytes calldata ctx) external virtual returns(bytes memory newCtx); /************************************************************************** * Subscription operations *************************************************************************/ /** * @dev Approve the subscription of an index * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - if subscription exist * - AgreementCreated callback to the publisher: * - agreementId is for the subscription * - if subscription does not exist * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function approveSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index subscribed event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The approved subscriber * @param userData The user provided data */ event IndexSubscribed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, bytes userData); /** * @dev Subscription approved event * @param token Super token address * @param subscriber The approved subscriber * @param publisher Index publisher * @param indexId The specified indexId * @param userData The user provided data */ event SubscriptionApproved( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, bytes userData); /** * @notice Revoke the subscription of an index * @dev "Unapproves" the subscription and moves approved units to pending * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function revokeSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index unsubscribed event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The unsubscribed subscriber * @param userData The user provided data */ event IndexUnsubscribed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, bytes userData); /** * @dev Subscription approved event * @param token Super token address * @param subscriber The approved subscriber * @param publisher Index publisher * @param indexId The specified indexId * @param userData The user provided data */ event SubscriptionRevoked( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, bytes userData); /** * @dev Update the nuber of units of a subscription * @param token Super token address * @param indexId Id of the index * @param subscriber The subscriber of the index * @param units Number of units of the subscription * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - if subscription exist * - AgreementCreated callback to the subscriber: * - agreementId is for the subscription * - if subscription does not exist * - AgreementUpdated callback to the subscriber: * - agreementId is for the subscription */ function updateSubscription( ISuperfluidToken token, uint32 indexId, address subscriber, uint128 units, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index units updated event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The subscriber units updated * @param units The new units amount * @param userData The user provided data */ event IndexUnitsUpdated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, uint128 units, bytes userData); /** * @dev Subscription units updated event * @param token Super token address * @param subscriber The subscriber units updated * @param indexId The specified indexId * @param publisher Index publisher * @param units The new units amount * @param userData The user provided data */ event SubscriptionUnitsUpdated( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, uint128 units, bytes userData); /** * @dev Get data of a subscription * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param subscriber The subscriber of the index * @return exist Does the subscription exist? * @return approved Is the subscription approved? * @return units Units of the suscription * @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription */ function getSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber) external view virtual returns( bool exist, bool approved, uint128 units, uint256 pendingDistribution ); /** * @notice Get data of a subscription by agreement ID * @dev indexId (agreementId) is the keccak256 hash of encodePacked("publisher", publisher, indexId) * @param token Super token address * @param agreementId The agreement ID * @return publisher The publisher of the index * @return indexId Id of the index * @return approved Is the subscription approved? * @return units Units of the suscription * @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription */ function getSubscriptionByID( ISuperfluidToken token, bytes32 agreementId) external view virtual returns( address publisher, uint32 indexId, bool approved, uint128 units, uint256 pendingDistribution ); /** * @dev List subscriptions of an user * @param token Super token address * @param subscriber The subscriber's address * @return publishers Publishers of the subcriptions * @return indexIds Indexes of the subscriptions * @return unitsList Units of the subscriptions */ function listSubscriptions( ISuperfluidToken token, address subscriber) external view virtual returns( address[] memory publishers, uint32[] memory indexIds, uint128[] memory unitsList); /** * @dev Delete the subscription of an user * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param subscriber The subscriber's address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - if the subscriber called it * - AgreementTerminated callback to the publsiher: * - agreementId is for the subscription * - if the publisher called it * - AgreementTerminated callback to the subscriber: * - agreementId is for the subscription */ function deleteSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Claim pending distributions * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param subscriber The subscriber's address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:note The subscription should not be approved yet * * @custom:callbacks * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function claim( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index distribution claimed event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The subscriber units updated * @param amount The pending amount claimed */ event IndexDistributionClaimed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, uint256 amount); /** * @dev Subscription distribution claimed event * @param token Super token address * @param subscriber The subscriber units updated * @param publisher Index publisher * @param indexId The specified indexId * @param amount The pending amount claimed */ event SubscriptionDistributionClaimed( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, uint256 amount); }
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.16; import { ISuperfluidGovernance, ISuperfluid, ISuperfluidToken, ISuperApp, SuperAppDefinitions, ContextDefinitions } from "../interfaces/superfluid/ISuperfluid.sol"; import { ISuperfluidToken } from "../interfaces/superfluid/ISuperfluidToken.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; /** * @title Agreement Library * @author Superfluid * @dev Helper library for building super agreement */ library AgreementLibrary { using SafeCast for uint256; using SafeCast for int256; /************************************************************************** * Context helpers *************************************************************************/ /** * @dev Authorize the msg.sender to access token agreement storage * * NOTE: * - msg.sender must be the expected host contract. * - it should revert on unauthorized access. */ function authorizeTokenAccess(ISuperfluidToken token, bytes memory ctx) internal view returns (ISuperfluid.Context memory) { require(token.getHost() == msg.sender, "unauthorized host"); require(ISuperfluid(msg.sender).isCtxValid(ctx), "invalid ctx"); return ISuperfluid(msg.sender).decodeCtx(ctx); } /************************************************************************** * Agreement callback helpers *************************************************************************/ struct CallbackInputs { ISuperfluidToken token; address account; bytes32 agreementId; bytes agreementData; uint256 appCreditGranted; int256 appCreditUsed; uint256 noopBit; } function createCallbackInputs( ISuperfluidToken token, address account, bytes32 agreementId, bytes memory agreementData ) internal pure returns (CallbackInputs memory inputs) { inputs.token = token; inputs.account = account; inputs.agreementId = agreementId; inputs.agreementData = agreementData; } function callAppBeforeCallback( CallbackInputs memory inputs, bytes memory ctx ) internal returns(bytes memory cbdata) { bool isSuperApp; bool isJailed; uint256 noopMask; (isSuperApp, isJailed, noopMask) = ISuperfluid(msg.sender).getAppManifest(ISuperApp(inputs.account)); if (isSuperApp && !isJailed) { bytes memory appCtx = _pushCallbackStack(ctx, inputs); if ((noopMask & inputs.noopBit) == 0) { bytes memory callData = abi.encodeWithSelector( _selectorFromNoopBit(inputs.noopBit), inputs.token, address(this) /* agreementClass */, inputs.agreementId, inputs.agreementData, new bytes(0) // placeholder ctx ); cbdata = ISuperfluid(msg.sender).callAppBeforeCallback( ISuperApp(inputs.account), callData, inputs.noopBit == SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP, appCtx); } // [SECURITY] NOTE: ctx should be const, do not modify it ever to ensure callback stack correctness _popCallbackStack(ctx, 0); } } function callAppAfterCallback( CallbackInputs memory inputs, bytes memory cbdata, bytes /* const */ memory ctx ) internal returns (ISuperfluid.Context memory appContext, bytes memory newCtx) { bool isSuperApp; bool isJailed; uint256 noopMask; (isSuperApp, isJailed, noopMask) = ISuperfluid(msg.sender).getAppManifest(ISuperApp(inputs.account)); newCtx = ctx; if (isSuperApp && !isJailed) { newCtx = _pushCallbackStack(newCtx, inputs); if ((noopMask & inputs.noopBit) == 0) { bytes memory callData = abi.encodeWithSelector( _selectorFromNoopBit(inputs.noopBit), inputs.token, address(this) /* agreementClass */, inputs.agreementId, inputs.agreementData, cbdata, new bytes(0) // placeholder ctx ); newCtx = ISuperfluid(msg.sender).callAppAfterCallback( ISuperApp(inputs.account), callData, inputs.noopBit == SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP, newCtx); appContext = ISuperfluid(msg.sender).decodeCtx(newCtx); // adjust credit used to the range [appCreditUsed..appCreditGranted] appContext.appCreditUsed = _adjustNewAppCreditUsed( inputs.appCreditGranted, appContext.appCreditUsed ); } // [SECURITY] NOTE: ctx should be const, do not modify it ever to ensure callback stack correctness newCtx = _popCallbackStack(ctx, appContext.appCreditUsed); } } /** * @dev Determines how much app credit the app will use. * @param appCreditGranted set prior to callback based on input flow * @param appCallbackDepositDelta set in callback - sum of deposit deltas of callback agreements and * current flow owed deposit amount */ function _adjustNewAppCreditUsed( uint256 appCreditGranted, int256 appCallbackDepositDelta ) internal pure returns (int256) { // NOTE: we use max(0, ...) because appCallbackDepositDelta can be negative and appCallbackDepositDelta // should never go below 0, otherwise the SuperApp can return more money than borrowed return max( 0, // NOTE: we use min(appCreditGranted, appCallbackDepositDelta) to ensure that the SuperApp borrows // appCreditGranted at most and appCallbackDepositDelta at least (if smaller than appCreditGranted) min( appCreditGranted.toInt256(), appCallbackDepositDelta ) ); } function _selectorFromNoopBit(uint256 noopBit) private pure returns (bytes4 selector) { if (noopBit == SuperAppDefinitions.BEFORE_AGREEMENT_CREATED_NOOP) { return ISuperApp.beforeAgreementCreated.selector; } else if (noopBit == SuperAppDefinitions.BEFORE_AGREEMENT_UPDATED_NOOP) { return ISuperApp.beforeAgreementUpdated.selector; } else if (noopBit == SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP) { return ISuperApp.beforeAgreementTerminated.selector; } else if (noopBit == SuperAppDefinitions.AFTER_AGREEMENT_CREATED_NOOP) { return ISuperApp.afterAgreementCreated.selector; } else if (noopBit == SuperAppDefinitions.AFTER_AGREEMENT_UPDATED_NOOP) { return ISuperApp.afterAgreementUpdated.selector; } else /* if (noopBit == SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP) */ { return ISuperApp.afterAgreementTerminated.selector; } } function _pushCallbackStack( bytes memory ctx, CallbackInputs memory inputs ) private returns (bytes memory appCtx) { // app credit params stack PUSH // pass app credit and current credit used to the app, appCtx = ISuperfluid(msg.sender).appCallbackPush( ctx, ISuperApp(inputs.account), inputs.appCreditGranted, inputs.appCreditUsed, inputs.token); } function _popCallbackStack( bytes memory ctx, int256 appCreditUsedDelta ) private returns (bytes memory newCtx) { // app credit params stack POP return ISuperfluid(msg.sender).appCallbackPop(ctx, appCreditUsedDelta); } /************************************************************************** * Misc *************************************************************************/ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } function min(int256 a, int256 b) internal pure returns (int256) { return a > b ? b : a; } }
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.16; import { UUPSProxiable } from "../upgradability/UUPSProxiable.sol"; import { ISuperAgreement } from "../interfaces/superfluid/ISuperAgreement.sol"; import { SuperfluidErrors } from "../interfaces/superfluid/Definitions.sol"; /** * @title Superfluid agreement base boilerplate contract * @author Superfluid */ abstract contract AgreementBase is UUPSProxiable, ISuperAgreement { address immutable internal _host; constructor(address host) { _host = host; } function proxiableUUID() public view override returns (bytes32) { return ISuperAgreement(this).agreementType(); } function updateCode(address newAddress) external override { if (msg.sender != _host) revert SuperfluidErrors.ONLY_HOST(SuperfluidErrors.AGREEMENT_BASE_ONLY_HOST); return _updateCodeAddress(newAddress); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol) pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248) { require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits"); return int248(value); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240) { require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits"); return int240(value); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232) { require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits"); return int232(value); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224) { require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits"); return int224(value); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216) { require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits"); return int216(value); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208) { require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits"); return int208(value); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200) { require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits"); return int200(value); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192) { require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits"); return int192(value); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184) { require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits"); return int184(value); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176) { require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits"); return int176(value); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168) { require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits"); return int168(value); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160) { require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits"); return int160(value); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152) { require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits"); return int152(value); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144) { require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits"); return int144(value); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136) { require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits"); return int136(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120) { require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits"); return int120(value); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112) { require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits"); return int112(value); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104) { require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits"); return int104(value); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96) { require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits"); return int96(value); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88) { require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits"); return int88(value); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80) { require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits"); return int80(value); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72) { require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits"); return int72(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56) { require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits"); return int56(value); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48) { require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits"); return int48(value); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40) { require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits"); return int40(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24) { require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits"); return int24(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/IERC777.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777Token standard as defined in the EIP. * * This contract uses the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let * token holders and recipients react to token movements by using setting implementers * for the associated interfaces in said registry. See {IERC1820Registry} and * {ERC1820Implementer}. */ interface IERC777 { /** * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`. * * Note that some additional user `data` and `operatorData` can be logged in the event. */ event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); /** * @dev Emitted when `operator` destroys `amount` tokens from `account`. * * Note that some additional user `data` and `operatorData` can be logged in the event. */ event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); /** * @dev Emitted when `operator` is made operator for `tokenHolder` */ event AuthorizedOperator(address indexed operator, address indexed tokenHolder); /** * @dev Emitted when `operator` is revoked its operator status for `tokenHolder` */ event RevokedOperator(address indexed operator, address indexed tokenHolder); /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * For most token contracts, this value will equal 1. */ function granularity() external view returns (uint256); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address owner) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send( address recipient, uint256 amount, bytes calldata data ) external; /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply. * * If a send hook is registered for the caller, the corresponding function * will be called with `data` and empty `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata data) external; /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * Emits an {AuthorizedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external; /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * Emits a {RevokedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function revokeOperator(address operator) external; /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `data` and `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; event Sent( address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "london", "libraries": { "/contracts/libs/SlotsBitmapLibrary.sol": { "SlotsBitmapLibrary": "0x3acF197E729fB2816DCa7d61f3622ed77eCABbf7" } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"inputs":[{"internalType":"contract ISuperfluid","name":"host","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"_code","type":"uint256"}],"name":"ALREADY_EXISTS","type":"error"},{"inputs":[{"internalType":"uint256","name":"_code","type":"uint256"}],"name":"DOES_NOT_EXIST","type":"error"},{"inputs":[],"name":"IDA_INDEX_SHOULD_GROW","type":"error"},{"inputs":[],"name":"IDA_OPERATION_NOT_ALLOWED","type":"error"},{"inputs":[{"internalType":"uint256","name":"_code","type":"uint256"}],"name":"INSUFFICIENT_BALANCE","type":"error"},{"inputs":[{"internalType":"uint256","name":"_code","type":"uint256"}],"name":"ONLY_HOST","type":"error"},{"inputs":[{"internalType":"uint256","name":"_code","type":"uint256"}],"name":"ZERO_ADDRESS","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"uuid","type":"bytes32"},{"indexed":false,"internalType":"address","name":"codeAddress","type":"address"}],"name":"CodeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"publisher","type":"address"},{"indexed":true,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"IndexCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"publisher","type":"address"},{"indexed":true,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"IndexDistributionClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"publisher","type":"address"},{"indexed":true,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"IndexSubscribed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"publisher","type":"address"},{"indexed":true,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"uint128","name":"units","type":"uint128"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"IndexUnitsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"publisher","type":"address"},{"indexed":true,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"IndexUnsubscribed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"publisher","type":"address"},{"indexed":true,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"uint128","name":"oldIndexValue","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newIndexValue","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"totalUnitsPending","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"totalUnitsApproved","type":"uint128"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"IndexUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"address","name":"publisher","type":"address"},{"indexed":false,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"SubscriptionApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"address","name":"publisher","type":"address"},{"indexed":false,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SubscriptionDistributionClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"address","name":"publisher","type":"address"},{"indexed":false,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"SubscriptionRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"subscriber","type":"address"},{"indexed":false,"internalType":"address","name":"publisher","type":"address"},{"indexed":false,"internalType":"uint32","name":"indexId","type":"uint32"},{"indexed":false,"internalType":"uint128","name":"units","type":"uint128"},{"indexed":false,"internalType":"bytes","name":"userData","type":"bytes"}],"name":"SubscriptionUnitsUpdated","type":"event"},{"inputs":[],"name":"SLOTS_BITMAP_LIBRARY_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"agreementType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"approveSubscription","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateDistribution","outputs":[{"internalType":"uint256","name":"actualAmount","type":"uint256"},{"internalType":"uint128","name":"newIndexValue","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"castrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"claim","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"createIndex","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"deleteSubscription","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"distribute","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCodeAddress","outputs":[{"internalType":"address","name":"codeAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"}],"name":"getIndex","outputs":[{"internalType":"bool","name":"exist","type":"bool"},{"internalType":"uint128","name":"indexValue","type":"uint128"},{"internalType":"uint128","name":"totalUnitsApproved","type":"uint128"},{"internalType":"uint128","name":"totalUnitsPending","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"address","name":"subscriber","type":"address"}],"name":"getSubscription","outputs":[{"internalType":"bool","name":"exist","type":"bool"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint128","name":"units","type":"uint128"},{"internalType":"uint256","name":"pendingDistribution","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"bytes32","name":"agreementId","type":"bytes32"}],"name":"getSubscriptionByID","outputs":[{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint128","name":"units","type":"uint128"},{"internalType":"uint256","name":"pendingDistribution","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"subscriber","type":"address"}],"name":"listSubscriptions","outputs":[{"internalType":"address[]","name":"publishers","type":"address[]"},{"internalType":"uint32[]","name":"indexIds","type":"uint32[]"},{"internalType":"uint128[]","name":"unitsList","type":"uint128[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"realtimeBalanceOf","outputs":[{"internalType":"int256","name":"dynamicBalance","type":"int256"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"uint256","name":"owedDeposit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"address","name":"publisher","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"revokeSubscription","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"updateCode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"uint128","name":"indexValue","type":"uint128"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"updateIndex","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperfluidToken","name":"token","type":"address"},{"internalType":"uint32","name":"indexId","type":"uint32"},{"internalType":"address","name":"subscriber","type":"address"},{"internalType":"uint128","name":"units","type":"uint128"},{"internalType":"bytes","name":"ctx","type":"bytes"}],"name":"updateSubscription","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200538238038062005382833981016040819052620000349162000046565b6001600160a01b031660805262000078565b6000602082840312156200005957600080fd5b81516001600160a01b03811681146200007157600080fd5b9392505050565b6080516152ee6200009460003960006110d701526152ee6000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637fbc7639116100ad578063acf4a6c211610071578063acf4a6c214610320578063b6dacdb814610333578063b96731c214610355578063cd7245c514610368578063d787840a146103c057600080fd5b80637fbc763914610294578063899baaec146102a75780639903ad38146102d75780639b2e48bc146102df578063acafa1b81461030d57600080fd5b806350d75d25116100f457806350d75d25146101f957806352d1902d146102015780635b534051146102175780636041ae961461025b5780637730599e1461026e57600080fd5b8063232d2b581461013157806323fc23f31461015a5780632e5e74c61461019e5780633fd4176a146101b157806346951954146101e4575b600080fd5b61014461013f3660046143c7565b6103d3565b60405161015191906144a2565b60405180910390f35b61016d6101683660046144b5565b610af6565b6040805194151585526001600160801b03938416602086015291831691840191909152166060820152608001610151565b6101446101ac366004614500565b610b61565b6101cc733acf197e729fb2816dca7d61f3622ed77ecabbf781565b6040516001600160a01b039091168152602001610151565b6101f76101f2366004614554565b6110cc565b005b6101cc611125565b610209611154565b604051908152602001610151565b61022a610225366004614578565b6111b8565b6040516101519493929190931515845291151560208401526001600160801b03166040830152606082015260800190565b6101446102693660046145d4565b61128e565b7f8aedc3b5d4bf031e11a7e2940f7251c005698405d58e02e1c247fed3b1b3a674610209565b6101446102a236600461464f565b6116b7565b6102ba6102b5366004614690565b6117a4565b604080519283526001600160801b03909116602083015201610151565b6101f761184d565b6102f26102ed3660046146e1565b611956565b60408051938452602084019290925290820152606001610151565b61014461031b366004614500565b611b61565b61014461032e3660046145d4565b611f6e565b610346610341366004614722565b61252c565b6040516101519392919061479f565b61014461036336600461483c565b612781565b61037b610376366004614891565b612881565b604080516001600160a01b03909616865263ffffffff9094166020860152911515928401929092526001600160801b039091166060830152608082015260a001610151565b6101446103ce3660046148bd565b612987565b60606001600160a01b0385166104055760405163e961d6ff60e01b81526109c460048201526024015b60405180910390fd5b61040d61421f565b61041561427d565b606060008061045a8c89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b90508060a00151925080606001519150506104798b828b8d6000612d13565b60808901521515602080890191909152606088019190915260408088018390529287528251908101909252600082526104b5918d918c91612e0e565b925086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050602086015191965050156105195764040000000060c084015261050f8386612e3c565b60a0850152610534565b64010000000060c084015261052e8386612e3c565b60a08501525b83602001518015610551575060808401515163ffffffff90811614155b1561062c576105a08460800151608001516001600160801b0316896001600160801b03168660600151602001516001600160801b03166105919190614937565b61059b919061494a565b612ff3565b6060850180516001600160801b03909216602090920191909152845190516001600160a01b038d169163a1b2bf8b916105d890613060565b6040518363ffffffff1660e01b81526004016105f592919061498d565b600060405180830381600087803b15801561060f57600080fd5b505af1158015610623573d6000803e3d6000fd5b50505050610813565b8360200151156106a9576106718460800151608001516001600160801b0316896001600160801b03168660600151604001516001600160801b03166105919190614937565b6060850180516001600160801b03909216604090920191909152845190516001600160a01b038d169163a1b2bf8b916105d890613060565b6040518060a0016040528063ffffffff80168152602001826001600160a01b031681526020018b63ffffffff1681526020018560600151600001516001600160801b03168152602001896001600160801b031681525084608001819052508a6001600160a01b03166312a6a3f8856040015161072887608001516130fe565b6040518363ffffffff1660e01b815260040161074592919061498d565b600060405180830381600087803b15801561075f57600080fd5b505af1158015610773573d6000803e3d6000fd5b505050508784606001516040015161078b91906149a6565b6060850180516001600160801b03909216604090920191909152845190516001600160a01b038d169163a1b2bf8b916107c390613060565b6040518363ffffffff1660e01b81526004016107e092919061498d565b600060405180830381600087803b1580156107fa57600080fd5b505af115801561080e573d6000803e3d6000fd5b505050505b60008460800151608001516001600160801b031685608001516060015186606001516000015161084391906149cd565b6001600160801b031661085691906149ed565b905063ffffffff801685608001516000015163ffffffff16036108ef576108868c8361088184614a72565b6131a5565b6001600160a01b038c1663cf97256d8361089f84614a72565b6040518363ffffffff1660e01b81526004016108bc929190614a8e565b600060405180830381600087803b1580156108d657600080fd5b505af11580156108ea573d6000803e3d6000fd5b505050505b60405163cf97256d60e01b81526001600160a01b038d169063cf97256d9061091d908d908590600401614a8e565b600060405180830381600087803b15801561093757600080fd5b505af115801561094b573d6000803e3d6000fd5b505050508460200151156109f15760608086015151608080880180516001600160801b039384169401939093528251918c16910152604086015190516001600160a01b038e169163a1b2bf8b916109a1906130fe565b6040518363ffffffff1660e01b81526004016109be92919061498d565b600060405180830381600087803b1580156109d857600080fd5b505af11580156109ec573d6000803e3d6000fd5b505050505b846020015115610a205764080000000060c085015260a0850151610a17908590886132f3565b9650610a409050565b64020000000060c085015260a0850151610a3c908590886132f3565b9650505b8a63ffffffff16826001600160a01b03168d6001600160a01b03167f0115987243fd19d615b5ea62a80372a06a2b37fec378b148ee7a507c5c4c0a398d8d88604051610a8e93929190614aa7565b60405180910390a4896001600160a01b03168c6001600160a01b03167fe0707ac7efb8b59c22189af8d004ed17dc9e4379e71b9066119b62c182524977848e8d88604051610adf9493929190614ae3565b60405180910390a350505050509695505050505050565b600080600080610b1f604080516060810182526000808252602082018190529181019190915290565b6000610b2b888861353f565b9050610b3789826135a6565b90965091508515610b5657815160208301516040840151919650945092505b505093509350935093565b6060610b6b61421f565b610b7361427d565b600060606000610bb98c89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b606081015160a0909101519093509150506001600160a01b038816610bf55760405163e961d6ff60e01b81526109c460048201526024016103fc565b896001600160a01b0316826001600160a01b031614610c27576040516392da6d1760e01b815260040160405180910390fd5b610c358b8b8a8c6001612d13565b6080890152506060870152604080870182905291865281516020810190925260008252610c65918d918b91612e0e565b925086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505064100000000060c087015250909550610cb690508386612e3c565b60a08501526080808501519081015160609182015191860151516000926001600160801b0390921691610ce8916149cd565b6001600160801b0316610cfb91906149ed565b60808601515190915063ffffffff90811614610d4857846080015160800151856060015160200151610d2d91906149cd565b60608601516001600160801b03909116602090910152610d7b565b846080015160800151856060015160400151610d6491906149cd565b60608601516001600160801b039091166040909101525b8b6001600160a01b031663a1b2bf8b8660000151610d9c8860600151613060565b6040518363ffffffff1660e01b8152600401610db992919061498d565b600060405180830381600087803b158015610dd357600080fd5b505af1158015610de7573d6000803e3d6000fd5b5050505060808501515163ffffffff90811614610e1157610e118c8a8760800151600001516136ba565b60808501515163ffffffff1663fffffffe1901610e9f57610e368c8c61088184614a72565b6001600160a01b038c1663cf97256d8c610e4f84614a72565b6040518363ffffffff1660e01b8152600401610e6c929190614a8e565b600060405180830381600087803b158015610e8657600080fd5b505af1158015610e9a573d6000803e3d6000fd5b505050505b6040858101519051632704839760e01b81526004810191909152600260248201526001600160a01b038d1690632704839790604401600060405180830381600087803b158015610eee57600080fd5b505af1158015610f02573d6000803e3d6000fd5b505060405163cf97256d60e01b81526001600160a01b038f16925063cf97256d9150610f34908c908590600401614a8e565b600060405180830381600087803b158015610f4e57600080fd5b505af1158015610f62573d6000803e3d6000fd5b505064200000000060c0870152505060a0850151610f82908590886132f3565b9050809650508963ffffffff168b6001600160a01b03168d6001600160a01b03167fe1f8e9cd8061e5b251769965bda6ca9ef1674bc6541fb9131039fa53f024d1428c86604051610fd4929190614b2c565b60405180910390a4886001600160a01b03168c6001600160a01b03167f9e02127550b99adc8cc6ee332a36f31338facdbc396cebefce9a047247cd04558d8d8660405161102393929190614b50565b60405180910390a38963ffffffff168b6001600160a01b03168d6001600160a01b03167f0115987243fd19d615b5ea62a80372a06a2b37fec378b148ee7a507c5c4c0a398c60008760405161107a93929190614aa7565b60405180910390a4886001600160a01b03168c6001600160a01b03167fe0707ac7efb8b59c22189af8d004ed17dc9e4379e71b9066119b62c1825249778d8d600087604051610adf9493929190614ae3565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461111957604051632a94f67960e21b81526120d060048201526024016103fc565b61112281613745565b50565b600061114f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905090565b6000306001600160a01b0316637730599e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611194573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114f9190614b80565b6000806000806000806111e4604080516060810182526000808252602082018190529181019190915290565b6111ec6142b8565b6111fa8c8c8b8d6000612d13565b909b50929650909450925090508761122357600080600080975097509750975050505050611283565b8051608082015163ffffffff9182169091141597509550866112795780608001516001600160801b03168160600151836000015161126191906149cd565b6001600160801b03166112749190614b99565b61127c565b60005b9450505050505b945094509450949050565b606061129861421f565b6112a061427d565b6000606060006112e68b89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b9050806060015192508060a001519150506113058a8a848b6001612d13565b6080890181905260608901929092525060408701919091529085525163ffffffff1663fffffffe190161134f57604051639995b0c160e01b81526107d460048201526024016103fc565b61136e8a8a866040015160405180602001604052806000815250612e0e565b925086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505064100000000060c0870152509095506113bf90508386612e3c565b60a08501526080808501519081015160609182015191860151516000926001600160801b03909216916113f1916149cd565b6001600160801b031661140491906149ed565b905084608001516080015185606001516020015161142291906149cd565b6060860180516001600160801b03909216602090920191909152608080870151015190516040015161145491906149a6565b6060860180516001600160801b03909216604090920191909152855190516001600160a01b038d169163a1b2bf8b9161148c90613060565b6040518363ffffffff1660e01b81526004016114a992919061498d565b600060405180830381600087803b1580156114c357600080fd5b505af11580156114d7573d6000803e3d6000fd5b505050506114ee8b848760800151600001516136ba565b606080860151516080870180516001600160801b039092169190920152805163ffffffff9052604086015190516001600160a01b038d169163a1b2bf8b91611535906130fe565b6040518363ffffffff1660e01b815260040161155292919061498d565b600060405180830381600087803b15801561156c57600080fd5b505af1158015611580573d6000803e3d6000fd5b505060405163cf97256d60e01b81526001600160a01b038e16925063cf97256d91506115b29086908590600401614a8e565b600060405180830381600087803b1580156115cc57600080fd5b505af11580156115e0573d6000803e3d6000fd5b505064200000000060c0870152505060a0850151611600908590886132f3565b9050809650508863ffffffff168a6001600160a01b03168c6001600160a01b03167fe1f8e9cd8061e5b251769965bda6ca9ef1674bc6541fb9131039fa53f024d1428686604051611652929190614b2c565b60405180910390a4826001600160a01b03168b6001600160a01b03167f9e02127550b99adc8cc6ee332a36f31338facdbc396cebefce9a047247cd04558c8c866040516116a193929190614b50565b60405180910390a3505050505095945050505050565b606060006116fb8785858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b60608101519091506000806117118a848b61394d565b9150915080600001516001600160801b0316886001600160801b0316101561174c5760405163cfdca72560e01b815260040160405180910390fd5b61175f8a848b85858d8a60a001516139b0565b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929d9c50505050505050505050505050565b60008060006117b3868661353f565b90506000806117c289846135a6565b91509150816117e857604051639995b0c160e01b81526107d160048201526024016103fc565b6000816040015182602001516117fe91906149a6565b6001600160801b03169050600061181861059b838a614bb8565b83519091506118289082906149a6565b955061183d826001600160801b038316614b99565b9650505050505094509492505050565b600054610100900460ff161580801561186d5750600054600160ff909116105b806118875750303b158015611887575060005460ff166001145b6118ea5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103fc565b6000805460ff19166001179055801561190d576000805461ff0019166101001790555b8015611122576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b60008060006060806119688888613be3565b909250905060005b81518163ffffffff161015611b455760006119896142b8565b600080868563ffffffff16815181106119a4576119a4614bda565b602002602001015190506119d78d878763ffffffff16815181106119ca576119ca614bda565b6020026020010151613cd6565b9094509250836119e9576119e9614bf0565b8063ffffffff16836000015163ffffffff1614611a0857611a08614bf0565b6001600160a01b038d16634b61cc33308e611a2d63ffffffff8616600160801b614937565b60016040518563ffffffff1660e01b8152600401611a4e9493929190614c06565b600060405180830381865afa158015611a6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a939190810190614d2c565b600081518110611aa557611aa5614bda565b6020026020010151915050611ad3604080516060810182526000808252602082018190529181019190915290565b611add8d836135a6565b909450905083611aef57611aef614bf0565b82608001516001600160801b031683606001518260000151611b1191906149cd565b6001600160801b0316611b2491906149ed565b611b2e908b614d60565b99505050505080611b3e90614d88565b9050611970565b50611b508888613df2565b935060009250505093509350939050565b6060611ba38784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b506001600160a01b038416611bcf5760405163e961d6ff60e01b81526109c460048201526024016103fc565b611bd761421f565b611bdf61427d565b611bed8989888a6001612d13565b6080870181905260608701929092525060408501919091529083525163ffffffff90811614611c3357604051635b5b42a560e01b81526107d360048201526024016103fc565b60008260800151608001516001600160801b0316836080015160600151846060015160000151611c6391906149cd565b6001600160801b0316611c769190614b99565b9050611c978a8a856040015160405180602001604052806000815250612e0e565b915085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509296505082159150611f2790505764040000000060c0830152611cef8285612e3c565b60a0840152611d028a8a61088184614a72565b6001600160a01b038a1663cf97256d8a611d1b84614a72565b6040518363ffffffff1660e01b8152600401611d38929190614a8e565b600060405180830381600087803b158015611d5257600080fd5b505af1158015611d66573d6000803e3d6000fd5b50505050606083810151516080850180516001600160801b039092169190920152604084015190516001600160a01b038c169163a1b2bf8b91611da8906130fe565b6040518363ffffffff1660e01b8152600401611dc592919061498d565b600060405180830381600087803b158015611ddf57600080fd5b505af1158015611df3573d6000803e3d6000fd5b505060405163cf97256d60e01b81526001600160a01b038d16925063cf97256d9150611e25908a908590600401614a8e565b600060405180830381600087803b158015611e3f57600080fd5b505af1158015611e53573d6000803e3d6000fd5b505050508763ffffffff16896001600160a01b03168b6001600160a01b03167f467eccd248ef31c8bcef16d94856855799a8783aeef10f3759e43614059a6bb18a85604051611ea3929190614a8e565b60405180910390a4604080516001600160a01b038b8116825263ffffffff8b166020830152918101839052818916918c16907f48a3d91d4a07e4982b081260e24f922bd33bb965882772d6de19c922c3eabdea9060600160405180910390a364080000000060c083015260a0830151611f1e908390866132f3565b9450611f619050565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509296505050505b5050509695505050505050565b6060611f7861421f565b611f8061427d565b600060606000611fc68b89898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b9050806060015192508060a00151915050611fe58a8a848b6000612d13565b60808901521580156020890152606088019190915260408701919091529085526120395760808401515163ffffffff9081161461203957604051635b5b42a560e01b81526107d360048201526024016103fc565b86868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040808a0151815160208101909252918152949950612092948f94508e9350909150612e0e565b925083602001516121bb5764010000000060c08401526120b28386612e3c565b60a08086019190915260408051918201815260008083526001600160a01b038c16602084015263ffffffff8b1691830191909152606080870151516001600160801b0316908301526080808301919091528501528351612115908b908490613e9b565b60808501805163ffffffff909216909152604085015190516001600160a01b038c16916312a6a3f891612147906130fe565b6040518363ffffffff1660e01b815260040161216492919061498d565b600060405180830381600087803b15801561217e57600080fd5b505af1158015612192573d6000803e3d6000fd5b505064020000000060c0860152505060a08401516121b2908490876132f3565b955061247c9050565b64040000000060c08401526121d08386612e3c565b60a08501526080808501519081015160609182015191860151516000926001600160801b0390921691612202916149cd565b6001600160801b031661221591906149ed565b9050846080015160800151856060015160200181815161223591906149a6565b6001600160801b031690525060808086015101516060860151604001805161225e9083906149cd565b6001600160801b0316905250845160608601516001600160a01b038d169163a1b2bf8b9161228b90613060565b6040518363ffffffff1660e01b81526004016122a892919061498d565b600060405180830381600087803b1580156122c257600080fd5b505af11580156122d6573d6000803e3d6000fd5b505050506122e98b8b8361088190614a72565b6001600160a01b038b1663cf97256d8b61230284614a72565b6040518363ffffffff1660e01b815260040161231f929190614a8e565b600060405180830381600087803b15801561233957600080fd5b505af115801561234d573d6000803e3d6000fd5b505060405163cf97256d60e01b81526001600160a01b038e16925063cf97256d915061237f9086908590600401614a8e565b600060405180830381600087803b15801561239957600080fd5b505af11580156123ad573d6000803e3d6000fd5b5050506060808701515160808801516001600160801b039091169101525084516123da908c908590613e9b565b60808601805163ffffffff909216909152604086015190516001600160a01b038d169163a1b2bf8b9161240c906130fe565b6040518363ffffffff1660e01b815260040161242992919061498d565b600060405180830381600087803b15801561244357600080fd5b505af1158015612457573d6000803e3d6000fd5b505064080000000060c0870152505060a0850151612477908590886132f3565b965050505b8763ffffffff16896001600160a01b03168b6001600160a01b03167f492d2641617cfaf24ac7328f85bc5bdf5113537d78dc7671afa4f49a73f053c285856040516124c8929190614b2c565b60405180910390a4816001600160a01b03168a6001600160a01b03167fc0b8396b655615cdb85fe462a9a1792480816f909cd46d9517a940b386dfbf6b8b8b8560405161251793929190614b50565b60405180910390a35050505095945050505050565b606080606080606061253e8787613be3565b9092509050600061254d6142b8565b82516001600160401b0381111561256657612566614c2f565b60405190808252806020026020018201604052801561258f578160200160208202803683370190505b50965082516001600160401b038111156125ab576125ab614c2f565b6040519080825280602002602001820160405280156125d4578160200160208202803683370190505b50955082516001600160401b038111156125f0576125f0614c2f565b604051908082528060200260200182016040528015612619578160200160208202803683370190505b50945060005b83518163ffffffff161015612775576000858263ffffffff168151811061264857612648614bda565b602002602001015190506000858363ffffffff168151811061266c5761266c614bda565b602002602001015190506126808c82613cd6565b90955093508461269257612692614bf0565b8163ffffffff16846000015163ffffffff16146126b1576126b1614bf0565b83602001518a8463ffffffff16815181106126ce576126ce614bda565b60200260200101906001600160a01b031690816001600160a01b0316815250508360400151898463ffffffff168151811061270b5761270b614bda565b602002602001019063ffffffff16908163ffffffff16815250508360800151888463ffffffff168151811061274257612742614bda565b60200260200101906001600160801b031690816001600160801b03168152505050508061276e90614d88565b905061261f565b50505050509250925092565b606060006127c58785858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b60608101519091506000806127db8a848b61394d565b915091506000816040015182602001516127f591906149a6565b6001600160801b03169050801561283b57600061281561059b838c614bb8565b90506128398c868d878786896000015161282f91906149a6565b8c60a001516139b0565b505b87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929e9d5050505050505050505050505050565b60008060008060008060006128af604080516060810182526000808252602082018190529181019190915290565b6128b76142b8565b6128c18b8b613cd6565b9094509050836128e857604051639995b0c160e01b81526107d260048201526024016103fc565b8060200151985080604001519750612900898961353f565b925061290c8b846135a6565b90945091508361291e5761291e614bf0565b8051608082015163ffffffff9182169091141597509550866129745780608001516001600160801b03168160600151836000015161295c91906149cd565b6001600160801b031661296f9190614b99565b612977565b60005b9450505050509295509295909350565b606060006129cb8685858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b4692505050565b606081015190915060006129df828861353f565b90506129eb8882613f42565b15612a0d57604051635b5b42a560e01b81526107d060048201526024016103fc565b876001600160a01b03166312a6a3f882612a5e604051806060016040528060006001600160801b0316815260200160006001600160801b0316815260200160006001600160801b0316815250613060565b6040518363ffffffff1660e01b8152600401612a7b92919061498d565b600060405180830381600087803b158015612a9557600080fd5b505af1158015612aa9573d6000803e3d6000fd5b505050508663ffffffff16826001600160a01b0316896001600160a01b03167f01ab8663165edfb7390d9e5f75d960a66dacf4f01fa9787e3a731c870d0da9218660a00151604051612afb91906144a2565b60405180910390a485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929b9a5050505050505050505050565b612b4e6142e6565b336001600160a01b0316836001600160a01b03166320bc44256040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bba9190614db6565b6001600160a01b031614612c045760405162461bcd60e51b81526020600482015260116024820152701d5b985d5d1a1bdc9a5e9959081a1bdcdd607a1b60448201526064016103fc565b604051632fd0a1cd60e21b8152339063bf42873490612c279085906004016144a2565b602060405180830381865afa158015612c44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c689190614de3565b612ca25760405162461bcd60e51b815260206004820152600b60248201526a0d2dcecc2d8d2c840c6e8f60ab1b60448201526064016103fc565b604051631fb6491d60e11b81523390633f6c923a90612cc59085906004016144a2565b600060405180830381865afa158015612ce2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d0a9190810190614e8a565b90505b92915050565b6040805160608101825260008082526020820181905291810182905281906000612d3b6142b8565b6000612d478a8961353f565b9550612d538987613fee565b9450612d5f8b876135a6565b9450905080612d8557604051639995b0c160e01b81526107d160048201526024016103fc565b612d8f8b86613cd6565b90935091508615612e005782612dbc57604051639995b0c160e01b81526107d260048201526024016103fc565b896001600160a01b031682602001516001600160a01b031614612de157612de1614bf0565b8763ffffffff16826040015163ffffffff1614612e0057612e00614bf0565b509550955095509550959050565b612e1661427d565b6001600160a01b0394851681529290931660208301526040820152606081019190915290565b6020820151604051633e7d48bd60e21b81526001600160a01b03909116600482015260609060009081908190339063f9f522f490602401606060405180830381865afa158015612e90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb49190614f90565b91945092509050828015612ec6575081155b15612fea576000612ed7868861402f565b90508660c001518216600003612fdc576000612ef68860c001516140ad565b88516040808b015160608c015182516000815260208101909352612f2293923092919060448101614fcc565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b031990951694909417909352918a015160c08b01519251633a020f0160e11b815291935033926374041e0292612f919291869164100000000091909114908890600401615011565b6000604051808303816000875af1158015612fb0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fd8919081019061505a565b9550505b612fe7866000614144565b50505b50505092915050565b60006001600160801b0382111561305c5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016103fc565b5090565b604080516002808252606080830184529260208301908036833701905050905081600001516001600160801b0316600160801b1760001b816000815181106130aa576130aa614bda565b602002602001018181525050608082604001516001600160801b0316901b82602001516001600160801b03161760001b816001815181106130ed576130ed614bda565b602002602001018181525050919050565b6040805160028082526060808301845292602083019080368337019050509050816000015163ffffffff166020836040015163ffffffff16901b606084602001516001600160a01b0316901b171760001b8160008151811061316257613162614bda565b602002602001018181525050608082608001516001600160801b0316901b82606001516001600160801b03161760001b816001815181106130ed576130ed614bda565b806000036131b257505050565b604051634b61cc3360e01b81526000906001600160a01b03851690634b61cc33906131ed903090879064010000000090600190600401614c06565b600060405180830381865afa15801561320a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132329190810190614d2c565b90508161325b8260008151811061324b5761324b614bda565b602002602001015160001c61416c565b6132659190614d60565b60001b8160008151811061327b5761327b614bda565b602090810291909101015260405163048620af60e11b81526001600160a01b0385169063090c415e906132bb90869064010000000090869060040161508e565b600060405180830381600087803b1580156132d557600080fd5b505af11580156132e9573d6000803e3d6000fd5b5050505050505050565b6132fb6142e6565b6020840151604051633e7d48bd60e21b81526001600160a01b03909116600482015260609060009081908190339063f9f522f490602401606060405180830381865afa15801561334f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133739190614f90565b88965091945092509050828015613388575081155b1561353457613397848961402f565b93508760c0015181166000036135225760006133b68960c001516140ad565b89516040808c015160608d0151825160008152602081019093526133e49392309291908e90604481016150b5565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b031990951694909417909352918b015160c08c0151925163079b42a160e21b81529193503392631e6d0a84926134539291869164200000000091909114908b90600401615011565b6000604051808303816000875af1158015613472573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261349a919081019061505a565b604051631fb6491d60e11b81529095503390633f6c923a906134c09088906004016144a2565b600060405180830381865afa1580156134dd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135059190810190614e8a565b955061351a89608001518761010001516141d6565b610100870152505b61353186866101000151614144565b93505b505050935093915050565b60405168383ab13634b9b432b960b91b60208201526bffffffffffffffffffffffff19606084901b1660298201526001600160e01b031960e083901b16603d8201526000906041015b60405160208183030381529060405280519060200120905092915050565b60408051606081018252600080825260208201819052918101829052604051636c2d9f2f60e01b815230600482015260248101849052600260448201526000906001600160a01b03861690636c2d9f2f90606401600060405180830381865afa158015613617573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261363f9190810190614d2c565b905060008160008151811061365657613656614bda565b602002602001015160001c905060008260018151811061367857613678614bda565b602002602001015160001c905060008211945084156136b0576001600160801b03808316855281166020850152608081901c60408501525b5050509250929050565b604051631528e57f60e31b81526001600160a01b038085166004830152831660248201526000604482015263ffffffff82166064820152733acf197e729fb2816dca7d61f3622ed77ecabbf79063a9472bf89060840160006040518083038186803b15801561372857600080fd5b505af415801561373c573d6000803e3d6000fd5b50505050505050565b600061376f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b0316036137c55760405162461bcd60e51b815260206004820152601d60248201527f5555505350726f786961626c653a206e6f742075706772616461626c6500000060448201526064016103fc565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613803573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138279190614b80565b61382f611154565b146138885760405162461bcd60e51b815260206004820152602360248201527f5555505350726f786961626c653a206e6f7420636f6d70617469626c65206c6f60448201526267696360e81b60648201526084016103fc565b6001600160a01b03811630036138e05760405162461bcd60e51b815260206004820152601960248201527f5555505350726f786961626c653a2070726f7879206c6f6f700000000000000060448201526064016103fc565b613908817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fe011bc04c286c344a8fcbb8de77f953da762c3e25d8cdea984147fc4168a5dcc613931611154565b604080519182526001600160a01b03841660208301520161194b565b604080516060810182526000808252602082018190529181018290526000613975858561353f565b925061398186846135a6565b92509050806139a757604051639995b0c160e01b81526107d160048201526024016103fc565b50935093915050565b866001600160a01b031663cf97256d8785602001516001600160801b03168660000151866139de91906149cd565b6001600160801b03166139f090614a72565b6139fa91906149ed565b6040518363ffffffff1660e01b8152600401613a17929190614a8e565b600060405180830381600087803b158015613a3157600080fd5b505af1158015613a45573d6000803e3d6000fd5b50505050613a7f878785604001516001600160801b0316866000015186613a6c91906149cd565b6001600160801b031661088191906149ed565b82516001600160801b03831684526001600160a01b03881663a1b2bf8b86613aa687613060565b6040518363ffffffff1660e01b8152600401613ac392919061498d565b600060405180830381600087803b158015613add57600080fd5b505af1158015613af1573d6000803e3d6000fd5b505050508563ffffffff16876001600160a01b0316896001600160a01b03167f81e37f3d9f16cbf29a62d6a1c21d79b23ef29b54124ec44af43a50fffb9304f3848789604001518a6020015189604051613b4f95949392919061511b565b60405180910390a46040516379359f6f60e01b81526001600160a01b0388811660048301528916906379359f6f90602401602060405180830381865afa158015613b9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bc19190614de3565b156132e957604051636212897360e01b815261083460048201526024016103fc565b606080733acf197e729fb2816dca7d61f3622ed77ecabbf76306967a8c85856000600160801b6040518563ffffffff1660e01b8152600401613c289493929190614c06565b600060405180830381865af4158015613c45573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c6d9190810190615157565b909250905060005b8151811015613cce57613ca184838381518110613c9457613c94614bda565b6020026020010151613fee565b828281518110613cb357613cb3614bda565b6020908102919091010152613cc78161521b565b9050613c75565b509250929050565b6000613ce06142b8565b604051636c2d9f2f60e01b815230600482015260248101849052600260448201526000906001600160a01b03861690636c2d9f2f90606401600060405180830381865afa158015613d35573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613d5d9190810190614d2c565b9050600081600081518110613d7457613d74614bda565b602002602001015160001c9050600082600181518110613d9657613d96614bda565b602002602001015160001c905060008211945084156136b057606082811c60208087019190915283901c63ffffffff9081166040870152831685526001600160801b03821690850152608081811c908501525050509250929050565b600080836001600160a01b0316634b61cc33308564010000000060016040518563ffffffff1660e01b8152600401613e2d9493929190614c06565b600060405180830381865afa158015613e4a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613e729190810190614d2c565b905080600081518110613e8757613e87614bda565b602002602001015160001c91505092915050565b604051630a32470160e41b81526001600160a01b03808516600483015283166024820152600060448201819052600160801b60648301526084820183905290733acf197e729fb2816dca7d61f3622ed77ecabbf79063a32470109060a401602060405180830381865af4158015613f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f3a9190615234565b949350505050565b604051636c2d9f2f60e01b8152306004820152602481018290526002604482015260009081906001600160a01b03851690636c2d9f2f90606401600060405180830381865afa158015613f99573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613fc19190810190614d2c565b9050600081600081518110613fd857613fd8614bda565b6020908102919091010151151595945050505050565b604080516b39bab139b1b934b83a34b7b760a11b6020820152606084811b6bffffffffffffffffffffffff1916602c83015291810183905260009101613588565b6020810151608082015160a08301518351604051630768fabb60e41b8152606094339463768fabb094614066948a94600401615251565b6000604051808303816000875af1158015614085573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d0a919081019061505a565b600064010000000082036140c957506330d9c91560e01b919050565b64040000000082036140e35750630221347d60e61b919050565b64100000000082036140fd5750635f9e7d7760e01b919050565b6402000000008203614117575063d86ed3e560e01b919050565b6408000000008203614131575063230dbd2960e01b919050565b506353c11f9960e01b919050565b919050565b604051634c4d861f60e11b8152606090339063989b0c3e906140669086908690600401615296565b60006001600160ff1b0382111561305c5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016103fc565b6000612d0a60006141ef6141e98661416c565b856141f4565b614209565b60008183136142035782612d0a565b50919050565b60008183136142185781612d0a565b5090919050565b6040805160c0810182526000808252602082018190529181019190915260608101614263604080516060810182526000808252602082018190529181019190915290565b81526020016142706142b8565b8152602001606081525090565b6040805160e0810182526000808252602082018190529181018290526060808201526080810182905260a0810182905260c081019190915290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a082015260c0810182905260e081018290526101008101829052610120810182905261014081019190915290565b6001600160a01b038116811461112257600080fd5b63ffffffff8116811461112257600080fd5b80356001600160801b038116811461413f57600080fd5b60008083601f84011261439157600080fd5b5081356001600160401b038111156143a857600080fd5b6020830191508360208285010111156143c057600080fd5b9250929050565b60008060008060008060a087890312156143e057600080fd5b86356143eb81614341565b955060208701356143fb81614356565b9450604087013561440b81614341565b935061441960608801614368565b925060808701356001600160401b0381111561443457600080fd5b61444089828a0161437f565b979a9699509497509295939492505050565b60005b8381101561446d578181015183820152602001614455565b50506000910152565b6000815180845261448e816020860160208601614452565b601f01601f19169290920160200192915050565b602081526000612d0a6020830184614476565b6000806000606084860312156144ca57600080fd5b83356144d581614341565b925060208401356144e581614341565b915060408401356144f581614356565b809150509250925092565b60008060008060008060a0878903121561451957600080fd5b863561452481614341565b9550602087013561453481614341565b9450604087013561454481614356565b9350606087013561441981614341565b60006020828403121561456657600080fd5b813561457181614341565b9392505050565b6000806000806080858703121561458e57600080fd5b843561459981614341565b935060208501356145a981614341565b925060408501356145b981614356565b915060608501356145c981614341565b939692955090935050565b6000806000806000608086880312156145ec57600080fd5b85356145f781614341565b9450602086013561460781614341565b9350604086013561461781614356565b925060608601356001600160401b0381111561463257600080fd5b61463e8882890161437f565b969995985093965092949392505050565b60008060008060006080868803121561466757600080fd5b853561467281614341565b9450602086013561468281614356565b935061461760408701614368565b600080600080608085870312156146a657600080fd5b84356146b181614341565b935060208501356146c181614341565b925060408501356146d181614356565b9396929550929360600135925050565b6000806000606084860312156146f657600080fd5b833561470181614341565b9250602084013561471181614341565b929592945050506040919091013590565b6000806040838503121561473557600080fd5b823561474081614341565b9150602083013561475081614341565b809150509250929050565b600081518084526020808501945080840160005b838110156147945781516001600160801b03168752958201959082019060010161476f565b509495945050505050565b606080825284519082018190526000906020906080840190828801845b828110156147e15781516001600160a01b0316845292840192908401906001016147bc565b5050508381038285015285518082528683019183019060005b8181101561481c57835163ffffffff16835292840192918401916001016147fa565b50508481036040860152614830818761475b565b98975050505050505050565b60008060008060006080868803121561485457600080fd5b853561485f81614341565b9450602086013561486f81614356565b93506040860135925060608601356001600160401b0381111561463257600080fd5b600080604083850312156148a457600080fd5b82356148af81614341565b946020939093013593505050565b600080600080606085870312156148d357600080fd5b84356148de81614341565b935060208501356148ee81614356565b925060408501356001600160401b0381111561490957600080fd5b6149158782880161437f565b95989497509550505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115612d0d57612d0d614921565b81810381811115612d0d57612d0d614921565b600081518084526020808501945080840160005b8381101561479457815187529582019590820190600101614971565b828152604060208201526000613f3a604083018461495d565b6001600160801b038181168382160190808211156149c6576149c6614921565b5092915050565b6001600160801b038281168282160390808211156149c6576149c6614921565b60006001600160ff1b0381841382841380821686840486111615614a1357614a13614921565b600160ff1b6000871282811687830589121615614a3257614a32614921565b60008712925087820587128484161615614a4e57614a4e614921565b87850587128184161615614a6457614a64614921565b505050929093029392505050565b6000600160ff1b8201614a8757614a87614921565b5060000390565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03841681526001600160801b0383166020820152606060408201819052600090614ada90830184614476565b95945050505050565b6001600160a01b038516815263ffffffff841660208201526001600160801b0383166040820152608060608201819052600090614b2290830184614476565b9695505050505050565b6001600160a01b0383168152604060208201819052600090613f3a90830184614476565b6001600160a01b038416815263ffffffff83166020820152606060408201819052600090614ada90830184614476565b600060208284031215614b9257600080fd5b5051919050565b6000816000190483118215151615614bb357614bb3614921565b500290565b600082614bd557634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b0381118282101715614c6857614c68614c2f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715614c9657614c96614c2f565b604052919050565b60006001600160401b03821115614cb757614cb7614c2f565b5060051b60200190565b600082601f830112614cd257600080fd5b81516020614ce7614ce283614c9e565b614c6e565b82815260059290921b84018101918181019086841115614d0657600080fd5b8286015b84811015614d215780518352918301918301614d0a565b509695505050505050565b600060208284031215614d3e57600080fd5b81516001600160401b03811115614d5457600080fd5b613f3a84828501614cc1565b8082018281126000831280158216821582161715614d8057614d80614921565b505092915050565b600063ffffffff808316818103614da157614da1614921565b6001019392505050565b805161413f81614341565b600060208284031215614dc857600080fd5b815161457181614341565b8051801515811461413f57600080fd5b600060208284031215614df557600080fd5b612d0a82614dd3565b805160ff8116811461413f57600080fd5b80516001600160e01b03198116811461413f57600080fd5b600082601f830112614e3857600080fd5b81516001600160401b03811115614e5157614e51614c2f565b614e64601f8201601f1916602001614c6e565b818152846020838601011115614e7957600080fd5b613f3a826020830160208701614452565b600060208284031215614e9c57600080fd5b81516001600160401b0380821115614eb357600080fd5b908301906101608286031215614ec857600080fd5b614ed0614c45565b614ed983614dfe565b8152614ee760208401614dfe565b602082015260408301516040820152614f0260608401614dab565b6060820152614f1360808401614e0f565b608082015260a083015182811115614f2a57600080fd5b614f3687828601614e27565b60a08301525060c083015160c082015260e083015160e0820152610100915081830151828201526101209150614f6d828401614dab565b828201526101409150614f81828401614dab565b91810191909152949350505050565b600080600060608486031215614fa557600080fd5b614fae84614dd3565b9250614fbc60208501614dd3565b9150604084015190509250925092565b6001600160a01b038681168252851660208201526040810184905260a060608201819052600090614fff90830185614476565b82810360808401526148308185614476565b6001600160a01b038516815260806020820181905260009061503590830186614476565b8415156040840152828103606084015261504f8185614476565b979650505050505050565b60006020828403121561506c57600080fd5b81516001600160401b0381111561508257600080fd5b613f3a84828501614e27565b60018060a01b0384168152826020820152606060408201526000614ada606083018461495d565b6001600160a01b038781168252861660208201526040810185905260c0606082018190526000906150e890830186614476565b82810360808401526150fa8186614476565b905082810360a084015261510e8185614476565b9998505050505050505050565b60006001600160801b0380881683528087166020840152808616604084015280851660608401525060a0608083015261504f60a0830184614476565b6000806040838503121561516a57600080fd5b82516001600160401b038082111561518157600080fd5b818501915085601f83011261519557600080fd5b815160206151a5614ce283614c9e565b82815260059290921b840181019181810190898411156151c457600080fd5b948201945b838610156151eb5785516151dc81614356565b825294820194908201906151c9565b9188015191965090935050508082111561520457600080fd5b5061521185828601614cc1565b9150509250929050565b60006001820161522d5761522d614921565b5060010190565b60006020828403121561524657600080fd5b815161457181614356565b60a08152600061526460a0830188614476565b6001600160a01b0396871660208401526040830195909552506060810192909252909216608090920191909152919050565b6040815260006152a96040830185614476565b9050826020830152939250505056fea2646970667358221220d26f9ab4961a5a9a2150de4b06a2b116fe33f93f65935ac73be15b533aac09bf64736f6c63430008100033000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192
-----Decoded View---------------
Arg [0] : host (address): 0xcf8acb4ef033eff16e8080aed4c7d5b9285d2192
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.