Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ETHEREUM-CONTRACTS] SuperApp registerApp deprecation #1706

Merged
merged 19 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,13 @@ interface ISuperfluid {
// uses SuperAppDefinitions' App Jail Reasons as _code
error APP_RULE(uint256 _code); // 0xa85ba64f

error HOST_INVALID_OR_EXPIRED_SUPER_APP_REGISTRATION_KEY(); // 0x19ab84d1
error HOST_NOT_A_SUPER_APP(); // 0x163cbe43
error HOST_NO_APP_REGISTRATION_PERMISSIONS(); // 0x5b93ebf0
error HOST_NO_APP_REGISTRATION_PERMISSION(); // 0x5b93ebf0
hellwolf marked this conversation as resolved.
Show resolved Hide resolved
error HOST_RECEIVER_IS_NOT_SUPER_APP(); // 0x96aa315e
error HOST_SENDER_IS_NOT_SUPER_APP(); // 0xbacfdc40
error HOST_SOURCE_APP_NEEDS_HIGHER_APP_LEVEL(); // 0x44725270
error HOST_SUPER_APP_IS_JAILED(); // 0x02384b64
error HOST_SUPER_APP_ALREADY_REGISTERED(); // 0x01b0a935
error HOST_UNAUTHORIZED_SUPER_APP_FACTORY(); // 0x289533c5

/**************************************************************************
* Time
Expand Down Expand Up @@ -245,35 +243,39 @@ interface ISuperfluid {
*************************************************************************/

/**
* @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.
* @dev Message sender (must be a contract) registers itself as a super app.
* @param configWord The super app manifest configuration, flags are defined in
* `SuperAppDefinitions`
* @notice On some mainnet deployments, pre-authorization by governance may be needed for this to succeed.
* See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide
*/
function registerApp(uint256 configWord) external;

/**
* @dev Registers an app (must be a contract) as a super app.
* @param app The super app address
* @param configWord The super app manifest configuration, flags are defined in
* `SuperAppDefinitions`
* @notice On some mainnet deployments, pre-authorization by governance may be needed for this to succeed.
* See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide
*/
function registerApp(ISuperApp app, 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.
* @dev DO NOT USE for new deployments
* @custom:deprecated you should use `registerApp(uint256 configWord) instead.
*/
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
* @dev DO NOT USE for new deployments
* @custom:deprecated you should use `registerApp(ISuperApp app, uint256 configWord) instead.
*/
function registerAppByFactory(ISuperApp app, uint256 configWord) external;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ contract SuperAppMockWithRegistrationKey {
}

// An Super App that uses registerAppWithKey
contract SuperAppMockUsingDeprecatedRegisterApp {
contract SuperAppMockUsingRegisterApp {
constructor(ISuperfluid host, uint256 configWord) {
// @note this is deprecated keeping this here for testing/coverage
host.registerApp(configWord);
Expand Down
112 changes: 52 additions & 60 deletions packages/ethereum-contracts/contracts/superfluid/Superfluid.sol
Original file line number Diff line number Diff line change
Expand Up @@ -312,89 +312,81 @@ contract Superfluid is
// App Registry
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/// @custom:deprecated
function registerApp(
uint256 configWord
)
external override
{
// check if whitelisting required
/// @inheritdoc ISuperfluid
function registerApp(uint256 configWord) external override {
if (APP_WHITE_LISTING_ENABLED) {
revert HOST_NO_APP_REGISTRATION_PERMISSIONS();
// for historical reasons, we internal use "k1" as default registration key
// solhint-disable-next-line avoid-tx-origin
_enforceAppRegistrationPermissioning("k1", tx.origin);
}
_registerApp(configWord, ISuperApp(msg.sender), true);
_registerApp(ISuperApp(msg.sender), configWord);
}

function registerAppWithKey(uint256 configWord, string calldata registrationKey)
external override
{
/// @inheritdoc ISuperfluid
function registerApp(ISuperApp app, uint256 configWord) external override {
// Cannot register an EOA as SuperApp
if ((address(app)).code.length == 0) revert HOST_MUST_BE_CONTRACT();
if (APP_WHITE_LISTING_ENABLED) {
bytes32 configKey = SuperfluidGovernanceConfigs.getAppRegistrationConfigKey(
// solhint-disable-next-line avoid-tx-origin
tx.origin,
registrationKey
);
// check if the key is valid and not expired
if (
_gov.getConfigAsUint256(
this,
ISuperfluidToken(address(0)),
configKey
// solhint-disable-next-line not-rely-on-time
) < block.timestamp) revert HOST_INVALID_OR_EXPIRED_SUPER_APP_REGISTRATION_KEY();
_enforceAppRegistrationPermissioning("k1", msg.sender);
}
_registerApp(configWord, ISuperApp(msg.sender), true);
_registerApp(app, configWord);
}

function registerAppByFactory(
ISuperApp app,
uint256 configWord
)
/// @custom:deprecated
function registerAppWithKey(uint256 configWord, string calldata registrationKey)
external override
{
// msg sender must be a contract
{
uint256 cs;
// solhint-disable-next-line no-inline-assembly
assembly { cs := extcodesize(caller()) }
if (cs == 0) revert HOST_MUST_BE_CONTRACT();
if (APP_WHITE_LISTING_ENABLED) {
// solhint-disable-next-line avoid-tx-origin
_enforceAppRegistrationPermissioning(registrationKey, tx.origin);
}
_registerApp(ISuperApp(msg.sender), configWord);
}

if (APP_WHITE_LISTING_ENABLED) {
// check if msg sender is authorized to register
bytes32 configKey = SuperfluidGovernanceConfigs.getAppFactoryConfigKey(msg.sender);
bool isAuthorizedAppFactory = _gov.getConfigAsUint256(
// internally we keep using the gov config method with key
function _enforceAppRegistrationPermissioning(string memory registrationKey, address deployer) internal view {
bytes32 configKey = SuperfluidGovernanceConfigs.getAppRegistrationConfigKey(
// solhint-disable-next-line avoid-tx-origin
deployer,
registrationKey
);
// check if the key is valid and not expired
if (
_gov.getConfigAsUint256(
this,
ISuperfluidToken(address(0)),
configKey) == 1;

if (!isAuthorizedAppFactory) revert HOST_UNAUTHORIZED_SUPER_APP_FACTORY();
configKey
// solhint-disable-next-line not-rely-on-time
) < block.timestamp)
{
revert HOST_NO_APP_REGISTRATION_PERMISSION();
}
_registerApp(configWord, app, false);
}

function _registerApp(uint256 configWord, ISuperApp app, bool checkIfInAppConstructor) private
{
// solhint-disable-next-line avoid-tx-origin
if (msg.sender == tx.origin) {
revert APP_RULE(SuperAppDefinitions.APP_RULE_NO_REGISTRATION_FOR_EOA);
/// @custom:deprecated
function registerAppByFactory(ISuperApp app, uint256 configWord) external override {
// Cannot register an EOA as SuperApp
if ((address(app)).code.length == 0) revert HOST_MUST_BE_CONTRACT();
if (APP_WHITE_LISTING_ENABLED) {
// enforce permissiniong with legacy gov config key for app factory
bytes32 configKey = SuperfluidGovernanceConfigs.getAppFactoryConfigKey(msg.sender);
bool isAuthorizedAppFactory = _gov.getConfigAsUint256(this, ISuperfluidToken(address(0)), configKey) == 1;
if (!isAuthorizedAppFactory) revert HOST_NO_APP_REGISTRATION_PERMISSION();
// We do not enforce any assumptions about what a "factory" is. It is whatever gov decided to.
}
_registerApp(app, configWord);
}

if (checkIfInAppConstructor) {
uint256 cs;
// solhint-disable-next-line no-inline-assembly
assembly { cs := extcodesize(app) }
if (cs != 0) {
revert APP_RULE(SuperAppDefinitions.APP_RULE_REGISTRATION_ONLY_IN_CONSTRUCTOR);
}
}
function _registerApp(ISuperApp app, uint256 configWord) private {
// validate configWord
if (
!SuperAppDefinitions.isConfigWordClean(configWord) ||
SuperAppDefinitions.getAppCallbackLevel(configWord) == 0 ||
(configWord & SuperAppDefinitions.APP_JAIL_BIT) != 0
) {
revert HOST_INVALID_CONFIG_WORD();
}
) {
revert HOST_INVALID_CONFIG_WORD();
}

if (_appManifests[ISuperApp(app)].configWord != 0) revert HOST_SUPER_APP_ALREADY_REGISTERED();
_appManifests[ISuperApp(app)] = AppManifest(configWord);
emit AppRegistered(app);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,46 @@ const {
} = require("./libs/common");

/**
* @dev Create a new super app registration key.
* @dev Authorizes an account to get Super Apps registered.
* For more details, see https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide
* @param {Array} argv Overriding command line arguments
* @param {boolean} options.isTruffle Whether the script is used within native truffle framework
* @param {Web3} options.web3 Injected web3 instance
* @param {Address} options.from Address to deploy contracts from
* @param {string} options.protocolReleaseVersion Specify the protocol release version to be used
*
* Note: the key itself doesn't have much meaning, it could be "stolen" from a broadcast tx anyway.
* But since it's bound to a deployer address, that doesn't really matter.
*
* Usage:
* npx truffle exec ops-scripts/gov-create-new-app-registration-key.js : {DEPLOYER} {REGISTRATION_KEY} [EXPIRATION_TS]
* EXPIRATION_TS is a Unix timestamp in seconds for when the key should expire.
* If not set, we default to 90 days in the future.
* npx truffle exec ops-scripts/gov-authorize-app-deployer.js : {DEPLOYER} [EXPIRATION_TS]
* EXPIRATION_TS is a Unix timestamp in seconds for when the authorization should expire.
* If not set, we default to (for practical purposed) no expiration.
* Hint: you may use https://www.unixtimestamp.com/ to calculate a timestamp
*/
module.exports = eval(`(${S.toString()})({
doNotPrintColonArgs: true
})`)(async function (args, options = {}) {
console.log("======== Creating new app registration key ========");
console.log("======== Authorizing Super App Deployer ========");
let {protocolReleaseVersion} = options;

if (args.length > 3 || args.length < 2) {
throw new Error("Wrong number of arguments");
}

let expirationTs = Math.floor(Date.now() / 1000) + 3600 * 24 * 90; // 90 days from now
// default: 2^64 - 1 (far in the future - for practical purposes, never expiring)
let expirationTs = (BigInt(2) ** BigInt(64) - BigInt(1)).toString();
if (args.length === 3) {
const expTsStr = args.pop();
const parsedExpTs = parseInt(expTsStr);
if (parsedExpTs.toString() !== expTsStr) {
throw new Error("EXPIRATON_TS not an integer");
}
expirationTs = parsedExpTs;
console.log("Expiration timestamp", expirationTs);
console.log("Expiration date", new Date(expirationTs * 1000)); // print human readable
}
const registrationKey = args.pop();
// for historical reasons, we have "registration keys" and now hardcode those to "k1"
const registrationKey = "k1";
const deployer = args.pop();
console.log("Deployer", deployer);
console.log("Registration key", registrationKey);
console.log("Expiration timestamp", expirationTs);

console.log("protocol release version:", protocolReleaseVersion);

Expand All @@ -63,8 +63,6 @@ module.exports = eval(`(${S.toString()})({
});
await sf.initialize();

console.log("Expiration date", new Date(expirationTs * 1000)); // print human readable

await sendGovernanceAction(sf, (gov) =>
gov.setAppRegistrationKey(
sf.host.address,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

set -x

CONTRACTS_DIR=build/truffle/contracts
CONTRACTS_DIR=build/truffle

TRUFFLE_NETWORK=$1
ADDRESSES_VARS=$2
Expand Down
Loading