Skip to content
Merged
2 changes: 1 addition & 1 deletion packages/automation-contracts/autowrap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Open contracts that allow upgrading underlying token to supertokens based on running stream",
"version": "0.3.0",
"devDependencies": {
"@superfluid-finance/ethereum-contracts": "^1.13.0",
"@superfluid-finance/ethereum-contracts": "^1.14.0",
"@superfluid-finance/metadata": "^1.6.2"
},
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/automation-contracts/scheduler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Open contracts that allow scheduling streams and vestings onchain",
"version": "1.3.0",
"devDependencies": {
"@superfluid-finance/ethereum-contracts": "^1.13.0",
"@superfluid-finance/ethereum-contracts": "^1.14.0",
"@superfluid-finance/metadata": "^1.6.2"
},
"license": "MIT",
Expand Down
3 changes: 2 additions & 1 deletion packages/ethereum-contracts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ All notable changes to the ethereum-contracts will be documented in this file.

This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [UNRELEASED]
## [v1.14.0]

### Added
- GDA _autoconnect_ feature: now any account can connect pool members using `tryConnectPoolFor()` as long as they have less than 4 connection slots occupied for that Super Token. This allows for smoother onboarding of new users, allowing Apps to make sure tokens distributed via GDA immediately show up in user's wallets. Accounts can opt out of this by using `setConnectPermission()`, this is mainly supposed to be used by contracts.
Expand All @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `GDAv1StorageWriter` contains functions for writing agreement data to the token contract. This can only be used by the GDA contract itself.
- bump solc to "0.8.30".
- Changed EVM target from `paris` to `shanghai` because now all networks with supported Superfluid deployment support it.
- Emit ERC20 `Transfer` events (with amount 0) on CFA and GDA actions potentially leading to account balance changes. This shall help indexers to keep track of SuperToken holders and account balances.

### Fixed
- `ISuperfluidPool`: `getClaimable` and `getClaimableNow` could previously return non-zero values for connected pools, which was inconsistent with what `claimAll` would actually do in this situation (claim nothing).
Expand Down
4 changes: 2 additions & 2 deletions packages/ethereum-contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ If you're building a smart contract that uses Superfluid protocol, or even your
### Installation

