Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
697b97d
added increaseMemberUnits and decreaseMemberUnits to ISuperfluidPool
d10r Jun 13, 2025
912f970
added burn method to PoolMemberNFT
d10r Jun 16, 2025
85a30d4
added burn method to PoolMemberNFT
d10r Jun 16, 2025
eb1b6bd
duplicate _isPool
d10r Jun 16, 2025
2722583
deprecate PoolMemberNFT
d10r Jun 16, 2025
9820c92
bump version to 1.13.0
d10r Jun 16, 2025
a0aed70
change PoolMemberNFT token name
d10r Jun 16, 2025
2bf628a
adjust tests
d10r Jun 16, 2025
45fbbd8
updated changelog
d10r Jun 16, 2025
5634adc
added test
d10r Jun 16, 2025
9c6cc97
fix flaky test
d10r Jun 17, 2025
1e56be3
Merge branch 'dev' into 2025-06-incdec_poolunits
d10r Jun 17, 2025
a4cee27
more sensible gas price defaults for testnets (too)
d10r Jun 17, 2025
35e54ee
convert _isPool to free function so it can be shared
d10r Jun 18, 2025
b3dcea2
removed duplicate line
d10r Jun 24, 2025
7a23d38
mocks shall not use the deprecated method anymore
d10r Jun 24, 2025
9d39c49
add dedicated allowlist for superapp registration
d10r Jun 24, 2025
959e9d3
test revoke too
d10r Jun 24, 2025
eac3fe0
Merge branch 'dev' into superapp-allowlist
d10r Jun 30, 2025
131d4a3
Merge branch 'dev' into superapp-allowlist
d10r Jun 30, 2025
a2f295c
use OZ AccessControl instead of a custom implementation
d10r Jul 1, 2025
ce53cea
updated CHANGELOG
d10r Jul 1, 2025
fbf3ad4
rename to SimpleACL
d10r Jul 1, 2025
09c1de0
more adjustments
d10r Jul 1, 2025
39fb8a9
fix test
d10r Jul 1, 2025
64a1879
text fix
d10r Jul 1, 2025
ede6643
one more fix
d10r Jul 1, 2025
e14c562
change return type of getSimpleACL
d10r Jul 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/ethereum-contracts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `SuperToken` now implements [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612) (permit extension for EIP-20 signed approvals).
- `SuperfluidPool` now has additional methods `increaseMemberUnits` and `decreaseMemberUnits` which allow the pool admin to change member units parameterized with delta amounts.

### Changed
- Curation of the SuperApp registration allowlist can now be delegated by governance to a newly added `ACL` contract.

