From 59763ec2c0463a8b625e9f451cbb2816542e697b Mon Sep 17 00:00:00 2001 From: didi Date: Thu, 3 Aug 2023 12:07:38 +0200 Subject: [PATCH 1/4] keep public & external SuperToken methods virtual to facilitate creation of customized logic --- .../contracts/superfluid/SuperToken.sol | 78 ++++++++++--------- .../contracts/superfluid/SuperfluidToken.sol | 30 +++---- 2 files changed, 55 insertions(+), 53 deletions(-) diff --git a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol index 4cd24a71bb..0e994385d0 100644 --- a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol +++ b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol @@ -126,6 +126,7 @@ contract SuperToken is string calldata s ) external + virtual override initializer // OpenZeppelin Initializable { @@ -142,11 +143,11 @@ contract SuperToken is emit Transfer(address(0), address(0), 0); } - function proxiableUUID() public pure override returns (bytes32) { + function proxiableUUID() public pure virtual override returns (bytes32) { return keccak256("org.superfluid-finance.contracts.SuperToken.implementation"); } - function updateCode(address newAddress) external override { + function updateCode(address newAddress) external virtual override { if (msg.sender != address(_host)) revert SUPER_TOKEN_ONLY_HOST(); UUPSProxiable._updateCodeAddress(newAddress); @@ -167,15 +168,15 @@ contract SuperToken is * ERC20 Token Info *************************************************************************/ - function name() external view override returns (string memory) { + function name() external view virtual override returns (string memory) { return _name; } - function symbol() external view override returns (string memory) { + function symbol() external view virtual override returns (string memory) { return _symbol; } - function decimals() external pure override returns (uint8) { + function decimals() external pure virtual override returns (uint8) { return _STANDARD_DECIMALS; } @@ -421,7 +422,7 @@ contract SuperToken is *************************************************************************/ function totalSupply() - public view override returns (uint256) + public view virtual override returns (uint256) { return _totalSupply; } @@ -431,6 +432,7 @@ contract SuperToken is ) public view + virtual override returns(uint256 balance) { @@ -440,19 +442,19 @@ contract SuperToken is } function transfer(address recipient, uint256 amount) - public override returns (bool) + public virtual override returns (bool) { return _transferFrom(msg.sender, msg.sender, recipient, amount); } function allowance(address account, address spender) - public view override returns (uint256) + public view virtual override returns (uint256) { return _allowances[account][spender]; } function approve(address spender, uint256 amount) - public override + public virtual override returns (bool) { _approve(msg.sender, spender, amount); @@ -460,19 +462,19 @@ contract SuperToken is } function transferFrom(address holder, address recipient, uint256 amount) - public override returns (bool) + public virtual override returns (bool) { return _transferFrom(msg.sender, holder, recipient, amount); } function increaseAllowance(address spender, uint256 addedValue) - public override returns (bool) { + public virtual override returns (bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender] + addedValue); return true; } function decreaseAllowance(address spender, uint256 subtractedValue) - public override returns (bool) { + public virtual override returns (bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "SuperToken: decreased allowance below zero")); return true; @@ -482,33 +484,33 @@ contract SuperToken is * ERC-777 functions *************************************************************************/ - function granularity() external pure override returns (uint256) { return 1; } + function granularity() external pure virtual override returns (uint256) { return 1; } - function send(address recipient, uint256 amount, bytes calldata data) external override { + function send(address recipient, uint256 amount, bytes calldata data) external virtual override { _send(msg.sender, msg.sender, recipient, amount, data, "", true); } - function burn(uint256 amount, bytes calldata data) external override { + function burn(uint256 amount, bytes calldata data) external virtual override { _downgrade(msg.sender, msg.sender, msg.sender, amount, data, ""); } - function isOperatorFor(address operator, address tokenHolder) external override view returns (bool) { + function isOperatorFor(address operator, address tokenHolder) external virtual override view returns (bool) { return _operators.isOperatorFor(operator, tokenHolder); } - function authorizeOperator(address operator) external override { + function authorizeOperator(address operator) external virtual override { address holder = msg.sender; _operators.authorizeOperator(holder, operator); emit AuthorizedOperator(operator, holder); } - function revokeOperator(address operator) external override { + function revokeOperator(address operator) external virtual override { address holder = msg.sender; _operators.revokeOperator(holder, operator); emit RevokedOperator(operator, holder); } - function defaultOperators() external override view returns (address[] memory) { + function defaultOperators() external virtual override view returns (address[] memory) { return ERC777Helper.defaultOperators(_operators); } @@ -518,7 +520,7 @@ contract SuperToken is uint256 amount, bytes calldata data, bytes calldata operatorData - ) external override { + ) external virtual override { address operator = msg.sender; if (!_operators.isOperatorFor(operator, sender)) revert SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); _send(operator, sender, recipient, amount, data, operatorData, true); @@ -529,7 +531,7 @@ contract SuperToken is uint256 amount, bytes calldata data, bytes calldata operatorData - ) external override { + ) external virtual override { address operator = msg.sender; if (!_operators.isOperatorFor(operator, account)) revert SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); _downgrade(operator, account, account, amount, data, operatorData); @@ -548,7 +550,7 @@ contract SuperToken is uint256 amount, bytes memory userData ) - external override + external virtual override onlySelf { _mint(msg.sender, account, amount, @@ -560,7 +562,7 @@ contract SuperToken is uint256 amount, bytes memory userData ) - external override + external virtual override onlySelf { _burn(msg.sender, account, amount, userData, new bytes(0)); @@ -571,7 +573,7 @@ contract SuperToken is address spender, uint256 amount ) - external override + external virtual override onlySelf { _approve(account, spender, amount); @@ -583,7 +585,7 @@ contract SuperToken is address recipient, uint256 amount ) - external override + external virtual override onlySelf { _transferFrom(spender, holder, recipient, amount); @@ -594,7 +596,7 @@ contract SuperToken is *************************************************************************/ function transferAll(address recipient) - external override + external virtual override { _transferFrom(msg.sender, msg.sender, recipient, balanceOf(msg.sender)); } @@ -604,27 +606,27 @@ contract SuperToken is *************************************************************************/ /// @dev ISuperfluidGovernance.getUnderlyingToken implementation - function getUnderlyingToken() external view override returns(address) { + function getUnderlyingToken() external view virtual override returns(address) { return address(_underlyingToken); } /// @dev ISuperToken.upgrade implementation - function upgrade(uint256 amount) external override { + function upgrade(uint256 amount) external virtual override { _upgrade(msg.sender, msg.sender, msg.sender, amount, "", ""); } /// @dev ISuperToken.upgradeTo implementation - function upgradeTo(address to, uint256 amount, bytes calldata data) external override { + function upgradeTo(address to, uint256 amount, bytes calldata data) external virtual override { _upgrade(msg.sender, msg.sender, to, amount, data, ""); } /// @dev ISuperToken.downgrade implementation - function downgrade(uint256 amount) external override { + function downgrade(uint256 amount) external virtual override { _downgrade(msg.sender, msg.sender, msg.sender, amount, "", ""); } /// @inheritdoc ISuperToken - function downgradeTo(address to, uint256 amount) external override { + function downgradeTo(address to, uint256 amount) external virtual override { _downgrade(msg.sender, msg.sender, to, amount, "", ""); } @@ -711,7 +713,7 @@ contract SuperToken is address spender, uint256 amount ) - external override + external virtual override onlyHost { _approve(account, spender, amount); @@ -722,7 +724,7 @@ contract SuperToken is address spender, uint256 addedValue ) - external override + external virtual override onlyHost { _approve(account, spender, _allowances[account][spender] + addedValue); @@ -733,7 +735,7 @@ contract SuperToken is address spender, uint256 subtractedValue ) - external override + external virtual override onlyHost { _approve(account, spender, _allowances[account][spender].sub(subtractedValue, @@ -746,7 +748,7 @@ contract SuperToken is address recipient, uint256 amount ) - external override + external virtual override onlyHost { _transferFrom(account, spender, recipient, amount); @@ -758,21 +760,21 @@ contract SuperToken is uint256 amount, bytes memory userData ) - external override + external virtual override onlyHost { _send(msg.sender, spender, recipient, amount, userData, "", true); } function operationUpgrade(address account, uint256 amount) - external override + external virtual override onlyHost { _upgrade(msg.sender, account, account, amount, "", ""); } function operationDowngrade(address account, uint256 amount) - external override + external virtual override onlyHost { _downgrade(msg.sender, account, account, amount, "", ""); diff --git a/packages/ethereum-contracts/contracts/superfluid/SuperfluidToken.sol b/packages/ethereum-contracts/contracts/superfluid/SuperfluidToken.sol index 1e4be19f0d..b18eb63c35 100644 --- a/packages/ethereum-contracts/contracts/superfluid/SuperfluidToken.sol +++ b/packages/ethereum-contracts/contracts/superfluid/SuperfluidToken.sol @@ -73,7 +73,7 @@ abstract contract SuperfluidToken is ISuperfluidToken address account, uint256 timestamp ) - public view override + public view virtual override returns ( int256 availableBalance, uint256 deposit, @@ -108,7 +108,7 @@ abstract contract SuperfluidToken is ISuperfluidToken function realtimeBalanceOfNow( address account ) - public view override + public view virtual override returns ( int256 availableBalance, uint256 deposit, @@ -127,7 +127,7 @@ abstract contract SuperfluidToken is ISuperfluidToken address account, uint256 timestamp ) - public view override + public view virtual override returns(bool isCritical) { (int256 availableBalance,,) = realtimeBalanceOf(account, timestamp); @@ -137,7 +137,7 @@ abstract contract SuperfluidToken is ISuperfluidToken function isAccountCriticalNow( address account ) - external view override + external view virtual override returns(bool isCritical) { return isAccountCritical(account, _host.getNow()); @@ -147,7 +147,7 @@ abstract contract SuperfluidToken is ISuperfluidToken address account, uint256 timestamp ) - public view override + public view virtual override returns(bool isSolvent) { (int256 availableBalance, uint256 deposit, uint256 owedDeposit) = @@ -161,7 +161,7 @@ abstract contract SuperfluidToken is ISuperfluidToken function isAccountSolventNow( address account ) - external view override + external view virtual override returns(bool isSolvent) { return isAccountSolvent(account, _host.getNow()); @@ -169,7 +169,7 @@ abstract contract SuperfluidToken is ISuperfluidToken /// @dev ISuperfluidToken.getAccountActiveAgreements implementation function getAccountActiveAgreements(address account) - public view override + public view virtual override returns(ISuperAgreement[] memory) { return _host.mapAgreementClasses(~_inactiveAgreementBitmap[account]); @@ -232,7 +232,7 @@ abstract contract SuperfluidToken is ISuperfluidToken bytes32 id, bytes32[] calldata data ) - external override + external virtual override { address agreementClass = msg.sender; bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); @@ -249,7 +249,7 @@ abstract contract SuperfluidToken is ISuperfluidToken bytes32 id, uint dataLength ) - external view override + external view virtual override returns(bytes32[] memory data) { bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); @@ -261,7 +261,7 @@ abstract contract SuperfluidToken is ISuperfluidToken bytes32 id, bytes32[] calldata data ) - external override + external virtual override { address agreementClass = msg.sender; bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); @@ -274,7 +274,7 @@ abstract contract SuperfluidToken is ISuperfluidToken bytes32 id, uint dataLength ) - external override + external virtual override { address agreementClass = msg.sender; bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); @@ -291,7 +291,7 @@ abstract contract SuperfluidToken is ISuperfluidToken uint256 slotId, bytes32[] calldata slotData ) - external override + external virtual override { bytes32 slot = keccak256(abi.encode("AgreementState", msg.sender, account, slotId)); FixedSizeData.storeData(slot, slotData); @@ -305,7 +305,7 @@ abstract contract SuperfluidToken is ISuperfluidToken uint256 slotId, uint dataLength ) - external override view + external view virtual override returns (bytes32[] memory slotData) { bytes32 slot = keccak256(abi.encode("AgreementState", agreementClass, account, slotId)); slotData = FixedSizeData.loadData(slot, dataLength); @@ -316,7 +316,7 @@ abstract contract SuperfluidToken is ISuperfluidToken address account, int256 delta ) - external override + external virtual override onlyAgreement { _sharedSettledBalances[account] = _sharedSettledBalances[account] + delta; @@ -331,7 +331,7 @@ abstract contract SuperfluidToken is ISuperfluidToken address targetAccount, // Account to be liquidated uint256 rewardAmount, // The amount the rewarded account will receive int256 targetAccountBalanceDelta // The delta amount the target account balance should change by - ) external override onlyAgreement { + ) external virtual override onlyAgreement { address rewardAccount = _getRewardAccount(); // we set the rewardAccount to the user who executed the liquidation if From 01fcbe63d40a2f4c89b3e1dce6a9bde330cf399d Mon Sep 17 00:00:00 2001 From: didi Date: Thu, 3 Aug 2023 12:42:16 +0200 Subject: [PATCH 2/4] also make internal methods for transfer/mint/burn virtual --- .../contracts/superfluid/SuperToken.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol index 0e994385d0..00e18c2ac9 100644 --- a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol +++ b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol @@ -193,7 +193,7 @@ contract SuperToken is * For more context, see https://github.com/superfluid-finance/protocol-monorepo/wiki/About-ERC-777 */ function _transferFrom(address spender, address holder, address recipient, uint amount) - internal returns (bool) + internal virtual returns (bool) { if (holder == address(0)) { revert SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); @@ -234,7 +234,7 @@ contract SuperToken is bytes memory operatorData, bool requireReceptionAck ) - private + internal virtual { if (from == address(0)) { revert SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); @@ -291,7 +291,7 @@ contract SuperToken is bytes memory userData, bytes memory operatorData ) - internal + internal virtual { if (account == address(0)) { revert SUPER_TOKEN_MINT_TO_ZERO_ADDRESS(); @@ -319,7 +319,7 @@ contract SuperToken is bytes memory userData, bytes memory operatorData ) - internal + internal virtual { if (from == address(0)) { revert SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS(); From c214233cf27e35b5e47625899a8a0973d05c4fcd Mon Sep 17 00:00:00 2001 From: didi Date: Thu, 3 Aug 2023 12:45:06 +0200 Subject: [PATCH 3/4] virtual _upgrade and _downgrade --- .../ethereum-contracts/contracts/superfluid/SuperToken.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol index 00e18c2ac9..3af790c83c 100644 --- a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol +++ b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol @@ -637,7 +637,7 @@ contract SuperToken is uint256 amount, bytes memory userData, bytes memory operatorData - ) private { + ) internal virtual { if (address(_underlyingToken) == address(0)) revert SUPER_TOKEN_NO_UNDERLYING_TOKEN(); (uint256 underlyingAmount, uint256 adjustedAmount) = _toUnderlyingAmount(amount); @@ -661,7 +661,8 @@ contract SuperToken is address to, // the account receiving the underlying tokens uint256 amount, bytes memory data, - bytes memory operatorData) private { + bytes memory operatorData + ) internal virtual { if (address(_underlyingToken) == address(0)) revert SUPER_TOKEN_NO_UNDERLYING_TOKEN(); (uint256 underlyingAmount, uint256 adjustedAmount) = _toUnderlyingAmount(amount); From 2f03d8300967bb3c68ab1c8c1369829b1d88654f Mon Sep 17 00:00:00 2001 From: didi Date: Mon, 7 Aug 2023 11:43:51 +0200 Subject: [PATCH 4/4] undo: make some internal functions virtual too --- .../contracts/superfluid/SuperToken.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol index 3af790c83c..eb677c39eb 100644 --- a/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol +++ b/packages/ethereum-contracts/contracts/superfluid/SuperToken.sol @@ -193,7 +193,7 @@ contract SuperToken is * For more context, see https://github.com/superfluid-finance/protocol-monorepo/wiki/About-ERC-777 */ function _transferFrom(address spender, address holder, address recipient, uint amount) - internal virtual returns (bool) + internal returns (bool) { if (holder == address(0)) { revert SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); @@ -234,7 +234,7 @@ contract SuperToken is bytes memory operatorData, bool requireReceptionAck ) - internal virtual + internal { if (from == address(0)) { revert SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); @@ -291,7 +291,7 @@ contract SuperToken is bytes memory userData, bytes memory operatorData ) - internal virtual + internal { if (account == address(0)) { revert SUPER_TOKEN_MINT_TO_ZERO_ADDRESS(); @@ -319,7 +319,7 @@ contract SuperToken is bytes memory userData, bytes memory operatorData ) - internal virtual + internal { if (from == address(0)) { revert SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS(); @@ -637,7 +637,7 @@ contract SuperToken is uint256 amount, bytes memory userData, bytes memory operatorData - ) internal virtual { + ) internal { if (address(_underlyingToken) == address(0)) revert SUPER_TOKEN_NO_UNDERLYING_TOKEN(); (uint256 underlyingAmount, uint256 adjustedAmount) = _toUnderlyingAmount(amount); @@ -662,7 +662,7 @@ contract SuperToken is uint256 amount, bytes memory data, bytes memory operatorData - ) internal virtual { + ) internal { if (address(_underlyingToken) == address(0)) revert SUPER_TOKEN_NO_UNDERLYING_TOKEN(); (uint256 underlyingAmount, uint256 adjustedAmount) = _toUnderlyingAmount(amount);