Prerequisites:
- [node.js v18+](https://nodejs.org/en/download). The project recommends 22, and is tested with node 18,20,22.
- [node.js v20+](https://nodejs.org/en/download). The project recommends 24, and is tested with node 20,22,24.
- [yarn](https://classic.yarnpkg.com/en/docs/install)
- [forge](https://book.getfoundry.sh/getting-started/installation)

Expand Down Expand Up @@ -305,7 +305,7 @@ If you want contribute to Superfluid protocol contracts instead of just interfac

### Setup Development Environment

Prerequisites: You need node.js v18+ and yarn installed.
Prerequisites: You need node.js v20+ and yarn installed.

First, check out this repository and cd into it.
```sh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ contract ConstantFlowAgreementV1 is
ctx, currentContext);
}

flowVars.token.emitZeroTransfer(flowVars.sender, flowVars.receiver);

_requireAvailableBalance(flowVars.token, flowVars.sender, currentContext);
}

Expand Down Expand Up @@ -592,6 +594,8 @@ contract ConstantFlowAgreementV1 is
newCtx, currentContext);
}
}

flowVars.token.emitZeroTransfer(flowVars.sender, flowVars.receiver);
}

/**************************************************************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,14 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
return true;
}

function tokenEmitZeroTransfer(ISuperfluidToken superToken, address from, address to) external {
if (superToken.isPool(this, msg.sender) == false) {
revert GDA_ONLY_SUPER_TOKEN_POOL();
}

superToken.emitZeroTransfer(from, to);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// TokenMonad interface
//////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,11 @@ contract SuperfluidPool is ISuperfluidPool, BeaconProxiable {
_membersData[memberAddr] = _pdPoolMemberToMemberData(pdPoolMember, claimedValue);
assert(GDA.appendIndexUpdateByPool(superToken, p, t));
}

if (oldUnits == 0 && newUnits != 0 || oldUnits != 0 && newUnits == 0) {
GDA.tokenEmitZeroTransfer(superToken, address(this), memberAddr);
}

emit MemberUnitsUpdated(superToken, memberAddr, oldUnits, newUnits);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,11 @@ interface ISuperfluidToken {
uint256 rewardAmount,
uint256 bailoutAmount
);

/**
* @dev Emit an ERC20.Transfer event with zero amount, helps indexers track token holders.
* @param from The address from which the transfer is happening
* @param to The address to which the transfer is happening
*/
function emitZeroTransfer(address from, address to) external;
}
19 changes: 16 additions & 3 deletions packages/ethereum-contracts/contracts/superfluid/SuperToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ contract SuperToken is
if (spender != holder) {
require(amount <= _allowances[holder][spender], "SuperToken: transfer amount exceeds allowance");
// TODO: this triggers an `Approval` event, which shouldn't happen for transfers.
_approve(holder, spender, _allowances[holder][spender] - amount);
_approve(holder, spender, _allowances[holder][spender] - amount, false);
}

return true;
Expand Down Expand Up @@ -504,7 +504,17 @@ contract SuperToken is
* - `account` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address account, address spender, uint256 amount)
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}

/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made
* during the `transferFrom` operation set the flag to false.
*/
function _approve(address account, address spender, uint256 amount, bool emitEvent)
internal
{
if (account == address(0)) {
Expand All @@ -515,7 +525,10 @@ contract SuperToken is
}

_allowances[account][spender] = amount;
emit Approval(account, spender, amount);

if (emitEvent) {
emit Approval(account, spender, amount);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,10 @@ abstract contract SuperfluidToken is ISuperfluidToken
);
}

function emitZeroTransfer(address from, address to) external onlyAgreement {
emit IERC20.Transfer(from, to, 0);
}

/**************************************************************************
* Modifiers
*************************************************************************/
Expand Down
2 changes: 1 addition & 1 deletion packages/ethereum-contracts/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@superfluid-finance/ethereum-contracts",
"description": " Ethereum contracts implementation for the Superfluid Protocol",
"version": "1.13.0",
"version": "1.14.0",
"dependencies": {
"@decentral.ee/web3-helpers": "0.5.3",
"@nomiclabs/hardhat-ethers": "2.2.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
// SPDX-License-Identifier: AGPLv3
pragma solidity ^0.8.23;

import { Test } from "forge-std/Test.sol";
import { Test, console } from "forge-std/Test.sol";
import { UUPSProxy } from "../../../contracts/upgradability/UUPSProxy.sol";
import { UUPSProxiable } from "../../../contracts/upgradability/UUPSProxiable.sol";
import { IERC20, ISuperToken, SuperToken }
import { IERC20, ISuperToken, ISuperfluidPool, PoolConfig }
from "../../../contracts/interfaces/superfluid/ISuperfluid.sol";
import { SuperToken }
from "../../../contracts/superfluid/SuperToken.sol";
import { PoolAdminNFT, IPoolAdminNFT } from "../../../contracts/agreements/gdav1/PoolAdminNFT.sol";
import { FoundrySuperfluidTester } from "../FoundrySuperfluidTester.t.sol";
import { TestToken } from "../../../contracts/utils/TestToken.sol";
import { TokenDeployerLibrary } from "../../../contracts/utils/SuperfluidFrameworkDeploymentSteps.t.sol";
import { SuperTokenV1Library } from "../../../contracts/apps/SuperTokenV1Library.sol";

contract SuperTokenIntegrationTest is FoundrySuperfluidTester {
constructor() FoundrySuperfluidTester(0) { }
using SuperTokenV1Library for ISuperToken;

constructor() FoundrySuperfluidTester(1) { }

function setUp() public override {
super.setUp();
Expand Down Expand Up @@ -254,4 +259,54 @@ contract SuperTokenIntegrationTest is FoundrySuperfluidTester {
assertEq(localSuperToken.nonces(permitSigner), 1, "Nonce should be incremented");
assertEq(localSuperToken.allowance(permitSigner, spender), amount, "Allowance should be set");
}

// Verify zero Transfer events being emitted by CFA and GDA actions
function testEmitZeroTransferEvent() public {
vm.startPrank(admin);

// case 1: create flow
vm.expectEmit(address(superToken));
emit IERC20.Transfer(admin, alice, 0);
superToken.createFlow(alice, 1);

// case 2: delete flow
vm.expectEmit(address(superToken));
emit IERC20.Transfer(admin, alice, 0);
superToken.deleteFlow(admin, alice);

// create a pool for the next tests
ISuperfluidPool pool = superToken.createPool(
admin,
PoolConfig({
transferabilityForUnitsOwner: true,
distributionFromAnyAddress: true
})
);

// case 3: assign pool units
vm.expectEmit(address(superToken));
emit IERC20.Transfer(address(pool), alice, 0);
pool.updateMemberUnits(alice, 1);

vm.stopPrank();

// case 4: test pool token transfer
vm.startPrank(alice);
// This emits 2 Transfer events, because the sender's units toggle to 0 and the receiver units from 0
vm.expectEmit(address(superToken));
emit IERC20.Transfer(address(pool), alice, 0);
vm.expectEmit(address(superToken));
emit IERC20.Transfer(address(pool), bob, 0);
IERC20(pool).transfer(bob, 1);

vm.stopPrank();

// case 5: remove pool units
vm.startPrank(admin);
vm.expectEmit(address(superToken));
emit IERC20.Transfer(address(pool), bob, 0);
pool.updateMemberUnits(bob, 0);

vm.stopPrank();
}
}
4 changes: 2 additions & 2 deletions packages/hot-fuzz/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
},
"bugs": "https://github.com/superfluid-finance/protocol-monorepo/issues",
"devDependencies": {
"@superfluid-finance/ethereum-contracts": "^1.13.0"
"@superfluid-finance/ethereum-contracts": "^1.14.0"
},
"homepage": "https://github.com/superfluid-finance/protocol-monorepo#readme",
"license": "AGPL-3.0",
"main": "index.js",
"peerDependencies": {
"@superfluid-finance/ethereum-contracts": "1.13.0"
"@superfluid-finance/ethereum-contracts": "1.14.0"
},
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/js-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"node-fetch": "2.7.0"
},
"devDependencies": {
"@superfluid-finance/ethereum-contracts": "^1.13.0",
"@superfluid-finance/ethereum-contracts": "^1.14.0",
"chai-as-promised": "^8.0.0",
"webpack": "^5.94.0",
"webpack-bundle-analyzer": "^4.10.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.9.0",
"bugs": "https://github.com/superfluid-finance/protocol-monorepo/issues",
"dependencies": {
"@superfluid-finance/ethereum-contracts": "1.13.0",
"@superfluid-finance/ethereum-contracts": "1.14.0",
"@superfluid-finance/metadata": "^1.6.2",
"graphql-request": "6.1.0",
"lodash": "4.17.21",
Expand Down
Loading