### Breaking
- `SuperfluidPool` does no longer mint and burn EIP-721 tokens (NFTs) on member unit updates. The gas overhead of this operation caused friction for integrations with other protocols (e.g. Uniswap V4).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,12 @@ interface ISuperfluid {
// solhint-disable func-name-mixedcase
function getERC2771Forwarder() external view returns(address);

/**
* @dev returns the address of the ACL contract used for granular permissioning.
* @return address of the ACL contract
*/
function getACL() external view returns(address);

/**************************************************************************
* Function modifiers for access control and parameter validations
*
Expand Down
10 changes: 5 additions & 5 deletions packages/ethereum-contracts/contracts/mocks/CFAAppMocks.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ contract ExclusiveInflowTestApp is SuperAppBase {
// | SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP
;

_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
}

function afterAgreementCreated(
Expand Down Expand Up @@ -121,7 +121,7 @@ contract NonClosableOutflowTestApp is SuperAppBase {
// | SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP
;

_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
}

function setupOutflow(
Expand Down Expand Up @@ -210,7 +210,7 @@ contract SelfDeletingFlowTestApp is SuperAppBase {
| SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP
;

_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
}

function afterAgreementCreated(
Expand Down Expand Up @@ -267,7 +267,7 @@ contract ClosingOnUpdateFlowTestApp is SuperAppBase {
| SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP
;

_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
}

function afterAgreementUpdated(
Expand Down Expand Up @@ -326,7 +326,7 @@ contract FlowExchangeTestApp is SuperAppBase {
| SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP
;

_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
}

function afterAgreementCreated(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract IDASuperAppTester is ISuperApp {
uint32 indexId)
{
_host = host;
_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
_ida = ida;
_token = token;
_indexId = indexId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ contract MultiFlowTesterApp is SuperAppBase {
SuperAppDefinitions.BEFORE_AGREEMENT_CREATED_NOOP |
SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP;

_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
}

function _parseUserData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ contract StreamRedirector is SuperAppBase {
token = _token;
receiver = _receiver;

host.registerAppWithKey(configWord, "");
host.registerApp(configWord);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ contract SuperAppMock is ISuperApp {

constructor(ISuperfluid host, uint256 configWord, bool doubleRegistration) {
_host = host;
_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
if (doubleRegistration) {
_host.registerAppWithKey(configWord, "");
_host.registerApp(configWord);
}
_aux = new SuperAppMockAux();
}
Expand Down Expand Up @@ -472,7 +472,7 @@ contract SuperAppMockReturningEmptyCtx {

constructor(ISuperfluid host) {
_host = host;
_host.registerAppWithKey(SuperAppDefinitions.APP_LEVEL_FINAL, "");
_host.registerApp(SuperAppDefinitions.APP_LEVEL_FINAL);
}

function beforeAgreementCreated(
Expand Down Expand Up @@ -533,7 +533,7 @@ contract SuperAppMockReturningInvalidCtx {

constructor(ISuperfluid host) {
_host = host;
_host.registerAppWithKey(SuperAppDefinitions.APP_LEVEL_FINAL, "");
_host.registerApp(SuperAppDefinitions.APP_LEVEL_FINAL);
}

function afterAgreementCreated(
Expand Down Expand Up @@ -574,7 +574,7 @@ contract SuperAppMock2ndLevel {

constructor(ISuperfluid host, SuperAppMock app, AgreementMock agreement) {
_host = host;
_host.registerAppWithKey(SuperAppDefinitions.APP_LEVEL_SECOND, "");
_host.registerApp(SuperAppDefinitions.APP_LEVEL_SECOND);
_app = app;
_agreement = agreement;
}
Expand Down Expand Up @@ -630,6 +630,6 @@ contract SuperAppMockNotSelfRegistering { }
// Factory which allows anybody to deploy arbitrary contracts as app (do NOT allow this in a real factory!)
contract SuperAppFactoryMock {
function registerAppWithHost(ISuperfluid host, ISuperApp app, uint256 configWord) external {
host.registerAppByFactory(app, configWord);
host.registerApp(app, configWord);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ contract SuperTokenLibraryCFASuperAppMock is SuperAppBase {
SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP |
SuperAppDefinitions.AFTER_AGREEMENT_TERMINATED_NOOP;

host.registerAppWithKey(configWord, "");
host.registerApp(configWord);
}

function createFlow(ISuperToken token) external {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { CallUtils } from "../libs/CallUtils.sol";
contract SuperfluidUpgradabilityTester is Superfluid {

// 3_000_000 is the min callback gas limit used in a prod deployment
constructor() Superfluid(false, false, 3_000_000, address(0), address(0))
constructor() Superfluid(false, false, 3_000_000, address(0), address(0), address(0))
// solhint-disable-next-line no-empty-blocks
{
}
Expand Down Expand Up @@ -135,10 +135,12 @@ contract SuperfluidMock is Superfluid {
bool appWhiteListingEnabled,
uint64 callbackGasLimit,
address simpleForwarderAddress,
address erc2771ForwarderAddress
address erc2771ForwarderAddress,
address allowListAddress
)
Superfluid(
nonUpgradable, appWhiteListingEnabled, callbackGasLimit, simpleForwarderAddress, erc2771ForwarderAddress
nonUpgradable, appWhiteListingEnabled, callbackGasLimit, simpleForwarderAddress, erc2771ForwarderAddress,
allowListAddress
)
// solhint-disable-next-line no-empty-blocks
{
Expand Down
24 changes: 22 additions & 2 deletions packages/ethereum-contracts/contracts/superfluid/Superfluid.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { CallbackUtils } from "../libs/CallbackUtils.sol";
import { BaseRelayRecipient } from "../libs/BaseRelayRecipient.sol";
import { SimpleForwarder } from "../utils/SimpleForwarder.sol";
import { ERC2771Forwarder } from "../utils/ERC2771Forwarder.sol";
import { ACL } from "../utils/ACL.sol";

/**
* @dev The Superfluid host implementation.
Expand Down Expand Up @@ -59,6 +60,9 @@ contract Superfluid is
SimpleForwarder immutable public SIMPLE_FORWARDER;
ERC2771Forwarder immutable internal _ERC2771_FORWARDER;

// ACL (for superapp registration)
ACL immutable internal _ACL;

/**
* @dev Maximum number of level of apps can be composed together
*
Expand All @@ -71,6 +75,8 @@ contract Superfluid is

uint32 constant public MAX_NUM_AGREEMENTS = 256;

bytes32 constant public ACL_SUPERAPP_REGISTRATION_ROLE = keccak256("ACL_SUPERAPP_REGISTRATION_ROLE");

/* WARNING: NEVER RE-ORDER VARIABLES! Always double-check that new
variables are added APPEND-ONLY. Re-ordering variables can
permanently BREAK the deployed proxy contract. */
Expand Down Expand Up @@ -105,13 +111,15 @@ contract Superfluid is
bool appWhiteListingEnabled,
uint64 callbackGasLimit,
address simpleForwarderAddress,
address erc2771ForwarderAddress
address erc2771ForwarderAddress,
address aclAddress
) {
NON_UPGRADABLE_DEPLOYMENT = nonUpgradable;
APP_WHITE_LISTING_ENABLED = appWhiteListingEnabled;
CALLBACK_GAS_LIMIT = callbackGasLimit;
SIMPLE_FORWARDER = SimpleForwarder(simpleForwarderAddress);
_ERC2771_FORWARDER = ERC2771Forwarder(erc2771ForwarderAddress);
_ACL = ACL(aclAddress);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -375,8 +383,16 @@ contract Superfluid is
_registerApp(ISuperApp(msg.sender), configWord);
}

// internally we keep using the gov config method with key
// Checks if the deployer account has permission to register SuperApps, reverts if not.
// New method: lookup in the ACL contract.
// Legacy/fallback method: lookup in the governance contract.
function _enforceAppRegistrationPermissioning(string memory registrationKey, address deployer) internal view {
// new method: check if the deployer is granted permission in the ACL
if (_ACL.hasRole(ACL_SUPERAPP_REGISTRATION_ROLE, deployer)) {
return;
}

// legacy/fallback method: check if permission is given by gov
bytes32 configKey = SuperfluidGovernanceConfigs.getAppRegistrationConfigKey(
// solhint-disable-next-line avoid-tx-origin
deployer,
Expand Down Expand Up @@ -958,6 +974,10 @@ contract Superfluid is
return address(_ERC2771_FORWARDER);
}

function getACL() external view override returns(address) {
return address(_ACL);
}

/**************************************************************************
* Internal
**************************************************************************/
Expand Down
16 changes: 16 additions & 0 deletions packages/ethereum-contracts/contracts/utils/ACL.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";

contract ACL is AccessControl {
constructor() {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}

/// Allows the default admin to set the admin role for a given role.
/// This gives the flexibility to set up sophisticated permissioning schemes in the future.
function setRoleAdmin(bytes32 role, bytes32 adminRole) external onlyRole(DEFAULT_ADMIN_ROLE) {
_setRoleAdmin(role, adminRole);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { TOGA } from "./TOGA.sol";
import { IResolver } from "../interfaces/utils/IResolver.sol";
import { SimpleForwarder } from "../utils/SimpleForwarder.sol";
import { ERC2771Forwarder } from "../utils/ERC2771Forwarder.sol";
import { ACL } from "../utils/ACL.sol";
import { MacroForwarder } from "../utils/MacroForwarder.sol";

/// @title Superfluid Framework Deployment Steps
Expand Down Expand Up @@ -143,10 +144,11 @@ contract SuperfluidFrameworkDeploymentSteps {
} else if (step == 1) { // CORE CONTRACT: Superfluid (Host)
SimpleForwarder simpleForwarder = new SimpleForwarder();
ERC2771Forwarder erc2771Forwarder = new ERC2771Forwarder();
ACL acl = new ACL();
// Deploy Host and initialize the test governance.
// 3_000_000 is the min callback gas limit used in a prod deployment
host = SuperfluidHostDeployerLibrary.deploy(
true, false, 3_000_000, address(simpleForwarder), address(erc2771Forwarder)
true, false, 3_000_000, address(simpleForwarder), address(erc2771Forwarder), address(acl)
);
simpleForwarder.transferOwnership(address(host));
erc2771Forwarder.transferOwnership(address(host));
Expand Down Expand Up @@ -319,12 +321,14 @@ library SuperfluidHostDeployerLibrary {
bool _appWhiteListingEnabled,
uint64 callbackGasLimit,
address simpleForwarderAddress,
address erc2771ForwarderAddress
address erc2771ForwarderAddress,
address allowListAddress
)
external returns (Superfluid)
{
return new Superfluid(
_nonUpgradable, _appWhiteListingEnabled, callbackGasLimit, simpleForwarderAddress, erc2771ForwarderAddress
_nonUpgradable, _appWhiteListingEnabled, callbackGasLimit, simpleForwarderAddress, erc2771ForwarderAddress,
allowListAddress
);
}
}
Expand Down
Loading
Loading