diff --git a/.github/workflows/ci.canary.yml b/.github/workflows/ci.canary.yml index 4359372432..064fc0466a 100644 --- a/.github/workflows/ci.canary.yml +++ b/.github/workflows/ci.canary.yml @@ -272,7 +272,7 @@ jobs: cloudfront_distribution_id: E3JEO5R14CT8IH upgrade-contracts: - name: Upgrade ethereum-contracts on canary testnet (protocol release version "test") + name: Upgrade ethereum-contracts on canary testnet (protocol release version "canary") needs: [all-packages-tested] @@ -306,6 +306,6 @@ jobs: npx truffle exec --network ${{ matrix.network }} ops-scripts/info-print-contract-addresses.js : addresses.vars tasks/etherscan-verify-framework.sh ${{ matrix.network }} addresses.vars env: - RELEASE_VERSION: master + RELEASE_VERSION: canary AVALANCHE_FUJI_MNEMONIC: ${{ secrets.BUILD_AGENT_MNEMONIC }} AVALANCHE_FUJI_PROVIDER_URL: ${{ secrets.AVALANCHE_FUJI_PROVIDER_URL }} diff --git a/.github/workflows/handler.deploy-to-testnets.yml b/.github/workflows/handler.deploy-to-testnets.yml index bb20e32c38..43dd5c5b76 100644 --- a/.github/workflows/handler.deploy-to-testnets.yml +++ b/.github/workflows/handler.deploy-to-testnets.yml @@ -26,6 +26,10 @@ jobs: DEFAULT_MNEMONIC: ${{ secrets.BUILD_AGENT_MNEMONIC }} PROVIDER_URL_TEMPLATE: ${{ secrets.PROVIDER_URL_TEMPLATE }} + defaults: + run: + shell: nix develop -c bash -xe {0} + strategy: fail-fast: false matrix: @@ -39,12 +43,10 @@ jobs: if: ${{ github.event.inputs.only_network != '' && github.event.inputs.only_network != matrix.network }} run: echo "DO_SKIP=1" >> "$GITHUB_ENV" - - name: Use Node.js 18.x + - uses: cachix/install-nix-action@v19 if: env.DO_SKIP != 1 - uses: actions/setup-node@v3 with: - node-version: 18.x - cache: "yarn" + github_access_token: ${{ secrets.GITHUB_TOKEN }} - name: Build if: env.DO_SKIP != 1 diff --git a/.github/workflows/handler.run-ethereum-contracts-script.yml b/.github/workflows/handler.run-ethereum-contracts-script.yml index 16564474c2..b6571f914a 100644 --- a/.github/workflows/handler.run-ethereum-contracts-script.yml +++ b/.github/workflows/handler.run-ethereum-contracts-script.yml @@ -28,6 +28,10 @@ jobs: run-ethereum-contracts-script: runs-on: ubuntu-latest + defaults: + run: + shell: nix develop -c bash -xe {0} + env: RELEASE_VERSION: ${{ github.event.inputs.release_version }} RESOLVER_ADMIN_TYPE: ${{ github.event.inputs.admin_type }} @@ -35,12 +39,10 @@ jobs: steps: - uses: actions/checkout@v3 - - - name: Use Node.js 18.x - uses: actions/setup-node@v3 + + - uses: cachix/install-nix-action@v19 with: - node-version: 18.x - cache: "yarn" + github_access_token: ${{ secrets.GITHUB_TOKEN }} - name: Build run: | diff --git a/README.md b/README.md index 8cff7b072d..0b81b93adb 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@

Welcome to superfluid protocol-monorepo 👋

- + npm - + GitHub package.json version (subfolder of monorepo) - + npm - + npm - + npm - + GitHub package.json version (subfolder of monorepo)
diff --git a/packages/automation-contracts/autowrap/package.json b/packages/automation-contracts/autowrap/package.json index d2dab4d495..f26d9df987 100644 --- a/packages/automation-contracts/autowrap/package.json +++ b/packages/automation-contracts/autowrap/package.json @@ -15,6 +15,6 @@ "dependencies": { "@openzeppelin/contracts": "4.9.3", "@superfluid-finance/ethereum-contracts": "1.8.1", - "@superfluid-finance/metadata": "1.1.17" + "@superfluid-finance/metadata": "1.1.21" } } diff --git a/packages/automation-contracts/scheduler/package.json b/packages/automation-contracts/scheduler/package.json index db1d54a2b7..7735dd40a0 100644 --- a/packages/automation-contracts/scheduler/package.json +++ b/packages/automation-contracts/scheduler/package.json @@ -15,6 +15,6 @@ "dependencies": { "@openzeppelin/contracts": "4.9.3", "@superfluid-finance/ethereum-contracts": "1.8.1", - "@superfluid-finance/metadata": "1.1.17" + "@superfluid-finance/metadata": "1.1.21" } } diff --git a/packages/ethereum-contracts/CHANGELOG.md b/packages/ethereum-contracts/CHANGELOG.md index 7b267759a9..1e022c7bd3 100644 --- a/packages/ethereum-contracts/CHANGELOG.md +++ b/packages/ethereum-contracts/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Unreleased ### Breaking + - `TokenInfo` and `ERC20WithTokenInfo` interface/abstract contract are removed from the codebase, including the bundled ABI contracts - Migration: Use `IERC20Metadata` instead, as this replaces the previous contracts - `build/typechain-ethers-v5` is removed from the npm package @@ -25,13 +26,19 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Note that the admin is stored in the EIP-1967 admin storage slot (`0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`) - `SuperToken.getAdmin()` added to retrieve the admin address - `SuperTokenFactory.createERC20Wrapper()` overloads added to create a SuperToken AND explicitly initialize a SuperToken with an admin +- New explicit functions: `deployTestFrameworkWithEthersV5` and `deployTestFrameworkWithEthersV6` in `deploy-test-framework.js` + - `deployTestFramework` is still there, but it is considered deprecated now ### Changed + - Reuse config keys from `SuperfluidGovernanceConfigs` instead of duplicating them in `ConstantFlowAgreementV1`. - Deprecating `registerAppWithKey` and `registerAppByFactory`: DO NOT USE for new deployments - Simplification of Super App registration: use `registerApp` in all cases going forward. - Use `registerApp(uint256 configWord)` to be called by the super app in the constructor or `registerApp(ISuperApp app, uint256 configWord)` to be called by any address with a valid app registration config key +### Fixes +- [`dev-scripts/deploy-test-framework.js`](dev-scripts/deploy-test-framework.js) compatible with both ethers-v5 and ethers-v6 now + ## [v1.8.1] - 2023-08-28 ### Fixed diff --git a/packages/ethereum-contracts/contracts/agreements/gdav1/GeneralDistributionAgreementV1.sol b/packages/ethereum-contracts/contracts/agreements/gdav1/GeneralDistributionAgreementV1.sol index cb0808ec97..19be6f0955 100644 --- a/packages/ethereum-contracts/contracts/agreements/gdav1/GeneralDistributionAgreementV1.sol +++ b/packages/ethereum-contracts/contracts/agreements/gdav1/GeneralDistributionAgreementV1.sol @@ -90,10 +90,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi uint256 private constant _POOL_SUBS_BITMAP_STATE_SLOT_ID = 1; /// @dev Pool member state slot id starting point for pool connections uint256 private constant _POOL_CONNECTIONS_DATA_STATE_SLOT_ID_START = 1 << 128; - /// @dev CFAv1 PPP Config Key - bytes32 private constant CFAV1_PPP_CONFIG_KEY = - keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1.PPPConfiguration"); - + /// @dev SuperToken minimum deposit key bytes32 private constant SUPERTOKEN_MINIMUM_DEPOSIT_KEY = keccak256("org.superfluid-finance.superfluid.superTokenMinimumDeposit"); @@ -105,19 +102,21 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi superfluidPoolBeacon = superfluidPoolBeacon_; } - function realtimeBalanceVectorAt(ISuperfluidToken token, address account, uint256 time) + function realtimeBalanceOf(ISuperfluidToken token, address account, uint256 time) public view - returns (int256 available, int256 fromPools, int256 buffer) + override + returns (int256 rtb, uint256 buf, uint256 owedBuffer) { UniversalIndexData memory universalIndexData = _getUIndexData(abi.encode(token), account); if (_isPool(token, account)) { - available = ISuperfluidPool(account).getDisconnectedBalance(uint32(time)); + rtb = ISuperfluidPool(account).getDisconnectedBalance(uint32(time)); } else { - available = Value.unwrap(_getBasicParticleFromUIndex(universalIndexData).rtb(Time.wrap(uint32(time)))); + rtb = Value.unwrap(_getBasicParticleFromUIndex(universalIndexData).rtb(Time.wrap(uint32(time)))); } + int256 fromPools; { (uint32[] memory slotIds, bytes32[] memory pidList) = _listPoolConnectionIds(token, account); for (uint256 i = 0; i < slotIds.length; ++i) { @@ -126,24 +125,12 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi _getPoolMemberData(token, account, ISuperfluidPool(pool)); assert(exist); assert(poolMemberData.pool == pool); - fromPools = fromPools + ISuperfluidPool(pool).getClaimable(account, uint32(time)); + fromPools += ISuperfluidPool(pool).getClaimable(account, uint32(time)); } } + rtb += fromPools; - buffer = universalIndexData.totalBuffer.toInt256(); - } - - function realtimeBalanceOf(ISuperfluidToken token, address account, uint256 time) - public - view - override - returns (int256 rtb, uint256 buf, uint256 owedBuffer) - { - (int256 available, int256 fromPools, int256 buffer) = realtimeBalanceVectorAt(token, account, time); - rtb = available + fromPools; - - buf = uint256(buffer); // upcasting to uint256 is safe - owedBuffer = 0; + buf = uint256(universalIndexData.totalBuffer.toInt256()); // upcasting to uint256 is safe } /// @dev ISuperAgreement.realtimeBalanceOf implementation @@ -322,10 +309,15 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi ISuperfluid.Context memory currentContext = AgreementLibrary.authorizeTokenAccess(token, ctx); address msgSender = currentContext.msgSender; newCtx = ctx; - if (doConnect) { - if (!isMemberConnected(token, address(pool), msgSender)) { - assert(SuperfluidPool(address(pool)).operatorConnectMember(msgSender, true, uint32(block.timestamp))); + bool isConnected = _isMemberConnected(token, address(pool), msgSender); + if (doConnect != isConnected) { + assert( + SuperfluidPool(address(pool)).operatorConnectMember( + msgSender, doConnect, uint32(currentContext.timestamp) + ) + ); + if (doConnect) { uint32 poolSlotID = _findAndFillPoolConnectionsBitmap(token, msgSender, bytes32(uint256(uint160(address(pool))))); @@ -336,33 +328,24 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi _getPoolMemberHash(msgSender, pool), _encodePoolMemberData(PoolMemberData({ poolID: poolSlotID, pool: address(pool) })) ); - } - } else { - if (isMemberConnected(token, address(pool), msgSender)) { - assert(SuperfluidPool(address(pool)).operatorConnectMember(msgSender, false, uint32(block.timestamp))); + } else { (, PoolMemberData memory poolMemberData) = _getPoolMemberData(token, msgSender, pool); token.terminateAgreement(_getPoolMemberHash(msgSender, pool), 1); _clearPoolConnectionsBitmap(token, msgSender, poolMemberData.poolID); } + + emit PoolConnectionUpdated(token, pool, msgSender, doConnect, currentContext.userData); } - - emit PoolConnectionUpdated(token, pool, msgSender, doConnect, currentContext.userData); } - /// @inheritdoc IGeneralDistributionAgreementV1 - function isMemberConnected(ISuperfluidToken token, address pool, address member) - public - view - override - returns (bool) - { + function _isMemberConnected(ISuperfluidToken token, address pool, address member) internal view returns (bool) { (bool exist,) = _getPoolMemberData(token, member, ISuperfluidPool(pool)); return exist; } - function isMemberConnected(ISuperfluidPool pool, address member) public view override returns (bool) { - return isMemberConnected(pool.superToken(), address(pool), member); + function isMemberConnected(ISuperfluidPool pool, address member) external view override returns (bool) { + return _isMemberConnected(pool.superToken(), address(pool), member); } function appendIndexUpdateByPool(ISuperfluidToken token, BasicParticle memory p, Time t) external returns (bool) { @@ -404,12 +387,15 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi revert GDA_ONLY_SUPER_TOKEN_POOL(); } + // you cannot distribute if admin is not equal to the ctx.msgSender if (!pool.distributionFromAnyAddress()) { if (pool.admin() != currentContext.msgSender) { revert GDA_DISTRIBUTE_FROM_ANY_ADDRESS_NOT_ALLOWED(); } } + // the from address must be the same as the ctx.msgSender + // there is no ACL support if (from != currentContext.msgSender) { revert GDA_DISTRIBUTE_FOR_OTHERS_NOT_ALLOWED(); } @@ -467,7 +453,10 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi newCtx = ctx; - if (!pool.distributionFromAnyAddress()) { + // we must check if the requestedFlowRate is greater than 0 here + // otherwise we will block liquidators from closing streams in pools + // where the pool config has distributionFromAnyAddress set to false + if (requestedFlowRate > 0 && !pool.distributionFromAnyAddress()) { if (pool.admin() != flowVars.currentContext.msgSender) { revert GDA_DISTRIBUTE_FROM_ANY_ADDRESS_NOT_ALLOWED(); } @@ -479,7 +468,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi address(pool), flowVars.distributionFlowHash, FlowRate.wrap(requestedFlowRate), - Time.wrap(uint32(block.timestamp)) + Time.wrap(uint32(flowVars.currentContext.timestamp)) ); // handle distribute flow on behalf of someone else @@ -515,14 +504,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi } { - _adjustBuffer( - abi.encode(token), - address(pool), - from, - flowVars.distributionFlowHash, - flowVars.oldFlowRate, - actualFlowRate - ); + _adjustBuffer(token, address(pool), from, flowVars.distributionFlowHash, actualFlowRate); } // ensure sender has enough balance to execute transaction @@ -636,7 +618,6 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi _getFlowDistributionData(ISuperfluidToken(data.token), data.distributionFlowHash); int256 signedSingleDeposit = flowDistributionData.buffer.toInt256(); - bytes memory liquidationTypeData; bool isCurrentlyPatricianPeriod; { @@ -652,10 +633,9 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi // critical case if (totalRewardLeft >= 0) { int256 rewardAmount = (signedSingleDeposit * totalRewardLeft) / data.signedTotalGDADeposit; - liquidationTypeData = abi.encode(2, isCurrentlyPatricianPeriod ? 0 : 1); data.token.makeLiquidationPayoutsV2( data.distributionFlowHash, - liquidationTypeData, + abi.encode(2, isCurrentlyPatricianPeriod ? 0 : 1), data.liquidator, isCurrentlyPatricianPeriod, data.sender, @@ -677,15 +657,9 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi } } - function _adjustBuffer( - bytes memory eff, - address pool, - address from, - bytes32 flowHash, - FlowRate, // oldFlowRate, - FlowRate newFlowRate - ) internal returns (bytes memory) { - address token = abi.decode(eff, (address)); + function _adjustBuffer(ISuperfluidToken token, address pool, address from, bytes32 flowHash, FlowRate newFlowRate) + internal + { // not using oldFlowRate in this model // surprising effect: reducing flow rate may require more buffer when liquidation_period adjusted upward ISuperfluidGovernance gov = ISuperfluidGovernance(ISuperfluid(_host).getGovernance()); @@ -718,7 +692,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi ISuperfluidToken(token).updateAgreementData(flowHash, data); } - UniversalIndexData memory universalIndexData = _getUIndexData(eff, from); + UniversalIndexData memory universalIndexData = _getUIndexData(abi.encode(token), from); universalIndexData.totalBuffer = // new buffer (universalIndexData.totalBuffer.toInt256() + Value.unwrap(bufferDelta)).toUint256(); @@ -736,8 +710,6 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi universalIndexData.totalBuffer ); } - - return eff; } // Solvency Related Getters @@ -810,7 +782,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi data = new bytes32[](2); data[0] = bytes32( (uint256(int256(FlowRate.unwrap(p.flow_rate()))) << 160) | (uint256(Time.unwrap(p.settled_at())) << 128) - | (buffer << 32) | (isPool_ ? 1 : 0) + | (uint256(buffer.toUint96()) << 32) | (isPool_ ? 1 : 0) ); data[1] = bytes32(uint256(Value.unwrap(p._settled_value))); } @@ -823,7 +795,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi data = new bytes32[](2); data[0] = bytes32( (uint256(int256(uIndexData.flowRate)) << 160) | (uint256(uIndexData.settledAt) << 128) - | (uint256(uIndexData.totalBuffer) << 32) | (uIndexData.isPool ? 1 : 0) + | (uint256(uIndexData.totalBuffer.toUint96()) << 32) | (uIndexData.isPool ? 1 : 0) ); data[1] = bytes32(uint256(uIndexData.settledValue)); } diff --git a/packages/ethereum-contracts/contracts/agreements/gdav1/SuperfluidPool.sol b/packages/ethereum-contracts/contracts/agreements/gdav1/SuperfluidPool.sol index 6ad329cc26..fcb5714a4a 100644 --- a/packages/ethereum-contracts/contracts/agreements/gdav1/SuperfluidPool.sol +++ b/packages/ethereum-contracts/contracts/agreements/gdav1/SuperfluidPool.sol @@ -302,8 +302,8 @@ contract SuperfluidPool is ISuperfluidPool, BeaconProxiable { override returns (int256 claimableBalance, uint256 timestamp) { - // TODO, GDA.getHost().getTimestamp() should be used in principle - return (getClaimable(memberAddr, uint32(block.timestamp)), block.timestamp); + timestamp = ISuperfluid(superToken.getHost()).getNow(); + return (getClaimable(memberAddr, uint32(timestamp)), timestamp); } /// @inheritdoc ISuperfluidPool @@ -402,7 +402,7 @@ contract SuperfluidPool is ISuperfluidPool, BeaconProxiable { PDPoolMemberMU memory mu = PDPoolMemberMU(pdPoolIndex, pdPoolMember); // update pool's disconnected units - if (!GDA.isMemberConnected(superToken, address(this), memberAddr)) { + if (!GDA.isMemberConnected(ISuperfluidPool(address(this)), memberAddr)) { // trigger the side effect of claiming all if not connected // @note claiming is a bit surprising here given the function name int256 claimedAmount = _claimAll(memberAddr, time); @@ -442,9 +442,8 @@ contract SuperfluidPool is ISuperfluidPool, BeaconProxiable { /// @inheritdoc ISuperfluidPool function claimAll(address memberAddr) public returns (bool) { - bool isConnected = GDA.isMemberConnected(superToken, address(this), memberAddr); - // TODO, GDA.getHost().getTimestamp() should be used in principle - uint32 time = uint32(block.timestamp); + bool isConnected = GDA.isMemberConnected(ISuperfluidPool(address(this)), memberAddr); + uint32 time = uint32(ISuperfluid(superToken.getHost()).getNow()); int256 claimedAmount = _claimAll(memberAddr, time); if (!isConnected) { _shiftDisconnectedUnits(Unit.wrap(0), Value.wrap(claimedAmount), Time.wrap(time)); diff --git a/packages/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol b/packages/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol index b6ba00846b..df79a017ad 100644 --- a/packages/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol +++ b/packages/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol @@ -1055,7 +1055,7 @@ library SuperTokenV1Library { function isMemberConnected(ISuperToken token, address pool, address member) internal view returns (bool) { (, IGeneralDistributionAgreementV1 gda) = _getHostAndGDA(token); - return gda.isMemberConnected(token, pool, member); + return gda.isMemberConnected(ISuperfluidPool(pool), member); } @@ -1927,8 +1927,8 @@ library SuperTokenV1Library { function distributeFlowWithCtx( ISuperToken token, - ISuperfluidPool pool, address from, + ISuperfluidPool pool, int96 requestedFlowRate, bytes memory ctx ) internal returns (bytes memory newCtx) { diff --git a/packages/ethereum-contracts/contracts/gov/SuperfluidGovernanceBase.sol b/packages/ethereum-contracts/contracts/gov/SuperfluidGovernanceBase.sol index 3ed7e16750..4473fe2f18 100644 --- a/packages/ethereum-contracts/contracts/gov/SuperfluidGovernanceBase.sol +++ b/packages/ethereum-contracts/contracts/gov/SuperfluidGovernanceBase.sol @@ -64,7 +64,8 @@ abstract contract SuperfluidGovernanceBase is ISuperfluidGovernance ISuperfluid host, address hostNewLogic, address[] calldata agreementClassNewLogics, - address superTokenFactoryNewLogic + address superTokenFactoryNewLogic, + address poolBeaconNewLogic ) external override onlyAuthorized(host) @@ -87,6 +88,9 @@ abstract contract SuperfluidGovernanceBase is ISuperfluidGovernance // solhint-disable-next-line no-empty-blocks catch {} } + if (poolBeaconNewLogic != address(0)) { + host.updatePoolBeaconLogic(poolBeaconNewLogic); + } } function batchUpdateSuperTokenLogic( diff --git a/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IGeneralDistributionAgreementV1.sol b/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IGeneralDistributionAgreementV1.sol index 61baf42dc8..5b4e1fdb3b 100644 --- a/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IGeneralDistributionAgreementV1.sol +++ b/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IGeneralDistributionAgreementV1.sol @@ -215,13 +215,6 @@ abstract contract IGeneralDistributionAgreementV1 is ISuperAgreement { /// Check if an address is connected to the pool function isMemberConnected(ISuperfluidPool pool, address memberAddr) external view virtual returns (bool); - /// Check if an address is connected to the pool - function isMemberConnected(ISuperfluidToken token, address pool, address memberAddr) - external - view - virtual - returns (bool); - /// Get pool adjustment flow information: (recipient, flowHash, flowRate) function getPoolAdjustmentFlowInfo(ISuperfluidPool pool) external view virtual returns (address, bytes32, int96); diff --git a/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IPoolNFTBase.sol b/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IPoolNFTBase.sol index 6a8b736b0e..587c7c97d5 100644 --- a/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IPoolNFTBase.sol +++ b/packages/ethereum-contracts/contracts/interfaces/agreements/gdav1/IPoolNFTBase.sol @@ -4,14 +4,14 @@ pragma solidity >=0.8.4; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; interface IPoolNFTBase is IERC721Metadata { - error POOL_NFT_APPROVE_TO_CALLER(); - error POOL_NFT_ONLY_SUPER_TOKEN_FACTORY(); - error POOL_NFT_INVALID_TOKEN_ID(); - error POOL_NFT_APPROVE_TO_CURRENT_OWNER(); - error POOL_NFT_APPROVE_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); - error POOL_NFT_NOT_REGISTERED_POOL(); - error POOL_NFT_TRANSFER_NOT_ALLOWED(); - error POOL_NFT_TRANSFER_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); + error POOL_NFT_APPROVE_TO_CALLER(); // 0x9212b333 + error POOL_NFT_ONLY_SUPER_TOKEN_FACTORY(); // 0x1fd7e3d8 + error POOL_NFT_INVALID_TOKEN_ID(); // 0x09275994 + error POOL_NFT_APPROVE_TO_CURRENT_OWNER(); // 0x020226d3 + error POOL_NFT_APPROVE_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0x1e82f255 + error POOL_NFT_NOT_REGISTERED_POOL(); // 0x6421912e + error POOL_NFT_TRANSFER_NOT_ALLOWED(); // 0x432fb160 + error POOL_NFT_TRANSFER_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0x4028ee0e /// @notice Informs third-party platforms that NFT metadata should be updated /// @dev This event comes from https://eips.ethereum.org/EIPS/eip-4906 diff --git a/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol b/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol index 03fab72ef2..b6abefb953 100644 --- a/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol +++ b/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol @@ -32,7 +32,7 @@ import { IPoolMemberNFT } from "../agreements/gdav1/IPoolMemberNFT.sol"; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { IConstantFlowAgreementV1 } from "../agreements/IConstantFlowAgreementV1.sol"; import { IInstantDistributionAgreementV1 } from "../agreements/IInstantDistributionAgreementV1.sol"; -import { IGeneralDistributionAgreementV1 } from "../agreements/gdav1/IGeneralDistributionAgreementV1.sol"; +import { IGeneralDistributionAgreementV1, PoolConfig } from "../agreements/gdav1/IGeneralDistributionAgreementV1.sol"; import { ISuperfluidPool } from "../agreements/gdav1/ISuperfluidPool.sol"; /// Superfluid App interfaces: import { ISuperApp } from "./ISuperApp.sol"; @@ -240,6 +240,19 @@ interface ISuperfluid { */ function changeSuperTokenAdmin(ISuperToken token, address newAdmin) external; + /** + * @notice Change the implementation address the pool beacon points to + * @dev Updating the logic the beacon points to will update the logic of all the Pool BeaconProxy instances + */ + function updatePoolBeaconLogic(address newBeaconLogic) external; + + /** + * @dev Pool Beacon logic updated event + * @param beaconProxy addrss of the beacon proxy + * @param newBeaconLogic address of the new beacon logic + */ + event PoolBeaconLogicUpdated(address indexed beaconProxy, address newBeaconLogic); + /************************************************************************** * App Registry *************************************************************************/ diff --git a/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidGovernance.sol b/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidGovernance.sol index 6ef45d6f79..0aa7e90b13 100644 --- a/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidGovernance.sol +++ b/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidGovernance.sol @@ -41,7 +41,8 @@ interface ISuperfluidGovernance { ISuperfluid host, address hostNewLogic, address[] calldata agreementClassNewLogics, - address superTokenFactoryNewLogic + address superTokenFactoryNewLogic, + address beaconNewLogic ) external; /** diff --git a/packages/ethereum-contracts/contracts/libs/SafeGasLibrary.sol b/packages/ethereum-contracts/contracts/libs/SafeGasLibrary.sol index eedfd60f4e..33e24bb4b8 100644 --- a/packages/ethereum-contracts/contracts/libs/SafeGasLibrary.sol +++ b/packages/ethereum-contracts/contracts/libs/SafeGasLibrary.sol @@ -8,7 +8,7 @@ library SafeGasLibrary { error OUT_OF_GAS(); // 0x20afada5 function _isOutOfGas(uint256 gasLeftBefore) internal view returns (bool) { - return gasleft() <= gasLeftBefore / 63; + return gasleft() <= gasLeftBefore / 64; } /// @dev A function used in the catch block to handle true out of gas errors diff --git a/packages/ethereum-contracts/contracts/mocks/CrossStreamSuperApp.sol b/packages/ethereum-contracts/contracts/mocks/CrossStreamSuperApp.sol new file mode 100644 index 0000000000..06cb22df2e --- /dev/null +++ b/packages/ethereum-contracts/contracts/mocks/CrossStreamSuperApp.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: AGPLv3 +pragma solidity 0.8.19; + +import { ISuperfluid, ISuperToken } from "../interfaces/superfluid/ISuperfluid.sol"; +import { SuperAppBaseFlow } from "../apps/SuperAppBaseFlow.sol"; +import { SuperTokenV1Library } from "../apps/SuperTokenV1Library.sol"; + +using SuperTokenV1Library for ISuperToken; + +/// @title CrossStreamSuperApp +/// @author Superfluid +/// @dev A super app used for testing "cross-stream" flows in callbacks +/// and its behavior surrounding the internal protocol accounting. +/// That is, two senders sending a flow to the super app +contract CrossStreamSuperApp is SuperAppBaseFlow { + address public flowRecipient; + address public prevSender; + int96 public prevFlowRate; + + constructor(ISuperfluid host_, address z_) SuperAppBaseFlow(host_, true, true, true, "") { + flowRecipient = z_; + } + + function onFlowCreated(ISuperToken superToken, address sender, bytes calldata ctx) + internal + override + returns (bytes memory newCtx) + { + newCtx = ctx; + + // get incoming stream + int96 inFlowRate = superToken.getFlowRate(sender, address(this)); + + if (prevSender == address(0)) { + // first flow to super app creates a flow + newCtx = superToken.createFlowWithCtx(flowRecipient, inFlowRate, newCtx); + } else { + // subsequent flows to super app updates and deletes the flow + newCtx = superToken.updateFlowWithCtx(flowRecipient, inFlowRate, newCtx); + newCtx = superToken.deleteFlowWithCtx(prevSender, address(this), newCtx); + } + + prevSender = sender; + prevFlowRate = inFlowRate; + } +} diff --git a/packages/ethereum-contracts/contracts/mocks/SuperTokenLibraryV1Mock.sol b/packages/ethereum-contracts/contracts/mocks/SuperTokenLibraryV1Mock.sol index aae36c8f77..3e5dc35c23 100644 --- a/packages/ethereum-contracts/contracts/mocks/SuperTokenLibraryV1Mock.sol +++ b/packages/ethereum-contracts/contracts/mocks/SuperTokenLibraryV1Mock.sol @@ -871,7 +871,7 @@ contract SuperTokenLibraryGDASuperAppMock is SuperTokenLibraryGDAMock, SuperAppB } else if (functionIndex == uint8(FunctionIndex.DISTRIBUTE)) { return token.distributeWithCtx(ISuperfluidPool(pool), from, requestedAmount, ctx); } else if (functionIndex == uint8(FunctionIndex.DISTRIBUTE_FLOW)) { - return token.distributeFlowWithCtx(ISuperfluidPool(pool), from, requestedFlowRate, ctx); + return token.distributeFlowWithCtx(from, ISuperfluidPool(pool), requestedFlowRate, ctx); } else { revert("invalid function index"); } diff --git a/packages/ethereum-contracts/contracts/superfluid/Superfluid.sol b/packages/ethereum-contracts/contracts/superfluid/Superfluid.sol index 4c32a8c965..2e0925450e 100644 --- a/packages/ethereum-contracts/contracts/superfluid/Superfluid.sol +++ b/packages/ethereum-contracts/contracts/superfluid/Superfluid.sol @@ -19,7 +19,8 @@ import { ISuperToken, ISuperTokenFactory } from "../interfaces/superfluid/ISuperfluid.sol"; - +import { GeneralDistributionAgreementV1 } from "../agreements/gdav1/GeneralDistributionAgreementV1.sol"; +import { SuperfluidUpgradeableBeacon } from "../upgradability/SuperfluidUpgradeableBeacon.sol"; import { CallUtils } from "../libs/CallUtils.sol"; import { BaseRelayRecipient } from "../libs/BaseRelayRecipient.sol"; @@ -308,6 +309,23 @@ contract Superfluid is token.changeAdmin(newAdmin); } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Superfluid Upgradeable Beacon + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /// @inheritdoc ISuperfluid + function updatePoolBeaconLogic(address newLogic) external override onlyGovernance { + GeneralDistributionAgreementV1 gda = GeneralDistributionAgreementV1( + address( + this.getAgreementClass(keccak256("org.superfluid-finance.agreements.GeneralDistributionAgreement.v1")) + ) + ); + SuperfluidUpgradeableBeacon beacon = SuperfluidUpgradeableBeacon(address(gda.superfluidPoolBeacon())); + beacon.upgradeTo(newLogic); + + emit PoolBeaconLogicUpdated(address(beacon), newLogic); + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // App Registry //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/ethereum-contracts/contracts/utils/BatchLiquidator.sol b/packages/ethereum-contracts/contracts/utils/BatchLiquidator.sol index 4bf0f59390..77603cdc72 100644 --- a/packages/ethereum-contracts/contracts/utils/BatchLiquidator.sol +++ b/packages/ethereum-contracts/contracts/utils/BatchLiquidator.sol @@ -64,7 +64,10 @@ contract BatchLiquidator { { uint256 balance = ERC20(superToken).balanceOf(address(this)); if (balance > 0) { - ERC20(superToken).transferFrom(address(this), msg.sender, balance); + // don't fail for non-transferrable tokens + try ERC20(superToken).transferFrom(address(this), msg.sender, balance) + // solhint-disable-next-line no-empty-blocks + {} catch {} } } } @@ -91,7 +94,9 @@ contract BatchLiquidator { { uint256 balance = ERC20(superToken).balanceOf(address(this)); if (balance > 0) { - ERC20(superToken).transferFrom(address(this), msg.sender, balance); + try ERC20(superToken).transferFrom(address(this), msg.sender, balance) + // solhint-disable-next-line no-empty-blocks + {} catch {} } } } diff --git a/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol b/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol index cfb104fc1a..b207720f50 100644 --- a/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol +++ b/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol @@ -118,139 +118,6 @@ contract SuperfluidFrameworkDeploymentSteps { error DEPLOY_SUPER_TOKEN_REQUIRES_DEPLOY_SUPER_TOKEN_CONTRACTS(); error RESOLVER_LIST_REQUIRES_DEPLOY_PERIPHERALS(); - function _deployNFTProxyAndLogicAndInitialize() internal { - if (address(host) == address(0)) revert DEPLOY_SUPER_TOKEN_CONTRACTS_REQUIRES_DEPLOY_CORE(); - // Deploy canonical Constant Outflow NFT proxy contract - UUPSProxy constantOutflowNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); - - // Deploy canonical Constant Outflow NFT proxy contract - UUPSProxy constantInflowNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); - - // Deploy canonical Pool Admin NFT proxy contract - UUPSProxy poolAdminNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); - - // Deploy canonical Pool Member NFT proxy contract - UUPSProxy poolMemberNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); - - // Deploy canonical Constant Outflow NFT logic contract - constantOutflowNFTLogic = SuperfluidFlowNFTLogicDeployerLibrary.deployConstantOutflowNFT( - host, IConstantInflowNFT(address(constantInflowNFTProxy)) - ); - - // Initialize Constant Outflow NFT logic contract - constantOutflowNFTLogic.castrate(); - - // Deploy canonical Constant Inflow NFT logic contract - constantInflowNFTLogic = SuperfluidFlowNFTLogicDeployerLibrary.deployConstantInflowNFT( - host, IConstantOutflowNFT(address(constantOutflowNFTProxy)) - ); - - // Initialize Constant Inflow NFT logic contract - constantInflowNFTLogic.castrate(); - - // Deploy canonical Pool Admin NFT logic contract - poolAdminNFTLogic = SuperfluidPoolNFTLogicDeployerLibrary.deployPoolAdminNFT(host); - - // Initialize Pool Admin NFT logic contract - poolAdminNFTLogic.castrate(); - - // Deploy canonical Pool Member NFT logic contract - poolMemberNFTLogic = SuperfluidPoolNFTLogicDeployerLibrary.deployPoolMemberNFT(host); - - // Initialize Pool Member NFT logic contract - poolMemberNFTLogic.castrate(); - - // Initialize COFNFT proxy contract - constantOutflowNFTProxy.initializeProxy(address(constantOutflowNFTLogic)); - - // Initialize CIFNFT proxy contract - constantInflowNFTProxy.initializeProxy(address(constantInflowNFTLogic)); - - // Initialize Pool Admin NFT proxy contract - poolAdminNFTProxy.initializeProxy(address(poolAdminNFTLogic)); - - // Initialize Pool Member NFT proxy contract - poolMemberNFTProxy.initializeProxy(address(poolMemberNFTLogic)); - - // // Initialize COFNFT proxy contract - IConstantOutflowNFT(address(constantOutflowNFTProxy)).initialize("Constant Outflow NFT", "COF"); - - // // Initialize CIFNFT proxy contract - IConstantInflowNFT(address(constantInflowNFTProxy)).initialize("Constant Inflow NFT", "CIF"); - - // // Initialize Pool Admin NFT proxy contract - IPoolAdminNFT(address(poolAdminNFTProxy)).initialize("Pool Admin NFT", "PA"); - - // // Initialize Pool Member NFT proxy contract - IPoolMemberNFT(address(poolMemberNFTProxy)).initialize("Pool Member NFT", "PM"); - - constantOutflowNFT = ConstantOutflowNFT(address(constantOutflowNFTProxy)); - constantInflowNFT = ConstantInflowNFT(address(constantInflowNFTProxy)); - poolAdminNFT = PoolAdminNFT(address(poolAdminNFTProxy)); - poolMemberNFT = PoolMemberNFT(address(poolMemberNFTProxy)); - } - - function _deploySuperTokenLogicAndSuperTokenFactoryAndUpdateContracts() internal { - // _deploySuperTokenLogic(); - // Deploy canonical SuperToken logic contract - superTokenLogic = SuperToken( - SuperTokenDeployerLibrary.deploySuperTokenLogic( - host, - IConstantOutflowNFT(address(constantOutflowNFT)), - IConstantInflowNFT(address(constantInflowNFT)), - IPoolAdminNFT(address(poolAdminNFT)), - IPoolMemberNFT(address(poolMemberNFT)) - ) - ); - - // _deploySuperTokenFactory(); - superTokenFactoryLogic = SuperfluidPeripheryDeployerLibrary.deploySuperTokenFactory( - host, - superTokenLogic, - constantOutflowNFTLogic, - constantInflowNFTLogic, - poolAdminNFTLogic, - poolMemberNFTLogic - ); - - // _setSuperTokenFactoryInHost(); - // 'Update' code with Governance and register SuperTokenFactory with Superfluid - testGovernance.updateContracts(host, address(0), new address[](0), address(superTokenFactoryLogic)); - - // we set the canonical address based on host.getSuperTokenFactory() because - // in the upgradeable case, we create a new proxy contract in the function - // and set it as the canonical supertokenfactory. - superTokenFactory = SuperTokenFactory(address(host.getSuperTokenFactory())); - } - - function _deployTestResolverAndSuperfluidLoaderAndSet(address resolverAdmin) internal { - // _deployTestResolver(resolverAdmin); - if (address(host) == address(0)) revert DEPLOY_PERIPHERALS_REQUIRES_DEPLOY_CORE(); - testResolver = SuperfluidPeripheryDeployerLibrary.deployTestResolver(resolverAdmin); - - // _deploySuperfluidLoader(); - superfluidLoader = SuperfluidLoaderDeployerLibrary.deploySuperfluidLoader(testResolver); - - // _setAddressesInResolver(); - // Register Governance with Resolver - testResolver.set("TestGovernance.test", address(testGovernance)); - - // Register Superfluid with Resolver - testResolver.set("Superfluid.test", address(host)); - - // Register SuperfluidLoader with Resolver - testResolver.set("SuperfluidLoader-v1", address(superfluidLoader)); - - // Register CFAv1Forwarder with Resolver - testResolver.set("CFAv1Forwarder", address(cfaV1Forwarder)); - - // Register IDAv1Forwarder with Resolver - testResolver.set("IDAv1Forwarder", address(idaV1Forwarder)); - - // Register GDAv1Forwarder with Resolver - testResolver.set("GDAv1Forwarder", address(gdaV1Forwarder)); - } - /// @notice Fetches the framework contracts function getFramework() external view returns (Framework memory sf) { sf = Framework({ @@ -377,21 +244,150 @@ contract SuperfluidFrameworkDeploymentSteps { SuperfluidUpgradeableBeacon superfluidPoolBeacon = ProxyDeployerLibrary.deploySuperfluidUpgradeableBeacon(address(superfluidPoolLogic)); gdaV1.initialize(superfluidPoolBeacon); + + superfluidPoolBeacon.transferOwnership(address(host)); } else if (step == 5) { // PERIPHERAL CONTRACTS: NFT Proxy and Logic // Deploy Superfluid NFTs (Proxy and Logic contracts) - _deployNFTProxyAndLogicAndInitialize(); + + if (address(host) == address(0)) revert DEPLOY_SUPER_TOKEN_CONTRACTS_REQUIRES_DEPLOY_CORE(); + // Deploy canonical Constant Outflow NFT proxy contract + UUPSProxy constantOutflowNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); + + // Deploy canonical Constant Outflow NFT proxy contract + UUPSProxy constantInflowNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); + + // Deploy canonical Pool Admin NFT proxy contract + UUPSProxy poolAdminNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); + + // Deploy canonical Pool Member NFT proxy contract + UUPSProxy poolMemberNFTProxy = ProxyDeployerLibrary.deployUUPSProxy(); + + // Deploy canonical Constant Outflow NFT logic contract + constantOutflowNFTLogic = SuperfluidFlowNFTLogicDeployerLibrary.deployConstantOutflowNFT( + host, IConstantInflowNFT(address(constantInflowNFTProxy)) + ); + + // Initialize Constant Outflow NFT logic contract + constantOutflowNFTLogic.castrate(); + + // Deploy canonical Constant Inflow NFT logic contract + constantInflowNFTLogic = SuperfluidFlowNFTLogicDeployerLibrary.deployConstantInflowNFT( + host, IConstantOutflowNFT(address(constantOutflowNFTProxy)) + ); + + // Initialize Constant Inflow NFT logic contract + constantInflowNFTLogic.castrate(); + + // Deploy canonical Pool Admin NFT logic contract + poolAdminNFTLogic = SuperfluidPoolNFTLogicDeployerLibrary.deployPoolAdminNFT(host); + + // Initialize Pool Admin NFT logic contract + poolAdminNFTLogic.castrate(); + + // Deploy canonical Pool Member NFT logic contract + poolMemberNFTLogic = SuperfluidPoolNFTLogicDeployerLibrary.deployPoolMemberNFT(host); + + // Initialize Pool Member NFT logic contract + poolMemberNFTLogic.castrate(); + + // Initialize COFNFT proxy contract + constantOutflowNFTProxy.initializeProxy(address(constantOutflowNFTLogic)); + + // Initialize CIFNFT proxy contract + constantInflowNFTProxy.initializeProxy(address(constantInflowNFTLogic)); + + // Initialize Pool Admin NFT proxy contract + poolAdminNFTProxy.initializeProxy(address(poolAdminNFTLogic)); + + // Initialize Pool Member NFT proxy contract + poolMemberNFTProxy.initializeProxy(address(poolMemberNFTLogic)); + + // // Initialize COFNFT proxy contract + IConstantOutflowNFT(address(constantOutflowNFTProxy)).initialize("Constant Outflow NFT", "COF"); + + // // Initialize CIFNFT proxy contract + IConstantInflowNFT(address(constantInflowNFTProxy)).initialize("Constant Inflow NFT", "CIF"); + + // // Initialize Pool Admin NFT proxy contract + IPoolAdminNFT(address(poolAdminNFTProxy)).initialize("Pool Admin NFT", "PA"); + + // // Initialize Pool Member NFT proxy contract + IPoolMemberNFT(address(poolMemberNFTProxy)).initialize("Pool Member NFT", "PM"); + + constantOutflowNFT = ConstantOutflowNFT(address(constantOutflowNFTProxy)); + constantInflowNFT = ConstantInflowNFT(address(constantInflowNFTProxy)); + poolAdminNFT = PoolAdminNFT(address(poolAdminNFTProxy)); + poolMemberNFT = PoolMemberNFT(address(poolMemberNFTProxy)); } else if (step == 6) { // PERIPHERAL CONTRACTS: SuperToken Logic and SuperTokenFactory Logic // Deploy SuperToken Logic // Deploy SuperToken Factory - _deploySuperTokenLogicAndSuperTokenFactoryAndUpdateContracts(); + + // _deploySuperTokenLogic(); + // Deploy canonical SuperToken logic contract + superTokenLogic = SuperToken( + SuperTokenDeployerLibrary.deploySuperTokenLogic( + host, + IConstantOutflowNFT(address(constantOutflowNFT)), + IConstantInflowNFT(address(constantInflowNFT)), + IPoolAdminNFT(address(poolAdminNFT)), + IPoolMemberNFT(address(poolMemberNFT)) + ) + ); + + // _deploySuperTokenFactory(); + superTokenFactoryLogic = SuperfluidPeripheryDeployerLibrary.deploySuperTokenFactory( + host, + superTokenLogic, + constantOutflowNFTLogic, + constantInflowNFTLogic, + poolAdminNFTLogic, + poolMemberNFTLogic + ); + + // _setSuperTokenFactoryInHost(); + // 'Update' code with Governance and register SuperTokenFactory with Superfluid + testGovernance.updateContracts( + host, address(0), new address[](0), address(superTokenFactoryLogic), address(0) + ); + + // we set the canonical address based on host.getSuperTokenFactory() because + // in the upgradeable case, we create a new proxy contract in the function + // and set it as the canonical supertokenfactory. + superTokenFactory = SuperTokenFactory(address(host.getSuperTokenFactory())); } else if (step == 7) { // PERIPHERAL CONTRACTS: Resolver, SuperfluidLoader, TOGA, BatchLiquidator // Deploy TestResolver - // Deploy SuperfluidLoader and make SuperfluidFrameworkDpeloyer an admin for the TestResolver + // Deploy SuperfluidLoader and make SuperfluidFrameworkDeployer an admin for the TestResolver // Set TestGovernance, Superfluid, SuperfluidLoader and CFAv1Forwarder in TestResolver - _deployTestResolverAndSuperfluidLoaderAndSet(address(this)); + + // _deployTestResolver(resolverAdmin); + if (address(host) == address(0)) revert DEPLOY_PERIPHERALS_REQUIRES_DEPLOY_CORE(); + testResolver = SuperfluidPeripheryDeployerLibrary.deployTestResolver(address(this)); + + // _deploySuperfluidLoader(); + superfluidLoader = SuperfluidLoaderDeployerLibrary.deploySuperfluidLoader(testResolver); + + // _setAddressesInResolver(); + // Register Governance with Resolver + testResolver.set("TestGovernance.test", address(testGovernance)); + + // Register Superfluid with Resolver + testResolver.set("Superfluid.test", address(host)); + + // Register SuperfluidLoader with Resolver + testResolver.set("SuperfluidLoader-v1", address(superfluidLoader)); + + // Register CFAv1Forwarder with Resolver + testResolver.set("CFAv1Forwarder", address(cfaV1Forwarder)); + + // Register IDAv1Forwarder with Resolver + testResolver.set("IDAv1Forwarder", address(idaV1Forwarder)); + + // Register GDAv1Forwarder with Resolver + testResolver.set("GDAv1Forwarder", address(gdaV1Forwarder)); + // Make SuperfluidFrameworkDeployer deployer an admin for the TestResolver as well testResolver.addAdmin(msg.sender); diff --git a/packages/ethereum-contracts/dev-scripts/deploy-contracts-and-token.js b/packages/ethereum-contracts/dev-scripts/deploy-contracts-and-token.js index e08b4fb6a0..34bf331116 100644 --- a/packages/ethereum-contracts/dev-scripts/deploy-contracts-and-token.js +++ b/packages/ethereum-contracts/dev-scripts/deploy-contracts-and-token.js @@ -2,13 +2,14 @@ const {ethers} = require("hardhat"); const testResolverArtifact = require("@superfluid-finance/ethereum-contracts/build/hardhat/contracts/utils/TestResolver.sol/TestResolver.json"); const { - deployTestFramework, + deployTestFrameworkWithEthersV5, } = require("@superfluid-finance/ethereum-contracts/dev-scripts/deploy-test-framework"); async function deployContractsAndToken() { const [Deployer] = await ethers.getSigners(); - const {frameworkDeployer: deployer} = await deployTestFramework(); + const {frameworkDeployer: deployer} = + await deployTestFrameworkWithEthersV5(Deployer); const framework = await deployer.getFramework(); const resolver = await ethers.getContractAt( diff --git a/packages/ethereum-contracts/dev-scripts/deploy-test-framework.js b/packages/ethereum-contracts/dev-scripts/deploy-test-framework.js index 74981b2802..168d3d3bcb 100644 --- a/packages/ethereum-contracts/dev-scripts/deploy-test-framework.js +++ b/packages/ethereum-contracts/dev-scripts/deploy-test-framework.js @@ -56,6 +56,17 @@ async function deployERC1820(provider) { } } +/** + * Gets the address of the deployed contract. + * This is for handling the different contract objects in ethers v5 (contract.address) + * vs ethers v6 (contract.target), that is, v6 does not have contract.address and vice versa. + * @param {ethers.Contract} contract + * @returns + */ +const getContractAddress = (contract) => { + return contract.address || contract.target; +}; + const _getFactoryAndReturnDeployedContract = async ( contractName, artifact, @@ -70,21 +81,40 @@ const _getFactoryAndReturnDeployedContract = async ( signerOrOptions ); const contract = await ContractFactory.deploy(...args); - await contract.deployed(); + // ethers v5 + if (contract.deployed) { + await contract.deployed(); + } else if (!contract.deployed) { + // ethers v6 + await contract.waitForDeployment(); + } + if (process.env.DEBUG_CONSOLE === true) { - console.log(`${contractName} Deployed At:`, contract.address); + console.log( + `${contractName} Deployed At:`, + getContractAddress(contract) + ); } return contract; }; -/** - * Deploys Superfluid Framework in local testing environments. - * NOTE: This only works with Hardhat. - * @returns - */ -const deployTestFramework = async () => { - const signer = (await ethers.getSigners())[0]; - await deployERC1820(ethers.provider); +const deployTestFrameworkWithEthersV6 = async (privateKey, provider) => { + if (!privateKey) throw new Error("You must pass a private key."); + if (!provider) throw new Error("You must pass a provider."); + + const signer = new ethers.Wallet(privateKey, provider); + + return await _deployTestFramework(provider, signer); +}; + +const deployTestFrameworkWithEthersV5 = async (ethersV5Signer) => { + if (!ethersV5Signer.provider) + throw new Error("Your signer must have a provider."); + return await _deployTestFramework(ethersV5Signer.provider, ethersV5Signer); +}; + +const _deployTestFramework = async (provider, signer) => { + await deployERC1820(provider); const SlotsBitmapLibrary = await _getFactoryAndReturnDeployedContract( "SlotsBitmapLibrary", SlotsBitmapLibraryArtifact, @@ -115,7 +145,7 @@ const deployTestFramework = async () => { { signer, libraries: { - SlotsBitmapLibrary: SlotsBitmapLibrary.address, + SlotsBitmapLibrary: getContractAddress(SlotsBitmapLibrary), }, } ); @@ -214,35 +244,50 @@ const deployTestFramework = async () => { { signer, libraries: { - SuperfluidGovDeployerLibrary: - SuperfluidGovDeployerLibrary.address, - SuperfluidHostDeployerLibrary: - SuperfluidHostDeployerLibrary.address, - SuperfluidCFAv1DeployerLibrary: - SuperfluidCFAv1DeployerLibrary.address, - SuperfluidIDAv1DeployerLibrary: - SuperfluidIDAv1DeployerLibrary.address, - SuperfluidGDAv1DeployerLibrary: - SuperfluidGDAv1DeployerLibrary.address, - SuperfluidPeripheryDeployerLibrary: - SuperfluidPeripheryDeployerLibrary.address, - SuperTokenDeployerLibrary: SuperTokenDeployerLibrary.address, - SuperfluidPoolLogicDeployerLibrary: - SuperfluidPoolLogicDeployerLibrary.address, - SuperfluidFlowNFTLogicDeployerLibrary: - SuperfluidFlowNFTLogicDeployerLibrary.address, - SuperfluidPoolNFTLogicDeployerLibrary: - SuperfluidPoolNFTLogicDeployerLibrary.address, - ProxyDeployerLibrary: ProxyDeployerLibrary.address, - CFAv1ForwarderDeployerLibrary: - CFAv1ForwarderDeployerLibrary.address, - IDAv1ForwarderDeployerLibrary: - IDAv1ForwarderDeployerLibrary.address, - GDAv1ForwarderDeployerLibrary: - GDAv1ForwarderDeployerLibrary.address, - SuperfluidLoaderDeployerLibrary: - SuperfluidLoaderDeployerLibrary.address, - TokenDeployerLibrary: TokenDeployerLibrary.address, + SuperfluidGovDeployerLibrary: getContractAddress( + SuperfluidGovDeployerLibrary + ), + SuperfluidHostDeployerLibrary: getContractAddress( + SuperfluidHostDeployerLibrary + ), + SuperfluidCFAv1DeployerLibrary: getContractAddress( + SuperfluidCFAv1DeployerLibrary + ), + SuperfluidIDAv1DeployerLibrary: getContractAddress( + SuperfluidIDAv1DeployerLibrary + ), + SuperfluidGDAv1DeployerLibrary: getContractAddress( + SuperfluidGDAv1DeployerLibrary + ), + SuperfluidPeripheryDeployerLibrary: getContractAddress( + SuperfluidPeripheryDeployerLibrary + ), + SuperTokenDeployerLibrary: getContractAddress( + SuperTokenDeployerLibrary + ), + SuperfluidPoolLogicDeployerLibrary: getContractAddress( + SuperfluidPoolLogicDeployerLibrary + ), + SuperfluidFlowNFTLogicDeployerLibrary: getContractAddress( + SuperfluidFlowNFTLogicDeployerLibrary + ), + SuperfluidPoolNFTLogicDeployerLibrary: getContractAddress( + SuperfluidPoolNFTLogicDeployerLibrary + ), + ProxyDeployerLibrary: getContractAddress(ProxyDeployerLibrary), + CFAv1ForwarderDeployerLibrary: getContractAddress( + CFAv1ForwarderDeployerLibrary + ), + IDAv1ForwarderDeployerLibrary: getContractAddress( + IDAv1ForwarderDeployerLibrary + ), + GDAv1ForwarderDeployerLibrary: getContractAddress( + GDAv1ForwarderDeployerLibrary + ), + SuperfluidLoaderDeployerLibrary: getContractAddress( + SuperfluidLoaderDeployerLibrary + ), + TokenDeployerLibrary: getContractAddress(TokenDeployerLibrary), }, } ); @@ -250,10 +295,44 @@ const deployTestFramework = async () => { for (let i = 0; i < numSteps; i++) { await sfDeployer.executeStep(i); } - const sf = await sfDeployer.getFramework(); return {frameworkDeployer: sfDeployer}; }; +const printProtocolFrameworkAddresses = (framework) => { + const output = { + Host: framework.host, + CFAv1: framework.cfa, + IDAv1: framework.ida, + SuperTokenFactory: framework.superTokenFactory, + SuperTokenLogic: framework.superTokenLogic, + ConstantOutflowNFT: framework.constantOutflowNFT, + ConstantInflowNFT: framework.constantInflowNFT, + Resolver: framework.resolver, + SuperfluidLoader: framework.superfluidLoader, + CFAv1Forwarder: framework.cfaV1Forwarder, + IDAv1Forwarder: framework.idaV1Forwarder, + }; + + console.log(JSON.stringify(output, null, 2)); + + return output; +}; + +/** + * {DEPRECATED} + * Deploys Superfluid Framework in local testing environments. + * + * NOTE: This only works with Hardhat + ethers v5. + * @returns SuperfluidFrameworkDeployer Contract object + */ +const deployTestFramework = async () => { + const signer = (await ethers.getSigners())[0]; + return await deployTestFrameworkWithEthersV5(signer); +}; + module.exports = { deployTestFramework, + deployTestFrameworkWithEthersV5, + deployTestFrameworkWithEthersV6, + printProtocolFrameworkAddresses, }; diff --git a/packages/ethereum-contracts/dev-scripts/index.js b/packages/ethereum-contracts/dev-scripts/index.js index feeb1da565..d2531ef3b7 100644 --- a/packages/ethereum-contracts/dev-scripts/index.js +++ b/packages/ethereum-contracts/dev-scripts/index.js @@ -1,5 +1,13 @@ -const deployTestFramework = require("./deploy-test-framework"); +const { + deployTestFramework, + deployTestFrameworkWithEthersV5, + deployTestFrameworkWithEthersV6, + printProtocolFrameworkAddresses +} = require("./deploy-test-framework"); module.exports = { + deployTestFrameworkWithEthersV6, + deployTestFrameworkWithEthersV5, deployTestFramework, + printProtocolFrameworkAddresses }; diff --git a/packages/ethereum-contracts/ops-scripts/deploy-framework.js b/packages/ethereum-contracts/ops-scripts/deploy-framework.js index 3c88fc500f..e41c8d4e2a 100644 --- a/packages/ethereum-contracts/ops-scripts/deploy-framework.js +++ b/packages/ethereum-contracts/ops-scripts/deploy-framework.js @@ -1229,7 +1229,8 @@ module.exports = eval(`(${S.toString()})({skipArgv: true})`)(async function ( superfluid.address, superfluidNewLogicAddress, agreementsToUpdate, - superTokenFactoryNewLogicAddress + superTokenFactoryNewLogicAddress, + ZERO_ADDRESS ) ); } @@ -1295,6 +1296,10 @@ module.exports = eval(`(${S.toString()})({skipArgv: true})`)(async function ( superfluidPoolBeaconContract.address ); output += `SUPERFLUID_POOL_BEACON=${superfluidPoolBeaconContract.address}\n`; + + console.log("Transferring ownership of beacon contract to Superfluid Host..."); + await superfluidPoolBeaconContract.transferOwnership(superfluid.address); + console.log("Initializing GDA w/ beacon contract..."); await gdaV1Contract.initialize(superfluidPoolBeaconContract.address); } else { diff --git a/packages/ethereum-contracts/ops-scripts/resolver-list-super-token.js b/packages/ethereum-contracts/ops-scripts/resolver-list-super-token.js index 35a8a28e82..15f99f061b 100644 --- a/packages/ethereum-contracts/ops-scripts/resolver-list-super-token.js +++ b/packages/ethereum-contracts/ops-scripts/resolver-list-super-token.js @@ -64,7 +64,8 @@ module.exports = eval(`(${S.toString()})()`)(async function ( "org.superfluid-finance.contracts.SuperToken.implementation" ) ) { - throw new Error("Not a super token"); + // This may be ok, but may also point to a mistake in address handling (e.g. not a SuperToken). + console.warn('!!! proxiableUUID is not keccak("org.superfluid-finance.contracts.SuperToken.implementation")'); } const tokenSymbol = symbolOverride !== undefined ? symbolOverride : await superToken.symbol.call(); const superTokenKey = `supertokens.${protocolReleaseVersion}.${tokenSymbol}`; diff --git a/packages/ethereum-contracts/package.json b/packages/ethereum-contracts/package.json index 242dd0011d..85eef3024a 100644 --- a/packages/ethereum-contracts/package.json +++ b/packages/ethereum-contracts/package.json @@ -78,10 +78,12 @@ }, "dependencies": { "@decentral.ee/web3-helpers": "0.5.3", + "@nomiclabs/hardhat-ethers": "^2.2.3", "@openzeppelin/contracts": "4.9.3", "@truffle/contract": "4.6.29", "ethereumjs-tx": "2.1.2", - "ethereumjs-util": "7.1.5" + "ethereumjs-util": "7.1.5", + "hardhat": "^2.17.3" }, "devDependencies": { "@nomiclabs/hardhat-truffle5": "^2.0.7", @@ -89,7 +91,7 @@ "@safe-global/safe-service-client": "^2.0.3", "@safe-global/safe-web3-lib": "^1.9.4", "@superfluid-finance/js-sdk": "0.6.3", - "@superfluid-finance/metadata": "1.1.17", + "@superfluid-finance/metadata": "1.1.21", "async": "^3.2.4", "csv-writer": "^1.6.0", "ethers": "^5.7.2", diff --git a/packages/ethereum-contracts/tasks/deploy-gda-forwarder.sh b/packages/ethereum-contracts/tasks/deploy-gda-forwarder.sh index 4046cfcf10..08da123704 100755 --- a/packages/ethereum-contracts/tasks/deploy-gda-forwarder.sh +++ b/packages/ethereum-contracts/tasks/deploy-gda-forwarder.sh @@ -26,7 +26,7 @@ source .env set -x network=$1 -expectedContractAddr="0x6dA170169d5Fca20F902b7E5755346a97c94B07c" +expectedContractAddr="0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08" deployerPk=$GDAFWD_DEPLOYER_PK tmpfile="/tmp/deploy-gda-forwarder.sh" diff --git a/packages/ethereum-contracts/tasks/etherscan-verify-framework.sh b/packages/ethereum-contracts/tasks/etherscan-verify-framework.sh index d2dd21886c..880d40dcdf 100755 --- a/packages/ethereum-contracts/tasks/etherscan-verify-framework.sh +++ b/packages/ethereum-contracts/tasks/etherscan-verify-framework.sh @@ -28,7 +28,7 @@ source "$ADDRESSES_VARS" FAILED_VERIFICATIONS=() function try_verify() { echo # newline for better readability - npx truffle run --network "$TRUFFLE_NETWORK" verify "$@" "$EXTRA_ARGS" || + npx truffle run --network "$TRUFFLE_NETWORK" verify "$@" ${EXTRA_ARGS:+$EXTRA_ARGS} || FAILED_VERIFICATIONS[${#FAILED_VERIFICATIONS[@]}]="$*" # NOTE: append using length so that having spaces in the element is not a problem # TODO: version 0.6.5 of the plugin seems to not reliably return non-zero if verification fails @@ -56,14 +56,6 @@ EOF ) > "$CONTRACTS_DIR/${contract_name}.json" } -if [ -n "$CONSTANT_OUTFLOW_NFT_LOGIC" ]; then - try_verify ConstantOutflowNFT@"${CONSTANT_OUTFLOW_NFT_LOGIC}" -fi - -if [ -n "$CONSTANT_INFLOW_NFT_LOGIC" ]; then - try_verify ConstantInflowNFT@"${CONSTANT_INFLOW_NFT_LOGIC}" -fi - if [ -n "$RESOLVER" ]; then try_verify Resolver@"${RESOLVER}" fi diff --git a/packages/ethereum-contracts/test/contracts/apps/SuperTokenV1Library.GDA.test.ts b/packages/ethereum-contracts/test/contracts/apps/SuperTokenV1Library.GDA.test.ts index 0c8a4920d9..68ddfff3e3 100644 --- a/packages/ethereum-contracts/test/contracts/apps/SuperTokenV1Library.GDA.test.ts +++ b/packages/ethereum-contracts/test/contracts/apps/SuperTokenV1Library.GDA.test.ts @@ -339,28 +339,16 @@ describe("SuperTokenV1Library.GDA", function () { ).to.equal(true); }); - it("#2.3 should disconnectPool in callback", async () => { - await expect( - host - .connect(aliceSigner) - .callAgreement( - cfa.address, - createFlowCalldata, - userData( - callbackFunctionIndex.DISCONNECT_POOL, - appCreatedPool.address - ) + it("#2.3 should call disconnectPool in callback without revert", async () => { + await host + .connect(aliceSigner) + .callAgreement( + cfa.address, + createFlowCalldata, + userData( + callbackFunctionIndex.DISCONNECT_POOL, + appCreatedPool.address ) - ) - .to.emit(t.contracts.gda, "PoolConnectionUpdated") - .withArgs( - ethers.utils.getAddress(appSuperToken.address), - ethers.utils.getAddress(appCreatedPool.address), - ethers.utils.getAddress( - superTokenLibGDASuperAppMock.address - ), - false, - "0x3078" ); }); diff --git a/packages/ethereum-contracts/test/contracts/gov/SuperfluidGovernanceII.test.ts b/packages/ethereum-contracts/test/contracts/gov/SuperfluidGovernanceII.test.ts index 28f9f974d8..8e06678697 100644 --- a/packages/ethereum-contracts/test/contracts/gov/SuperfluidGovernanceII.test.ts +++ b/packages/ethereum-contracts/test/contracts/gov/SuperfluidGovernanceII.test.ts @@ -79,6 +79,7 @@ describe("Superfluid Ownable Governance Contract", function () { superfluid.address, ZERO_ADDRESS, [], + ZERO_ADDRESS, ZERO_ADDRESS ), governance, diff --git a/packages/ethereum-contracts/test/contracts/superfluid/SuperTokenFactory.test.ts b/packages/ethereum-contracts/test/contracts/superfluid/SuperTokenFactory.test.ts index c682e94267..0e19b464c4 100644 --- a/packages/ethereum-contracts/test/contracts/superfluid/SuperTokenFactory.test.ts +++ b/packages/ethereum-contracts/test/contracts/superfluid/SuperTokenFactory.test.ts @@ -185,7 +185,8 @@ describe("SuperTokenFactory Contract", function () { superfluid.address, ZERO_ADDRESS, [], - factory2Logic.address + factory2Logic.address, + ZERO_ADDRESS ); await superfluid.getSuperTokenFactoryLogic(); } @@ -347,7 +348,8 @@ describe("SuperTokenFactory Contract", function () { superfluid.address, ZERO_ADDRESS, [], - factory2Logic.address + factory2Logic.address, + ZERO_ADDRESS ); await expectCustomError( diff --git a/packages/ethereum-contracts/test/contracts/superfluid/Superfluid.test.ts b/packages/ethereum-contracts/test/contracts/superfluid/Superfluid.test.ts index 14f1d3a219..98fe04baf7 100644 --- a/packages/ethereum-contracts/test/contracts/superfluid/Superfluid.test.ts +++ b/packages/ethereum-contracts/test/contracts/superfluid/Superfluid.test.ts @@ -122,6 +122,7 @@ describe("Superfluid Host Contract", function () { superfluid.address, mock1.address, [], + ZERO_ADDRESS, ZERO_ADDRESS ); @@ -137,6 +138,7 @@ describe("Superfluid Host Contract", function () { superfluid.address, mock2.address, [], + ZERO_ADDRESS, ZERO_ADDRESS ), superfluid, @@ -240,6 +242,7 @@ describe("Superfluid Host Contract", function () { superfluid.address, ZERO_ADDRESS, [mockA2.address], + ZERO_ADDRESS, ZERO_ADDRESS ); console.debug( @@ -349,6 +352,7 @@ describe("Superfluid Host Contract", function () { superfluid.address, ZERO_ADDRESS, [mockA.address], + ZERO_ADDRESS, ZERO_ADDRESS ), superfluid, @@ -430,7 +434,8 @@ describe("Superfluid Host Contract", function () { superfluid.address, ZERO_ADDRESS, [], - factory2Logic.address + factory2Logic.address, + ZERO_ADDRESS ); assert.equal( await superfluid.getSuperTokenFactory(), @@ -479,7 +484,8 @@ describe("Superfluid Host Contract", function () { superfluid.address, ZERO_ADDRESS, [], - factory2Logic.address + factory2Logic.address, + ZERO_ADDRESS ); assert.equal( await superfluid.getSuperTokenFactory(), @@ -2633,6 +2639,7 @@ describe("Superfluid Host Contract", function () { superfluid.address, ZERO_ADDRESS, [t.contracts.ida.address], + ZERO_ADDRESS, ZERO_ADDRESS ), superfluid, @@ -2677,7 +2684,8 @@ describe("Superfluid Host Contract", function () { superfluid.address, ZERO_ADDRESS, [], - factory2Logic.address + factory2Logic.address, + ZERO_ADDRESS ), superfluid, "HOST_NON_UPGRADEABLE" @@ -2696,6 +2704,7 @@ describe("Superfluid Host Contract", function () { superfluid.address, mock1.address, [], + ZERO_ADDRESS, ZERO_ADDRESS ), superfluid, diff --git a/packages/ethereum-contracts/test/foundry/FoundrySuperfluidTester.sol b/packages/ethereum-contracts/test/foundry/FoundrySuperfluidTester.sol index 5de4f35e06..e31dedfeb2 100644 --- a/packages/ethereum-contracts/test/foundry/FoundrySuperfluidTester.sol +++ b/packages/ethereum-contracts/test/foundry/FoundrySuperfluidTester.sol @@ -688,7 +688,7 @@ contract FoundrySuperfluidTester is Test { uint8 underlyingDecimals, string memory name, string memory symbol, - address admin + address _admin ) internal returns (SuperToken localSuperToken) { localSuperToken = new SuperToken( sf.host, @@ -697,7 +697,7 @@ contract FoundrySuperfluidTester is Test { previousSuperToken.POOL_ADMIN_NFT(), previousSuperToken.POOL_MEMBER_NFT() ); - localSuperToken.initializeWithAdmin(underlyingToken, underlyingDecimals, name, symbol, admin); + localSuperToken.initializeWithAdmin(underlyingToken, underlyingDecimals, name, symbol, _admin); } // Write Helpers - ConstantFlowAgreementV1 @@ -1700,7 +1700,7 @@ contract FoundrySuperfluidTester is Test { bool isMemberConnected = useForwarder_ ? sf.gdaV1Forwarder.isMemberConnected(pool_, caller_) - : sf.gda.isMemberConnected(superToken_, address(pool_), caller_); + : sf.gda.isMemberConnected(pool_, caller_); assertEq(isMemberConnected, true, "GDAv1.t: Member not connected"); // Assert connected units delta for the pool @@ -1758,7 +1758,7 @@ contract FoundrySuperfluidTester is Test { } assertEq( - sf.gda.isMemberConnected(superToken_, address(pool_), caller_), + sf.gda.isMemberConnected(pool_, caller_), false, "GDAv1.t D/C: Member not disconnected" ); @@ -1839,7 +1839,7 @@ contract FoundrySuperfluidTester is Test { (int256 fromRTBAfter,,,) = superToken.realtimeBalanceOfNow(from_); // If the distributor is a connected member themselves, they will receive the units // they have just distributed - uint256 amountReceivedInitial = sf.gda.isMemberConnected(superToken, address(pool_), from_) + uint256 amountReceivedInitial = sf.gda.isMemberConnected(pool_, from_) ? uint256(pool_.getUnits(from_)) * amountPerUnit : 0; assertEq( @@ -1854,7 +1854,7 @@ contract FoundrySuperfluidTester is Test { // Assert Members RTB for (uint256 i; i < members.length; ++i) { (int256 memberRTB,,,) = superToken.realtimeBalanceOfNow(members[i]); - bool memberConnected = sf.gda.isMemberConnected(superToken, address(pool_), members[i]); + bool memberConnected = sf.gda.isMemberConnected(pool_, members[i]); uint256 amountReceived = uint256(pool_.getUnits(members[i])) * amountPerUnit; if (memberConnected) { diff --git a/packages/ethereum-contracts/test/foundry/agreements/gdav1/GeneralDistributionAgreement.t.sol b/packages/ethereum-contracts/test/foundry/agreements/gdav1/GeneralDistributionAgreement.t.sol index ad1e8f1d08..9d9b80e727 100644 --- a/packages/ethereum-contracts/test/foundry/agreements/gdav1/GeneralDistributionAgreement.t.sol +++ b/packages/ethereum-contracts/test/foundry/agreements/gdav1/GeneralDistributionAgreement.t.sol @@ -41,20 +41,31 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); - SuperfluidPool public currentPool; + /// @dev The freePool uses `poolConfig` where both transfer and distributeFromAnyAddress is true + SuperfluidPool public freePool; uint256 public liquidationPeriod; - constructor() FoundrySuperfluidTester(6) { } + constructor() FoundrySuperfluidTester(7) { } function setUp() public override { super.setUp(); vm.startPrank(alice); - currentPool = SuperfluidPool(address(superToken.createPool(alice, poolConfig))); - _addAccount(address(currentPool)); + freePool = SuperfluidPool(address(superToken.createPool(alice, poolConfig))); + _addAccount(address(freePool)); vm.stopPrank(); (liquidationPeriod,) = sf.governance.getPPPConfig(sf.host, superToken); } + function _getMembers(uint8 length) internal view returns (address[] memory) { + if (length > TEST_ACCOUNTS.length - 2) revert("Too many members"); + address[] memory members = new address[](length); + for (uint8 i = 0; i < length; ++i) { + // do not use Admin and Alice + members[i] = TEST_ACCOUNTS[i + 2]; + } + return members; + } + /*////////////////////////////////////////////////////////////////////////// GDA Integration Tests //////////////////////////////////////////////////////////////////////////*/ @@ -82,9 +93,11 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste sf.gda.poolSettleClaim(superToken, claimRecipient, amount); } - function testProxiableUUIDIsExpectedValue() public { + function testProxiableUUIDIsExpectedValue(PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); assertEq( - currentPool.proxiableUUID(), keccak256("org.superfluid-finance.contracts.SuperfluidPool.implementation") + SuperfluidPool(address(pool)).proxiableUUID(), + keccak256("org.superfluid-finance.contracts.SuperfluidPool.implementation") ); } @@ -93,15 +106,16 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste assertEq(isPatricianPeriod, true); } - function testNegativeBalanceIsPatricianPeriodNowIsTrue() public { + function testNegativeBalanceIsPatricianPeriodNowIsTrue(PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); uint256 balance = superToken.balanceOf(alice); int96 flowRate = balance.toInt256().toInt96() / type(int32).max; int96 requestedDistributionFlowRate = int96(flowRate); - _helperConnectPool(bob, superToken, currentPool); - _helperUpdateMemberUnits(currentPool, alice, bob, 1); + _helperConnectPool(bob, superToken, pool); + _helperUpdateMemberUnits(pool, alice, bob, 1); - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedDistributionFlowRate); + _helperDistributeFlow(superToken, alice, alice, pool, requestedDistributionFlowRate); _helperWarpToCritical(superToken, alice, 1); @@ -109,18 +123,19 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste assertEq(isPatricianPeriod, true); } - function testNegativeBalanceIsPatricianPeriodNowIsFalse() public { + function testNegativeBalanceIsPatricianPeriodNowIsFalse(PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); uint256 balance = superToken.balanceOf(alice); int96 flowRate = balance.toInt256().toInt96() / type(int32).max; int96 requestedDistributionFlowRate = int96(flowRate); - _helperConnectPool(bob, superToken, currentPool); - _helperUpdateMemberUnits(currentPool, alice, bob, 1); + _helperConnectPool(bob, superToken, pool); + _helperUpdateMemberUnits(pool, alice, bob, 1); (int96 actualDistributionFlowRate,) = - sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, currentPool, requestedDistributionFlowRate); + sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, pool, requestedDistributionFlowRate); - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedDistributionFlowRate); + _helperDistributeFlow(superToken, alice, alice, pool, requestedDistributionFlowRate); if (actualDistributionFlowRate > 0) { _helperWarpToInsolvency(superToken, alice, liquidationPeriod, 1); @@ -130,7 +145,8 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste assertEq(isPatricianPeriod, false); } - function testNegativeBalanceIsPatricianPeriodNowIsFalseWithZeroDeposit() public { + function testNegativeBalanceIsPatricianPeriodNowIsFalseWithZeroDeposit(PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); uint256 aliceBalance = superToken.balanceOf(alice); int96 flowRate = aliceBalance.toInt256().toInt96() / type(int32).max; int96 requestedDistributionFlowRate = int96(flowRate); @@ -139,19 +155,19 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste sf.governance.setRewardAddress(sf.host, ISuperfluidToken(address(0)), alice); vm.stopPrank(); - _helperConnectPool(bob, superToken, currentPool); - _helperUpdateMemberUnits(currentPool, alice, bob, 1); + _helperConnectPool(bob, superToken, pool); + _helperUpdateMemberUnits(pool, alice, bob, 1); (int256 aliceRTB, uint256 deposit,,) = superToken.realtimeBalanceOfNow(alice); - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedDistributionFlowRate); - int96 fr = sf.gda.getFlowRate(superToken, alice, currentPool); + _helperDistributeFlow(superToken, alice, alice, pool, requestedDistributionFlowRate); + int96 fr = sf.gda.getFlowRate(superToken, alice, pool); vm.warp(block.timestamp + (INIT_SUPER_TOKEN_BALANCE / uint256(uint96(fr))) + 1); (aliceRTB, deposit,,) = superToken.realtimeBalanceOfNow(alice); - _helperDistributeFlow(superToken, bob, alice, currentPool, 0); + _helperDistributeFlow(superToken, bob, alice, pool, 0); (bool isPatricianPeriod,) = sf.gda.isPatricianPeriodNow(superToken, alice); assertEq(isPatricianPeriod, false, "false patrician period"); @@ -161,29 +177,33 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste _helperCreatePool(superToken, alice, alice, useForwarder, config); } - function testRevertConnectPoolByNonHost(address notHost) public { + function testRevertConnectPoolByNonHost(address notHost, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(notHost != address(sf.host)); vm.startPrank(notHost); vm.expectRevert("unauthorized host"); - sf.gda.connectPool(currentPool, "0x"); + sf.gda.connectPool(pool, "0x"); vm.stopPrank(); } - function testRevertNonHostDisconnectPool(address notHost) public { + function testRevertNonHostDisconnectPool(address notHost, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(notHost != address(sf.host)); vm.startPrank(notHost); vm.expectRevert("unauthorized host"); - sf.gda.disconnectPool(currentPool, "0x"); + sf.gda.disconnectPool(pool, "0x"); vm.stopPrank(); } - function testConnectPool(address caller, bool useForwarder) public { - _helperConnectPool(caller, superToken, currentPool, useForwarder); + function testConnectPool(address caller, bool useForwarder, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, caller, alice, useForwarder, config); + _helperConnectPool(caller, superToken, pool, useForwarder); } - function testDisconnectPool(address caller, bool useForwarder) public { - _helperConnectPool(caller, superToken, currentPool, useForwarder); - _helperDisconnectPool(caller, superToken, currentPool, useForwarder); + function testDisconnectPool(address caller, bool useForwarder, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, caller, alice, useForwarder, config); + _helperConnectPool(caller, superToken, pool, useForwarder); + _helperDisconnectPool(caller, superToken, pool, useForwarder); } function testRevertDistributeFlowToNonPool(int96 requestedFlowRate) public { @@ -196,10 +216,7 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste } function testRevertDistributeFromAnyAddressWhenNotAllowed(bool useForwarder) public { - PoolConfig memory config = PoolConfig({ - transferabilityForUnitsOwner: true, - distributionFromAnyAddress: false - }); + PoolConfig memory config = PoolConfig({ transferabilityForUnitsOwner: true, distributionFromAnyAddress: false }); ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, useForwarder, config); vm.expectRevert(IGeneralDistributionAgreementV1.GDA_DISTRIBUTE_FROM_ANY_ADDRESS_NOT_ALLOWED.selector); @@ -209,10 +226,7 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste } function testRevertDistributeFlowFromAnyAddressWhenNotAllowed(bool useForwarder) public { - PoolConfig memory config = PoolConfig({ - transferabilityForUnitsOwner: true, - distributionFromAnyAddress: false - }); + PoolConfig memory config = PoolConfig({ transferabilityForUnitsOwner: true, distributionFromAnyAddress: false }); ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, useForwarder, config); vm.expectRevert(IGeneralDistributionAgreementV1.GDA_DISTRIBUTE_FROM_ANY_ADDRESS_NOT_ALLOWED.selector); @@ -221,10 +235,11 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.stopPrank(); } - function testRevertIfNotAdminUpdatesMemberUnitsViaGDA() public { + function testRevertIfNotAdminUpdatesMemberUnitsViaGDA(bool useForwarder, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, useForwarder, config); vm.startPrank(bob); vm.expectRevert(IGeneralDistributionAgreementV1.GDA_NOT_POOL_ADMIN.selector); - superToken.updateMemberUnits(currentPool, bob, 69); + superToken.updateMemberUnits(pool, bob, 69); vm.stopPrank(); } @@ -232,16 +247,17 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.assume(caller != alice); vm.startPrank(caller); vm.expectRevert(ISuperfluidPool.SUPERFLUID_POOL_NOT_POOL_ADMIN_OR_GDA.selector); - currentPool.updateMemberUnits(caller, 69); + freePool.updateMemberUnits(caller, 69); vm.stopPrank(); } - function testRevertDistributeFlowWithNegativeFlowRate(int96 requestedFlowRate) public { + function testRevertDistributeFlowWithNegativeFlowRate(int96 requestedFlowRate, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(requestedFlowRate < 0); vm.startPrank(alice); vm.expectRevert(IGeneralDistributionAgreementV1.GDA_NO_NEGATIVE_FLOW_RATE.selector); - superToken.distributeFlow(alice, currentPool, requestedFlowRate); + superToken.distributeFlow(alice, pool, requestedFlowRate); vm.stopPrank(); } @@ -255,6 +271,7 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste } function testRevertDistributeForOthers(address signer, uint256 requestedAmount) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, poolConfig); vm.assume(requestedAmount < uint256(type(uint128).max)); vm.assume(signer != alice); @@ -262,13 +279,14 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.expectRevert(IGeneralDistributionAgreementV1.GDA_DISTRIBUTE_FOR_OTHERS_NOT_ALLOWED.selector); sf.host.callAgreement( sf.gda, - abi.encodeCall(sf.gda.distribute, (superToken, alice, currentPool, requestedAmount, new bytes(0))), + abi.encodeCall(sf.gda.distribute, (superToken, alice, pool, requestedAmount, new bytes(0))), new bytes(0) ); vm.stopPrank(); } function testRevertDistributeFlowForOthers(address signer, int32 requestedFlowRate) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, poolConfig); vm.assume(requestedFlowRate > 0); vm.assume(signer != alice); @@ -276,79 +294,88 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.expectRevert(IGeneralDistributionAgreementV1.GDA_DISTRIBUTE_FOR_OTHERS_NOT_ALLOWED.selector); sf.host.callAgreement( sf.gda, - abi.encodeCall(sf.gda.distributeFlow, (superToken, alice, currentPool, requestedFlowRate, new bytes(0))), + abi.encodeCall(sf.gda.distributeFlow, (superToken, alice, pool, requestedFlowRate, new bytes(0))), new bytes(0) ); vm.stopPrank(); } - function testRevertDistributeFlowInsufficientBalance() public { + function testRevertDistributeFlowInsufficientBalance(PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); uint256 balance = superToken.balanceOf(alice); balance /= 4 hours; int96 tooBigFlowRate = int96(int256(balance)) + 1; - _helperConnectPool(bob, superToken, currentPool); + _helperConnectPool(bob, superToken, pool); - _helperUpdateMemberUnits(currentPool, alice, bob, 1); + _helperUpdateMemberUnits(pool, alice, bob, 1); vm.startPrank(alice); vm.expectRevert(IGeneralDistributionAgreementV1.GDA_INSUFFICIENT_BALANCE.selector); sf.host.callAgreement( sf.gda, - abi.encodeCall(sf.gda.distributeFlow, (superToken, alice, currentPool, tooBigFlowRate, new bytes(0))), + abi.encodeCall(sf.gda.distributeFlow, (superToken, alice, pool, tooBigFlowRate, new bytes(0))), new bytes(0) ); vm.stopPrank(); } - function testRevertLiquidateNonCriticalDistributor(int32 flowRate, int96 units) public { + function testRevertLiquidateNonCriticalDistributor(int32 flowRate, int96 units, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(flowRate > 0); - _helperConnectPool(bob, superToken, currentPool); + _helperConnectPool(bob, superToken, pool); - _helperUpdateMemberUnits(currentPool, alice, bob, uint96(units)); + _helperUpdateMemberUnits(pool, alice, bob, uint96(units)); - _helperDistributeFlow(superToken, alice, alice, currentPool, flowRate); + _helperDistributeFlow(superToken, alice, alice, pool, flowRate); vm.startPrank(bob); vm.expectRevert(IGeneralDistributionAgreementV1.GDA_NON_CRITICAL_SENDER.selector); - superToken.distributeFlow(alice, currentPool, 0); + superToken.distributeFlow(alice, pool, 0); vm.stopPrank(); } - function testRevertDistributeInsufficientBalance() public { + function testRevertDistributeInsufficientBalance(PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); uint256 balance = superToken.balanceOf(alice); - _helperConnectPool(bob, superToken, currentPool); + _helperConnectPool(bob, superToken, pool); vm.startPrank(alice); - sf.gdaV1Forwarder.updateMemberUnits(currentPool, bob, 1, new bytes(0)); + sf.gdaV1Forwarder.updateMemberUnits(pool, bob, 1, new bytes(0)); vm.stopPrank(); vm.startPrank(alice); vm.expectRevert(IGeneralDistributionAgreementV1.GDA_INSUFFICIENT_BALANCE.selector); sf.host.callAgreement( sf.gda, - abi.encodeCall(sf.gda.distribute, (superToken, alice, currentPool, balance + 1, new bytes(0))), + abi.encodeCall(sf.gda.distribute, (superToken, alice, pool, balance + 1, new bytes(0))), new bytes(0) ); vm.stopPrank(); } - function testRevertPoolOperatorConnectMember(address notOperator, address member, bool doConnect, uint32 time) - public - { + function testRevertPoolOperatorConnectMember( + address notOperator, + address member, + bool doConnect, + uint32 time, + PoolConfig memory config + ) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(notOperator != address(sf.gda)); vm.startPrank(notOperator); vm.expectRevert(ISuperfluidPool.SUPERFLUID_POOL_NOT_GDA.selector); - currentPool.operatorConnectMember(member, doConnect, time); + SuperfluidPool(address(pool)).operatorConnectMember(member, doConnect, time); vm.stopPrank(); } - function testRevertPoolUpdateMemberThatIsPool(uint128 units) public { + function testRevertPoolUpdateMemberThatIsPool(uint128 units, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(units < uint128(type(int128).max)); vm.expectRevert(ISuperfluidPool.SUPERFLUID_POOL_NO_POOL_MEMBERS.selector); vm.startPrank(alice); - currentPool.updateMemberUnits(address(currentPool), units); + pool.updateMemberUnits(address(pool), units); vm.stopPrank(); } @@ -361,11 +388,13 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste uint64 distributionFlowRate, uint32 minDepositMultiplier, address member, - FoundrySuperfluidTester._StackVars_UseBools memory useBools_ + FoundrySuperfluidTester._StackVars_UseBools memory useBools_, + PoolConfig memory config ) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(distributionFlowRate < minDepositMultiplier); vm.assume(distributionFlowRate > 0); - vm.assume(member != address(currentPool)); + vm.assume(member != address(pool)); vm.assume(member != address(0)); _addAccount(member); @@ -375,9 +404,9 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste sf.governance.setSuperTokenMinimumDeposit(sf.host, superToken, minimumDeposit); vm.stopPrank(); - _helperConnectPool(member, superToken, currentPool); - _helperUpdateMemberUnits(currentPool, alice, member, 1, useBools_); - _helperDistributeFlow(superToken, alice, alice, currentPool, int96(int64(distributionFlowRate))); + _helperConnectPool(member, superToken, pool); + _helperUpdateMemberUnits(pool, alice, member, 1, useBools_); + _helperDistributeFlow(superToken, alice, alice, pool, int96(int64(distributionFlowRate))); (, uint256 buffer,,) = superToken.realtimeBalanceOfNow(alice); assertEq(buffer, minimumDeposit, "GDAv1.t: Min buffer should be used"); } @@ -386,12 +415,14 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste int32 distributionFlowRate, uint32 minDepositMultiplier, address member, - FoundrySuperfluidTester._StackVars_UseBools memory useBools_ + FoundrySuperfluidTester._StackVars_UseBools memory useBools_, + PoolConfig memory config ) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); vm.assume(uint32(distributionFlowRate) >= minDepositMultiplier); vm.assume(distributionFlowRate > 0); vm.assume(member != address(0)); - vm.assume(member != address(currentPool)); + vm.assume(member != address(freePool)); _addAccount(member); @@ -401,9 +432,9 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste sf.governance.setSuperTokenMinimumDeposit(sf.host, superToken, minimumDeposit); vm.stopPrank(); - _helperConnectPool(member, superToken, currentPool); - _helperUpdateMemberUnits(currentPool, alice, member, 1, useBools_); - _helperDistributeFlow(superToken, alice, alice, currentPool, int96(distributionFlowRate)); + _helperConnectPool(member, superToken, pool); + _helperUpdateMemberUnits(pool, alice, member, 1, useBools_); + _helperDistributeFlow(superToken, alice, alice, pool, int96(distributionFlowRate)); (, uint256 buffer,,) = superToken.realtimeBalanceOfNow(alice); assertTrue(buffer >= minimumDeposit, "GDAv1.t: Buffer should be >= minDeposit"); } @@ -411,20 +442,23 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste function testDistributeFlowToConnectedMemberSendingToCFA( int32 flowRate, uint64 units, - FoundrySuperfluidTester._StackVars_UseBools memory useBools_ + FoundrySuperfluidTester._StackVars_UseBools memory useBools_, + PoolConfig memory config ) public { vm.assume(flowRate > 0); - // alice creates currentPool in setUp() + + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + int96 requestedDistributionFlowRate = int96(flowRate); uint128 memberUnits = uint128(units); - _helperUpdateMemberUnits(currentPool, alice, bob, memberUnits, useBools_); + _helperUpdateMemberUnits(pool, alice, bob, memberUnits, useBools_); - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedDistributionFlowRate); + _helperDistributeFlow(superToken, alice, alice, pool, requestedDistributionFlowRate); - // bob sends a flow of 1 to carol - _helperConnectPool(bob, superToken, currentPool); + _helperConnectPool(bob, superToken, pool); + // bob sends a flow of 1 to alice vm.startPrank(bob); superToken.createFlow(alice, requestedDistributionFlowRate * 10); vm.stopPrank(); @@ -440,181 +474,217 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste ); } - function testDistributeToEmptyPool(uint64 distributionAmount, bool useForwarder) public { - _helperDistributeViaGDA(superToken, alice, alice, currentPool, distributionAmount, useForwarder); + function testDistributeToEmptyPool(uint64 distributionAmount, bool useForwarder, PoolConfig memory config) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, useForwarder, config); + _helperDistributeViaGDA(superToken, alice, alice, pool, distributionAmount, useForwarder); } - function testDistributeFlowToEmptyPool(int32 flowRate, bool useForwarder) public { + function testDistributeFlowToEmptyPool(int32 flowRate, bool useForwarder, PoolConfig memory config) public { vm.assume(flowRate >= 0); - _helperDistributeFlow(superToken, alice, alice, currentPool, flowRate, useForwarder); - assertEq(sf.gda.getFlowRate(superToken, alice, currentPool), 0, "GDAv1.t: distributionFlowRate should be 0"); + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, useForwarder, config); + _helperDistributeFlow(superToken, alice, alice, pool, flowRate, useForwarder); + assertEq(sf.gda.getFlowRate(superToken, alice, pool), 0, "GDAv1.t: distributionFlowRate should be 0"); } - function testDistributeFlowCriticalLiquidation(uint64 units, _StackVars_UseBools memory useBools_) public { + function testDistributeFlowCriticalLiquidation( + uint64 units, + _StackVars_UseBools memory useBools_, + PoolConfig memory config + ) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + uint256 balance = superToken.balanceOf(alice); int96 flowRate = balance.toInt256().toInt96() / type(int32).max; int96 requestedDistributionFlowRate = int96(flowRate); uint128 memberUnits = uint128(units); - _helperConnectPool(bob, superToken, currentPool); - _helperUpdateMemberUnits(currentPool, alice, bob, memberUnits, useBools_); + _helperConnectPool(bob, superToken, pool); + _helperUpdateMemberUnits(pool, alice, bob, memberUnits, useBools_); (int96 actualDistributionFlowRate,) = - sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, currentPool, requestedDistributionFlowRate); + sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, pool, requestedDistributionFlowRate); - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedDistributionFlowRate); + _helperDistributeFlow(superToken, alice, alice, pool, requestedDistributionFlowRate); if (actualDistributionFlowRate > 0) { _helperWarpToCritical(superToken, alice, 1); - _helperDistributeFlow(superToken, bob, alice, currentPool, 0); + _helperDistributeFlow(superToken, bob, alice, pool, 0); } } - function testDistributeFlowInsolventLiquidation(uint64 units, _StackVars_UseBools memory useBools_) public { + function testDistributeFlowInsolventLiquidation( + uint64 units, + _StackVars_UseBools memory useBools_, + PoolConfig memory config + ) public { + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + uint256 balance = superToken.balanceOf(alice); int96 flowRate = balance.toInt256().toInt96() / type(int32).max; int96 requestedDistributionFlowRate = int96(flowRate); uint128 memberUnits = uint128(units); - _helperConnectPool(bob, superToken, currentPool); - _helperUpdateMemberUnits(currentPool, alice, bob, memberUnits, useBools_); - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedDistributionFlowRate); + _helperConnectPool(bob, superToken, pool); + _helperUpdateMemberUnits(pool, alice, bob, memberUnits, useBools_); + _helperDistributeFlow(superToken, alice, alice, pool, requestedDistributionFlowRate); (int96 actualDistributionFlowRate,) = - sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, currentPool, requestedDistributionFlowRate); + sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, pool, requestedDistributionFlowRate); - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedDistributionFlowRate); + _helperDistributeFlow(superToken, alice, alice, pool, requestedDistributionFlowRate); if (actualDistributionFlowRate > 0) { _helperWarpToInsolvency(superToken, alice, liquidationPeriod, 1); - _helperDistributeFlow(superToken, bob, alice, currentPool, 0); + _helperDistributeFlow(superToken, bob, alice, pool, 0); } } function testDistributeToDisconnectedMembers( - UpdateMemberData[5] memory members, + uint64[5] memory memberUnits, uint256 distributionAmount, - _StackVars_UseBools memory useBools_ + _StackVars_UseBools memory useBools_, + PoolConfig memory config ) public { address distributor = alice; uint256 distributorBalance = superToken.balanceOf(distributor); - vm.assume(members.length > 0); vm.assume(distributionAmount < distributorBalance); + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + + address[] memory members = _getMembers(5); + for (uint256 i = 0; i < members.length; ++i) { - if (sf.gda.isPool(superToken, members[i].member) || members[i].member == address(0)) continue; + if (sf.gda.isPool(superToken, members[i]) || members[i] == address(0)) continue; - _helperUpdateMemberUnits(currentPool, alice, members[i].member, members[i].newUnits, useBools_); + _helperUpdateMemberUnits(pool, alice, members[i], memberUnits[i], useBools_); } - _helperDistributeViaGDA(superToken, alice, alice, currentPool, distributionAmount, useBools_.useForwarder); + _helperDistributeViaGDA(superToken, alice, alice, pool, distributionAmount, useBools_.useForwarder); } function testDistributeToConnectedMembers( - UpdateMemberData[5] memory members, + uint64[5] memory memberUnits, uint256 distributionAmount, - _StackVars_UseBools memory useBools_ + _StackVars_UseBools memory useBools_, + PoolConfig memory config ) public { address distributor = alice; uint256 distributorBalance = superToken.balanceOf(distributor); - vm.assume(members.length > 0); vm.assume(distributionAmount < distributorBalance); + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + + address[] memory members = _getMembers(5); + for (uint256 i = 0; i < members.length; ++i) { - if (sf.gda.isPool(superToken, members[i].member) || members[i].member == address(0)) continue; + if (sf.gda.isPool(superToken, members[i]) || members[i] == address(0)) continue; - _helperConnectPool(members[i].member, superToken, currentPool, useBools_.useForwarder); - _helperUpdateMemberUnits(currentPool, alice, members[i].member, members[i].newUnits, useBools_); - _addAccount(members[i].member); + _helperConnectPool(members[i], superToken, pool, useBools_.useForwarder); + _helperUpdateMemberUnits(pool, alice, members[i], memberUnits[i], useBools_); + _addAccount(members[i]); } - _helperDistributeViaGDA(superToken, alice, alice, currentPool, distributionAmount, useBools_.useForwarder); + _helperDistributeViaGDA(superToken, alice, alice, pool, distributionAmount, useBools_.useForwarder); } function testDistributeFlowToConnectedMembers( - UpdateMemberData[5] memory members, + uint64[5] memory memberUnits, int32 flowRate, - _StackVars_UseBools memory useBools_ + _StackVars_UseBools memory useBools_, + PoolConfig memory config ) public { - vm.assume(members.length > 0); vm.assume(flowRate > 0); + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + + address[] memory members = _getMembers(5); + for (uint256 i = 0; i < members.length; ++i) { - if (sf.gda.isPool(superToken, members[i].member) || members[i].member == address(0)) continue; + if (sf.gda.isPool(superToken, members[i]) || members[i] == address(0)) continue; - _helperConnectPool(members[i].member, superToken, currentPool, useBools_.useForwarder); - _helperUpdateMemberUnits(currentPool, alice, members[i].member, members[i].newUnits, useBools_); - _addAccount(members[i].member); + _helperConnectPool(members[i], superToken, pool, useBools_.useForwarder); + _helperUpdateMemberUnits(pool, alice, members[i], memberUnits[i], useBools_); + _addAccount(members[i]); } - _helperDistributeFlow(superToken, alice, alice, currentPool, 100, useBools_.useForwarder); + _helperDistributeFlow(superToken, alice, alice, pool, 100, useBools_.useForwarder); int96 poolAdjustmentFlowRate = useBools_.useForwarder - ? sf.gdaV1Forwarder.getPoolAdjustmentFlowRate(address(currentPool)) - : sf.gda.getPoolAdjustmentFlowRate(address(currentPool)); + ? sf.gdaV1Forwarder.getPoolAdjustmentFlowRate(address(pool)) + : sf.gda.getPoolAdjustmentFlowRate(address(pool)); assertEq(poolAdjustmentFlowRate, 0, "GDAv1.t: Pool adjustment rate is non-zero"); } function testDistributeFlowToUnconnectedMembers( - UpdateMemberData[5] memory members, + uint64[5] memory memberUnits, int32 flowRate, uint16 warpTime, - _StackVars_UseBools memory useBools_ + _StackVars_UseBools memory useBools_, + PoolConfig memory config ) public { vm.assume(flowRate > 0); - vm.assume(members.length > 0); - for (uint256 i = 0; i < members.length; ++i) { - if (sf.gda.isPool(superToken, members[i].member) || members[i].member == address(0)) continue; - _helperUpdateMemberUnits(currentPool, alice, members[i].member, members[i].newUnits, useBools_); + ISuperfluidPool pool; + { + pool = _helperCreatePool(superToken, alice, alice, false, config); } - int96 requestedFlowRate = flowRate; - _helperDistributeFlow(superToken, alice, alice, currentPool, requestedFlowRate, useBools_.useForwarder); - (int96 actualDistributionFlowRate,) = - sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, currentPool, requestedFlowRate); + address[] memory members = _getMembers(5); - vm.warp(block.timestamp + warpTime); + for (uint256 i = 0; i < members.length; ++i) { + if (sf.gda.isPool(superToken, members[i]) || members[i] == address(0)) continue; + _helperUpdateMemberUnits(pool, alice, members[i], memberUnits[i], useBools_); + } + + int96 actualDistributionFlowRate; + { + int96 requestedFlowRate = flowRate; + _helperDistributeFlow(superToken, alice, alice, pool, requestedFlowRate, useBools_.useForwarder); + (actualDistributionFlowRate,) = + sf.gda.estimateFlowDistributionActualFlowRate(superToken, alice, pool, requestedFlowRate); - uint128 totalUnits = currentPool.getTotalUnits(); + vm.warp(block.timestamp + warpTime); + } + uint128 totalUnits = pool.getTotalUnits(); for (uint256 i; i < members.length; ++i) { - address member = members[i].member; - if (member != address(0)) { + if (members[i] != address(0)) { // @note we test realtimeBalanceOfNow here as well - (int256 memberRTB,,) = sf.gda.realtimeBalanceOf(superToken, member, block.timestamp); - (int256 rtbNow,,,) = sf.gda.realtimeBalanceOfNow(superToken, member); + (int256 memberRTB,,) = sf.gda.realtimeBalanceOf(superToken, members[i], block.timestamp); + (int256 rtbNow,,,) = sf.gda.realtimeBalanceOfNow(superToken, members[i]); assertEq(memberRTB, rtbNow, "testDistributeFlowToUnconnectedMembers: rtb != rtbNow"); assertEq( - currentPool.getTotalDisconnectedFlowRate(), + pool.getTotalDisconnectedFlowRate(), actualDistributionFlowRate, "testDistributeFlowToUnconnectedMembers: pendingDistributionFlowRate != actualDistributionFlowRate" ); - (int256 memberClaimable,) = currentPool.getClaimableNow(member); + (int256 memberClaimable,) = pool.getClaimableNow(members[i]); + assertEq( memberClaimable, totalUnits > 0 - ? (actualDistributionFlowRate * int96(int256(uint256(warpTime)))) - * int96(uint96(members[i].newUnits)) / uint256(totalUnits).toInt256() + ? (actualDistributionFlowRate * int96(int256(uint256(warpTime)))) * int96(uint96(memberUnits[i])) + / uint256(totalUnits).toInt256() : int256(0), "testDistributeFlowToUnconnectedMembers: memberClaimable != (actualDistributionFlowRate * warpTime) / totalUnits" ); assertEq(memberRTB, 0, "testDistributeFlowToUnconnectedMembers: memberRTB != 0"); - vm.startPrank(member); + + vm.startPrank(members[i]); if (useBools_.useGDA) { if (useBools_.useForwarder) { - sf.gdaV1Forwarder.claimAll(currentPool, member, new bytes(0)); + sf.gdaV1Forwarder.claimAll(pool, members[i], new bytes(0)); } else { - superToken.claimAll(currentPool, member); + superToken.claimAll(pool, members[i]); } } else { - currentPool.claimAll(); + pool.claimAll(); } vm.stopPrank(); - (memberRTB,,) = sf.gda.realtimeBalanceOf(superToken, member, block.timestamp); + (memberRTB,,) = sf.gda.realtimeBalanceOf(superToken, members[i], block.timestamp); assertEq( memberRTB, memberClaimable, "testDistributeFlowToUnconnectedMembers: memberRTB != memberClaimable" ); @@ -624,29 +694,41 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste // Pool ERC20 functions - function testApproveOnly(address owner, address spender, uint256 amount) public { + function testApproveOnly(address owner, address spender, uint256 amount, PoolConfig memory config) public { vm.assume(owner != address(0)); vm.assume(spender != address(0)); - _helperSuperfluidPoolApprove(currentPool, owner, spender, amount); + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + + _helperSuperfluidPoolApprove(pool, owner, spender, amount); } - function testIncreaseAllowance(address owner, address spender, uint256 addedValue) public { + function testIncreaseAllowance(address owner, address spender, uint256 addedValue, PoolConfig memory config) + public + { vm.assume(owner != address(0)); vm.assume(spender != address(0)); - _helperSuperfluidPoolIncreaseAllowance(currentPool, owner, spender, addedValue); + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + + _helperSuperfluidPoolIncreaseAllowance(pool, owner, spender, addedValue); } - function testDecreaseAllowance(address owner, address spender, uint256 addedValue, uint256 subtractedValue) - public - { + function testDecreaseAllowance( + address owner, + address spender, + uint256 addedValue, + uint256 subtractedValue, + PoolConfig memory config + ) public { vm.assume(owner != address(0)); vm.assume(spender != address(0)); vm.assume(addedValue >= subtractedValue); - _helperSuperfluidPoolIncreaseAllowance(currentPool, owner, spender, addedValue); - _helperSuperfluidPoolDecreaseAllowance(currentPool, owner, spender, subtractedValue); + ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, false, config); + + _helperSuperfluidPoolIncreaseAllowance(pool, owner, spender, addedValue); + _helperSuperfluidPoolDecreaseAllowance(pool, owner, spender, subtractedValue); } function testRevertIfUnitsTransferReceiverIsPool(address from, address to, int96 unitsAmount, int128 transferAmount) @@ -659,22 +741,19 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.assume(to != address(0)); vm.assume(from != to); vm.assume(transferAmount <= unitsAmount); - _helperUpdateMemberUnits(currentPool, alice, from, uint128(int128(unitsAmount))); + _helperUpdateMemberUnits(freePool, alice, from, uint128(int128(unitsAmount))); vm.startPrank(from); vm.expectRevert(ISuperfluidPool.SUPERFLUID_POOL_NO_POOL_MEMBERS.selector); - currentPool.transfer(address(currentPool), uint256(uint128(transferAmount))); + freePool.transfer(address(freePool), uint256(uint128(transferAmount))); vm.stopPrank(); } function testRevertIfTransferNotAllowed(bool useForwarder) public { - PoolConfig memory config = PoolConfig({ - transferabilityForUnitsOwner: false, - distributionFromAnyAddress: true - }); + PoolConfig memory config = PoolConfig({ transferabilityForUnitsOwner: false, distributionFromAnyAddress: true }); ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, useForwarder, config); - _helperUpdateMemberUnits(currentPool, alice, bob, 1000); + _helperUpdateMemberUnits(pool, alice, bob, 1000); vm.startPrank(bob); vm.expectRevert(ISuperfluidPool.SUPERFLUID_POOL_TRANSFER_UNITS_NOT_ALLOWED.selector); @@ -683,13 +762,10 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste } function testRevertIfTransferFromNotAllowed(bool useForwarder) public { - PoolConfig memory config = PoolConfig({ - transferabilityForUnitsOwner: false, - distributionFromAnyAddress: true - }); + PoolConfig memory config = PoolConfig({ transferabilityForUnitsOwner: false, distributionFromAnyAddress: true }); ISuperfluidPool pool = _helperCreatePool(superToken, alice, alice, useForwarder, config); - _helperUpdateMemberUnits(currentPool, alice, bob, 1000); + _helperUpdateMemberUnits(freePool, alice, bob, 1000); vm.startPrank(bob); pool.approve(carol, 1000); @@ -715,9 +791,9 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.assume(to != address(0)); vm.assume(from != to); vm.assume(transferAmount <= unitsAmount); - _helperUpdateMemberUnits(currentPool, alice, from, uint128(int128(unitsAmount)), useBools_); + _helperUpdateMemberUnits(freePool, alice, from, uint128(int128(unitsAmount)), useBools_); - _helperSuperfluidPoolUnitsTransfer(currentPool, from, to, uint256(uint128(transferAmount))); + _helperSuperfluidPoolUnitsTransfer(freePool, from, to, uint256(uint128(transferAmount))); } function testApproveAndTransferFrom( @@ -730,9 +806,9 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.assume(spender != address(0)); vm.assume(owner != address(0)); vm.assume(spender != owner); - _helperUpdateMemberUnits(currentPool, alice, owner, uint128(int128(transferAmount)), useBools_); - _helperSuperfluidPoolApprove(currentPool, owner, spender, uint256(uint128(transferAmount))); - _helperSuperfluidPoolUnitsTransferFrom(currentPool, spender, owner, spender, uint256(uint128(transferAmount))); + _helperUpdateMemberUnits(freePool, alice, owner, uint128(int128(transferAmount)), useBools_); + _helperSuperfluidPoolApprove(freePool, owner, spender, uint256(uint128(transferAmount))); + _helperSuperfluidPoolUnitsTransferFrom(freePool, spender, owner, spender, uint256(uint128(transferAmount))); } function testIncreaseAllowanceAndTransferFrom( @@ -745,9 +821,9 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste vm.assume(spender != address(0)); vm.assume(owner != address(0)); vm.assume(spender != owner); - _helperUpdateMemberUnits(currentPool, alice, owner, uint128(int128(transferAmount)), useBools_); - _helperSuperfluidPoolIncreaseAllowance(currentPool, owner, spender, uint256(uint128(transferAmount))); - _helperSuperfluidPoolUnitsTransferFrom(currentPool, spender, owner, spender, uint256(uint128(transferAmount))); + _helperUpdateMemberUnits(freePool, alice, owner, uint128(int128(transferAmount)), useBools_); + _helperSuperfluidPoolIncreaseAllowance(freePool, owner, spender, uint256(uint128(transferAmount))); + _helperSuperfluidPoolUnitsTransferFrom(freePool, spender, owner, spender, uint256(uint128(transferAmount))); } /*////////////////////////////////////////////////////////////////////////// @@ -756,7 +832,7 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste struct PoolUpdateStep { uint8 u; // which user - uint8 a; // action types: 0 update units, 1 distribute flow, 2 currentPool connection, 3 currentPool claim for, + uint8 a; // action types: 0 update units, 1 distribute flow, 2 freePool connection, 3 freePool claim for, // 4 distribute uint32 v; // action param uint16 dt; // time delta @@ -781,69 +857,69 @@ contract GeneralDistributionAgreementV1IntegrationTest is FoundrySuperfluidTeste if (action == 0) { emit log_named_string("action", "updateMember"); emit log_named_uint("units", s.v); - _helperUpdateMemberUnits(currentPool, currentPool.admin(), user, s.v, useBools_); + _helperUpdateMemberUnits(freePool, freePool.admin(), user, s.v, useBools_); } else if (action == 1) { emit log_named_string("action", "distributeFlow"); emit log_named_uint("flow rate", s.v); - if (sf.gda.getFlowRate(superToken, user, currentPool) == 0) { + if (sf.gda.getFlowRate(superToken, user, freePool) == 0) { vm.assume(s.v > 0); } - _helperDistributeFlow(superToken, user, user, currentPool, int96(uint96(s.v)), useBools_.useForwarder); + _helperDistributeFlow(superToken, user, user, freePool, int96(uint96(s.v)), useBools_.useForwarder); } else if (action == 2) { address u4 = TEST_ACCOUNTS[1 + (s.v % N_MEMBERS)]; emit log_named_string("action", "claimAll"); emit log_named_address("claim for", u4); vm.startPrank(user); - assert(currentPool.claimAll(u4)); + assert(freePool.claimAll(u4)); vm.stopPrank(); } else if (action == 3) { bool doConnect = s.v % 2 == 0 ? false : true; emit log_named_string("action", "doConnectPool"); emit log_named_string("doConnect", doConnect ? "true" : "false"); doConnect - ? _helperConnectPool(user, superToken, currentPool, useBools_.useForwarder) - : _helperDisconnectPool(user, superToken, currentPool, useBools_.useForwarder); + ? _helperConnectPool(user, superToken, freePool, useBools_.useForwarder) + : _helperDisconnectPool(user, superToken, freePool, useBools_.useForwarder); } else if (action == 4) { emit log_named_string("action", "distribute"); emit log_named_uint("distributionAmount", s.v); - _helperDistributeViaGDA(superToken, user, user, currentPool, uint256(s.v), useBools_.useForwarder); + _helperDistributeViaGDA(superToken, user, user, freePool, uint256(s.v), useBools_.useForwarder); } else { assert(false); } { - (int256 own, int256 fromPools, int256 buffer) = - sf.gda.realtimeBalanceVectorAt(superToken, address(currentPool), block.timestamp); + (int256 rtb, uint256 buffer, uint256 owedBuffer) = + sf.gda.realtimeBalanceOf(superToken, address(freePool), block.timestamp); int96 nr = useBools_.useForwarder - ? sf.gdaV1Forwarder.getNetFlow(superToken, address(currentPool)) - : sf.gda.getNetFlow(superToken, address(currentPool)); - emit log_string("> currentPool before time warp"); - emit log_named_int("own", own); - emit log_named_int("fromPoolsBalance", fromPools); - emit log_named_int("buffer", buffer); - emit log_named_int("currentPool net flow rate", nr); + ? sf.gdaV1Forwarder.getNetFlow(superToken, address(freePool)) + : sf.gda.getNetFlow(superToken, address(freePool)); + emit log_string("> freePool before time warp"); + emit log_named_int("rtb", rtb); + emit log_named_uint("buffer", buffer); + emit log_named_uint("owedBuffer", owedBuffer); + emit log_named_int("freePool net flow rate", nr); } emit log_named_uint("> dt", s.dt); vm.warp(block.timestamp + s.dt); { - (int256 own, int256 fromPools, int256 buffer) = - sf.gda.realtimeBalanceVectorAt(superToken, address(currentPool), block.timestamp); + (int256 rtb, uint256 buffer, uint256 owedBuffer) = + sf.gda.realtimeBalanceOf(superToken, address(freePool), block.timestamp); int96 nr = useBools_.useForwarder - ? sf.gdaV1Forwarder.getNetFlow(superToken, address(currentPool)) - : sf.gda.getNetFlow(superToken, address(currentPool)); - emit log_string("> currentPool before time warp"); - emit log_named_int("own", own); - emit log_named_int("fromPoolsBalance", fromPools); - emit log_named_int("buffer", buffer); - emit log_named_int("currentPool net flow rate", nr); + ? sf.gdaV1Forwarder.getNetFlow(superToken, address(freePool)) + : sf.gda.getNetFlow(superToken, address(freePool)); + emit log_string("> freePool before time warp"); + emit log_named_int("rtb", rtb); + emit log_named_uint("buffer", buffer); + emit log_named_uint("owedBuffer", owedBuffer); + emit log_named_int("freePool net flow rate", nr); } } int96 flowRatesSum; { - int96 poolNetFlowRate = sf.gda.getNetFlow(superToken, address(currentPool)); + int96 poolNetFlowRate = sf.gda.getNetFlow(superToken, address(freePool)); flowRatesSum = flowRatesSum + poolNetFlowRate; } diff --git a/packages/ethereum-contracts/test/foundry/apps/CrossStreamSuperApp.t.sol b/packages/ethereum-contracts/test/foundry/apps/CrossStreamSuperApp.t.sol new file mode 100644 index 0000000000..33a68b8572 --- /dev/null +++ b/packages/ethereum-contracts/test/foundry/apps/CrossStreamSuperApp.t.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: AGPLv3 +pragma solidity 0.8.19; + +import { CrossStreamSuperApp } from "../../../contracts/mocks/CrossStreamSuperApp.sol"; +import { SuperTokenV1Library } from "../../../contracts/apps/SuperTokenV1Library.sol"; +import { ISuperToken } from "../../../contracts/interfaces/superfluid/ISuperfluid.sol"; + +import { FoundrySuperfluidTester } from "../FoundrySuperfluidTester.sol"; + +import "forge-std/Test.sol"; + +using SuperTokenV1Library for ISuperToken; + +contract CrossStreamSuperAppTest is FoundrySuperfluidTester { + CrossStreamSuperApp public superApp; + + constructor() FoundrySuperfluidTester(5) { } + + function setUp() public override { + super.setUp(); + + superApp = new CrossStreamSuperApp(sf.host, bob); + _addAccount(address(superApp)); + } + + function testNoTokensMintedOrBurnedInCrossStreamSuperApp(int96 flowRate, uint64 blockTimestamp) public { + vm.assume(flowRate < 1e14); + // @note due to clipping, there is precision loss, therefore if the flow rate is too low + // tokens will be unrecoverable + vm.assume(flowRate > 2 ** 32 - 1); + int96 initialFlowRate = flowRate; + + // @note transfer tokens from alice to carol so that + // alice has type(uint64).max balance to start + uint256 diff = type(uint88).max - type(uint64).max; + vm.startPrank(alice); + superToken.transfer(carol, diff); + vm.stopPrank(); + + uint256 balance = superToken.balanceOf(alice); + + uint256 amountOfTimeTillZero = balance / uint256(uint96(initialFlowRate)); + vm.assume(blockTimestamp < amountOfTimeTillZero); + + int256 rtbSumStart = _helperGetSuperTokenLiquiditySum(superToken); + + // send an initial deposit to the super app to allow the test to pass + uint256 deposit = sf.cfa.getDepositRequiredForFlowRate(superToken, initialFlowRate); + vm.startPrank(carol); + superToken.transfer(address(superApp), deposit); + vm.stopPrank(); + + // @note We are mainly concerned with _definitionAumGtEqRtbSumInvariant holding true: + // Assert the global invariants at every step. + _assertGlobalInvariants(); + + // create the first flow from alice -> super app -> bob + vm.startPrank(alice); + superToken.createFlow(address(superApp), initialFlowRate); + vm.stopPrank(); + + _assertGlobalInvariants(); + + uint256 bt = block.timestamp; + + vm.warp(bt + blockTimestamp); + + assertEq(initialFlowRate, superToken.getFlowRate(alice, address(superApp))); + + // create the second flow from dan -> super app -> bob + // this first: updates the flow from super app -> bob to equal to the new inflowRate (dan flow rateå) + // then we delete the flow from alice -> super app, super app executes this deletion + vm.startPrank(dan); + int96 updatedFlowRate = initialFlowRate * 2; + superToken.createFlow(address(superApp), updatedFlowRate); + vm.stopPrank(); + + _assertGlobalInvariants(); + + // finally we close the stream from dan => super app and super app => bob + vm.startPrank(dan); + superToken.deleteFlow(dan, address(superApp)); + vm.stopPrank(); + + _assertGlobalInvariants(); + + vm.startPrank(bob); + superToken.deleteFlow(address(superApp), bob); + vm.stopPrank(); + + _assertGlobalInvariants(); + + int256 rtbSumEnd = _helperGetSuperTokenLiquiditySum(superToken); + + assertEq(rtbSumStart, rtbSumEnd, "rtbSumStart != rtbSumEnd"); + } +} diff --git a/packages/ethereum-contracts/test/foundry/gov/SuperfluidGovernanceII.t.sol b/packages/ethereum-contracts/test/foundry/gov/SuperfluidGovernanceII.t.sol index dcdc71f891..6305d82130 100644 --- a/packages/ethereum-contracts/test/foundry/gov/SuperfluidGovernanceII.t.sol +++ b/packages/ethereum-contracts/test/foundry/gov/SuperfluidGovernanceII.t.sol @@ -8,6 +8,7 @@ import { SuperTokenV1Library } from "../../../contracts/apps/SuperTokenV1Library import { ISuperAgreement } from "../../../contracts/interfaces/superfluid/ISuperAgreement.sol"; import { ISuperfluid } from "../../../contracts/interfaces/superfluid/ISuperfluid.sol"; import { AgreementMock } from "../../../contracts/mocks/AgreementMock.sol"; +import { SuperfluidPool } from "../../../contracts/agreements/gdav1/SuperfluidPool.sol"; contract SuperfluidGovernanceIntegrationTest is FoundrySuperfluidTester { using SuperTokenV1Library for SuperToken; @@ -26,6 +27,7 @@ contract SuperfluidGovernanceIntegrationTest is FoundrySuperfluidTester { function testRevertChangeSuperTokenAdminWhenCallerIsNotNotGovOwner(address newAdmin) public { vm.assume(newAdmin != address(0)); + vm.assume(newAdmin != sf.governance.owner()); vm.startPrank(newAdmin); vm.expectRevert(); @@ -33,7 +35,7 @@ contract SuperfluidGovernanceIntegrationTest is FoundrySuperfluidTester { vm.stopPrank(); } - function testRevertWhenHostIsNotAdmin(address initialAdmin) public { + function testRevertChangeSuperTokenAdminWhenHostIsNotAdmin(address initialAdmin) public { vm.assume(initialAdmin != address(0)); vm.assume(initialAdmin != address(sf.host)); @@ -47,6 +49,45 @@ contract SuperfluidGovernanceIntegrationTest is FoundrySuperfluidTester { vm.stopPrank(); } + function testRevertUpgradePoolBeaconLogicWhenNotOwner() public { + SuperfluidPool newPoolLogic = new SuperfluidPool(sf.gda); + + vm.expectRevert(); + sf.governance.updateContracts(sf.host, address(0), new address[](0), address(0), address(newPoolLogic)); + } + + function testUpdateContractsToUpgradePoolBeaconLogic() public { + SuperfluidPool newPoolLogic = new SuperfluidPool(sf.gda); + vm.startPrank(sf.governance.owner()); + sf.governance.updateContracts(sf.host, address(0), new address[](0), address(0), address(newPoolLogic)); + vm.stopPrank(); + + assertEq( + sf.gda.superfluidPoolBeacon().implementation(), + address(newPoolLogic), + "testUpdateContractsToUpgradePoolBeaconLogic: pool beacon logic not upgraded" + ); + } + + function testRevertUpgradePoolBeaconLogicWhenNotGovernance() public { + SuperfluidPool newPoolLogic = new SuperfluidPool(sf.gda); + vm.expectRevert(); + sf.host.updatePoolBeaconLogic(address(newPoolLogic)); + } + + function testUpgradePoolBeaconLogic() public { + SuperfluidPool newPoolLogic = new SuperfluidPool(sf.gda); + vm.startPrank(address(sf.governance)); + sf.host.updatePoolBeaconLogic(address(newPoolLogic)); + vm.stopPrank(); + + assertEq( + sf.gda.superfluidPoolBeacon().implementation(), + address(newPoolLogic), + "testUpgradePoolBeaconLogic: pool beacon logic not upgraded" + ); + } + function testBatchChangeSuperTokenAdmin(address newAdmin) public { vm.assume(newAdmin != address(0)); diff --git a/packages/ethereum-contracts/test/foundry/superfluid/PoolAdminNFT.t.sol b/packages/ethereum-contracts/test/foundry/superfluid/PoolAdminNFT.t.sol index 63f36049ac..53f5d9bec0 100644 --- a/packages/ethereum-contracts/test/foundry/superfluid/PoolAdminNFT.t.sol +++ b/packages/ethereum-contracts/test/foundry/superfluid/PoolAdminNFT.t.sol @@ -15,16 +15,15 @@ contract PoolAdminNFTIntegrationTest is PoolNFTBaseIntegrationTest { Revert Tests //////////////////////////////////////////////////////////////////////////*/ - function testRevertIfTransferFromForPoolAdminNFT(address _poolAdmin, address _receiver) public { - vm.assume(_poolAdmin != address(0)); - vm.assume(_receiver != address(0)); - vm.assume(_poolAdmin != _receiver); + function testRevertIfTransferFromForPoolAdminNFT() public { + address poolAdmin = alice; + address receiver = bob; - ISuperfluidPool pool = sf.gda.createPool(superTokenMock, _poolAdmin, poolConfig); - uint256 nftId = _helperGetPoolAdminNftId(address(pool), _poolAdmin); + ISuperfluidPool pool = sf.gda.createPool(superTokenMock, poolAdmin, poolConfig); + uint256 nftId = _helperGetPoolAdminNftId(address(pool), poolAdmin); _helperRevertIfTransferFrom( - poolAdminNFT, _poolAdmin, _poolAdmin, _receiver, nftId, IPoolNFTBase.POOL_NFT_TRANSFER_NOT_ALLOWED.selector + poolAdminNFT, poolAdmin, poolAdmin, receiver, nftId, IPoolNFTBase.POOL_NFT_TRANSFER_NOT_ALLOWED.selector ); } diff --git a/packages/ethereum-contracts/test/foundry/superfluid/PoolMemberNFT.t.sol b/packages/ethereum-contracts/test/foundry/superfluid/PoolMemberNFT.t.sol index 0bcb12a5ea..f8feedd2aa 100644 --- a/packages/ethereum-contracts/test/foundry/superfluid/PoolMemberNFT.t.sol +++ b/packages/ethereum-contracts/test/foundry/superfluid/PoolMemberNFT.t.sol @@ -46,12 +46,12 @@ contract PoolMemberNFTIntegrationTest is PoolNFTBaseIntegrationTest { poolMemberNFT.mockMint(address(pool), _member); } - function testRevertIfMintingForZeroUnitMember(address _admin, address _member) public { - vm.assume(_admin != address(0)); - vm.assume(_member != address(0)); - ISuperfluidPool pool = sf.gda.createPool(superTokenMock, _admin, poolConfig); + function testRevertIfMintingForZeroUnitMember() public { + address admin_ = alice; + address member = bob; + ISuperfluidPool pool = sf.gda.createPool(superTokenMock, admin_, poolConfig); vm.expectRevert(IPoolMemberNFT.POOL_MEMBER_NFT_NO_UNITS.selector); - poolMemberNFT.mockMint(address(pool), _member); + poolMemberNFT.mockMint(address(pool), member); } function testRevertIfBurningNFTOfMemberWithUnits(address _admin, address _member) public { diff --git a/packages/ethereum-contracts/test/foundry/superfluid/SuperToken.t.sol b/packages/ethereum-contracts/test/foundry/superfluid/SuperToken.t.sol index e58ecdf2f9..bbd2d120e4 100644 --- a/packages/ethereum-contracts/test/foundry/superfluid/SuperToken.t.sol +++ b/packages/ethereum-contracts/test/foundry/superfluid/SuperToken.t.sol @@ -203,6 +203,22 @@ contract SuperTokenIntegrationTest is FoundrySuperfluidTester { vm.stopPrank(); } + function testRevertWhenNonAdminTriesToUpdateCode(address _admin, address nonAdmin) public { + vm.assume(_admin != address(sf.host)); + vm.assume(nonAdmin != address(sf.host)); + + (TestToken localTestToken, ISuperToken localSuperToken) = + sfDeployer.deployWrapperSuperToken("FTT", "FTT", 18, type(uint256).max, address(0)); + + SuperToken newSuperTokenLogic = + _helperDeploySuperTokenAndInitialize(localSuperToken, localTestToken, 18, "FTT", "FTT", _admin); + + vm.startPrank(nonAdmin); + vm.expectRevert(ISuperToken.SUPER_TOKEN_ONLY_ADMIN.selector); + UUPSProxiable(address(localSuperToken)).updateCode(address(newSuperTokenLogic)); + vm.stopPrank(); + } + function testOnlyHostCanUpdateCodeWhenNoAdmin() public { (TestToken localTestToken, ISuperToken localSuperToken) = sfDeployer.deployWrapperSuperToken("FTT", "FTT", 18, type(uint256).max, address(0)); @@ -242,19 +258,4 @@ contract SuperTokenIntegrationTest is FoundrySuperfluidTester { "testOnlyHostCanUpdateCodeWhenNoAdmin: super token logic not updated correctly" ); } - - function testRevertWhenNonAdminTriesToUpdateCode(address _admin, address nonAdmin) public { - vm.assume(_admin != address(sf.host)); - - (TestToken localTestToken, ISuperToken localSuperToken) = - sfDeployer.deployWrapperSuperToken("FTT", "FTT", 18, type(uint256).max, address(0)); - - SuperToken newSuperTokenLogic = - _helperDeploySuperTokenAndInitialize(localSuperToken, localTestToken, 18, "FTT", "FTT", _admin); - - vm.startPrank(nonAdmin); - vm.expectRevert(ISuperToken.SUPER_TOKEN_ONLY_ADMIN.selector); - UUPSProxiable(address(localSuperToken)).updateCode(address(newSuperTokenLogic)); - vm.stopPrank(); - } } diff --git a/packages/ethereum-contracts/test/foundry/upgradability/SuperfluidUpgradeableBeacon.t.sol b/packages/ethereum-contracts/test/foundry/upgradability/SuperfluidUpgradeableBeacon.t.sol index bbef8fa297..c505fc7522 100644 --- a/packages/ethereum-contracts/test/foundry/upgradability/SuperfluidUpgradeableBeacon.t.sol +++ b/packages/ethereum-contracts/test/foundry/upgradability/SuperfluidUpgradeableBeacon.t.sol @@ -20,8 +20,7 @@ contract BadProxiableBeacon is BeaconProxiable { } contract SuperfluidUpgradeableBeaconTest is Test { - - address owner = address(0x420); + address public constant owner = address(0x420); SuperfluidUpgradeableBeacon public beacon; function setUp() public { @@ -43,7 +42,7 @@ contract SuperfluidUpgradeableBeaconTest is Test { beacon.upgradeTo(address(0)); vm.stopPrank(); } - + function testRevertUpgradeToIncompatibleLogic() public { BadProxiableBeacon badProxiableBeacon = new BadProxiableBeacon(); vm.expectRevert(SuperfluidUpgradeableBeacon.INCOMPATIBLE_LOGIC.selector); @@ -64,6 +63,8 @@ contract SuperfluidUpgradeableBeaconTest is Test { vm.startPrank(owner); beacon.upgradeTo(address(proxiableBeacon)); vm.stopPrank(); - assertEq(beacon.implementation(), address(proxiableBeacon), "SuperfluidUpgradeableBeacon.t: wrong implementation"); + assertEq( + beacon.implementation(), address(proxiableBeacon), "SuperfluidUpgradeableBeacon.t: wrong implementation" + ); } -} \ No newline at end of file +} diff --git a/packages/ethereum-contracts/test/foundry/utils/BatchLiquidator.t.sol b/packages/ethereum-contracts/test/foundry/utils/BatchLiquidator.t.sol index af8ea3ca43..11e966caab 100644 --- a/packages/ethereum-contracts/test/foundry/utils/BatchLiquidator.t.sol +++ b/packages/ethereum-contracts/test/foundry/utils/BatchLiquidator.t.sol @@ -2,9 +2,40 @@ pragma solidity 0.8.19; import { FoundrySuperfluidTester, SuperTokenV1Library } from "../FoundrySuperfluidTester.sol"; -import { ISuperToken } from "../../../contracts/superfluid/SuperToken.sol"; +import { + ISuperfluid, + ISuperToken, + IConstantOutflowNFT, + IConstantInflowNFT, + IPoolAdminNFT, + IPoolMemberNFT, + SuperToken +} from "../../../contracts/superfluid/SuperToken.sol"; import { ISuperfluidPool } from "../../../contracts/interfaces/agreements/gdav1/ISuperfluidPool.sol"; import { BatchLiquidator } from "../../../contracts/utils/BatchLiquidator.sol"; +import "forge-std/Test.sol"; + +contract NonTransferableST is SuperToken { + // transferFrom will always revert + constructor(ISuperfluid host) + SuperToken( + host, + IConstantOutflowNFT(address(0)), + IConstantInflowNFT(address(0)), + IPoolAdminNFT(address(0)), + IPoolMemberNFT(address(0)) + ) // solhint-disable-next-line + // no-empty-blocks + { } + + function transferFrom(address holder, address recipient, uint256 amount) public override returns (bool) { + revert(); + } + + function mintInternal(address to, uint256 amount) external { + _mint(msg.sender, to, amount, false, /* invokeHook */ false, /* requireReceptionAck */ "", ""); + } +} contract BatchLiquidatorTest is FoundrySuperfluidTester { using SuperTokenV1Library for ISuperToken; @@ -14,11 +45,14 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester { int96 internal constant FLOW_RATE = 10000000000; + ISuperToken badToken; + constructor() FoundrySuperfluidTester(5) { } function setUp() public override { super.setUp(); batchLiquidator = new BatchLiquidator(address(sf.host)); + badToken = new NonTransferableST(sf.host); } // Helpers @@ -185,18 +219,9 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester { uint256 balanceBefore = superToken.balanceOf(liquidator); vm.warp(4 hours); // jump 4 hours BatchLiquidator.FlowLiquidationData[] memory data = new BatchLiquidator.FlowLiquidationData[](3); - - data[0].agreementOperation = BatchLiquidator.FlowType.ConstantFlowAgreement; - data[0].sender = alice; - data[0].receiver = bob; - - data[1].agreementOperation = BatchLiquidator.FlowType.ConstantFlowAgreement; - data[1].sender = carol; - data[1].receiver = bob; - - data[2].agreementOperation = BatchLiquidator.FlowType.ConstantFlowAgreement; - data[2].sender = dan; - data[2].receiver = bob; + data[0] = _createCFAFlowLiquidationData(alice, bob); + data[1] = _createCFAFlowLiquidationData(carol, bob); + data[2] = _createCFAFlowLiquidationData(dan, bob); batchLiquidator.deleteFlows(address(superToken), data); _assertNoCFAFlow(alice, bob); @@ -222,17 +247,9 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester { uint256 balanceBefore = superToken.balanceOf(liquidator); vm.warp(4 hours); // jump 4 hours BatchLiquidator.FlowLiquidationData[] memory data = new BatchLiquidator.FlowLiquidationData[](3); - data[0].agreementOperation = BatchLiquidator.FlowType.GeneralDistributionAgreement; - data[0].sender = alice; - data[0].receiver = address(pool); - - data[1].agreementOperation = BatchLiquidator.FlowType.GeneralDistributionAgreement; - data[1].sender = carol; - data[1].receiver = address(pool); - - data[2].agreementOperation = BatchLiquidator.FlowType.GeneralDistributionAgreement; - data[2].sender = dan; - data[2].receiver = address(pool); + data[0] = _createGDAFlowLiquidationData(alice, pool); + data[1] = _createGDAFlowLiquidationData(carol, pool); + data[2] = _createGDAFlowLiquidationData(dan, pool); batchLiquidator.deleteFlows(address(superToken), data); @@ -251,7 +268,6 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester { _helperUpdateMemberUnits(pool, alice, bob, 1); _helperDistributeFlow(superToken, alice, alice, pool, FLOW_RATE); - _helperCreateFlow(superToken, carol, bob, FLOW_RATE); _helperCreateFlow(superToken, dan, bob, FLOW_RATE); @@ -263,18 +279,9 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester { uint256 balanceBefore = superToken.balanceOf(liquidator); vm.warp(4 hours); // jump 4 hours BatchLiquidator.FlowLiquidationData[] memory data = new BatchLiquidator.FlowLiquidationData[](4); - - data[0].agreementOperation = BatchLiquidator.FlowType.GeneralDistributionAgreement; - data[0].sender = alice; - data[0].receiver = address(pool); - - data[1].agreementOperation = BatchLiquidator.FlowType.ConstantFlowAgreement; - data[1].sender = carol; - data[1].receiver = bob; - - data[2].agreementOperation = BatchLiquidator.FlowType.ConstantFlowAgreement; - data[2].sender = dan; - data[2].receiver = bob; + data[0] = _createGDAFlowLiquidationData(alice, pool); + data[1] = _createCFAFlowLiquidationData(carol, bob); + data[2] = _createCFAFlowLiquidationData(dan, bob); batchLiquidator.deleteFlows(address(superToken), data); @@ -301,17 +308,9 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester { vm.warp(4 hours); // jump 4 hours BatchLiquidator.FlowLiquidationData[] memory data = new BatchLiquidator.FlowLiquidationData[](4); - data[0].agreementOperation = BatchLiquidator.FlowType.GeneralDistributionAgreement; - data[0].sender = alice; - data[0].receiver = address(pool); - - data[1].agreementOperation = BatchLiquidator.FlowType.ConstantFlowAgreement; - data[1].sender = carol; - data[1].receiver = bob; - - data[2].agreementOperation = BatchLiquidator.FlowType.ConstantFlowAgreement; - data[2].sender = dan; - data[2].receiver = bob; + data[0] = _createGDAFlowLiquidationData(alice, pool); + data[1] = _createCFAFlowLiquidationData(carol, bob); + data[2] = _createCFAFlowLiquidationData(dan, bob); batchLiquidator.deleteFlows(address(superToken), data); @@ -322,4 +321,50 @@ contract BatchLiquidatorTest is FoundrySuperfluidTester { _assertLiquidatorBalanceGreater(liquidator, balanceBefore); vm.stopPrank(); } + + function testCFALiquidationWithCustomTokenRevert() public { + NonTransferableST(address(badToken)).mintInternal(alice, 10 ether); + + vm.startPrank(alice); + badToken.createFlow(bob, FLOW_RATE); + badToken.transferAll(admin); + vm.warp(4 hours); // jump 4 hours + vm.stopPrank(); + vm.startPrank(liquidator); + + BatchLiquidator.FlowLiquidationData memory data = _createCFAFlowLiquidationData(alice, bob); + + batchLiquidator.deleteFlow(address(badToken), data); + _assertNoCFAFlow(alice, bob); + + assertTrue(superToken.balanceOf(liquidator) == 0, "BatchLiquidator: SL - Balance should be 0 because of revert"); + vm.stopPrank(); + } + + function testCFABatchLiquidationWithCustomTokenRevert() public { + NonTransferableST(address(badToken)).mintInternal(alice, 10 ether); + NonTransferableST(address(badToken)).mintInternal(bob, 10 ether); + + vm.startPrank(alice); + badToken.createFlow(bob, FLOW_RATE); + badToken.transferAll(admin); + vm.stopPrank(); + + vm.startPrank(bob); + badToken.createFlow(carol, FLOW_RATE); + badToken.transferAll(admin); + vm.stopPrank(); + + vm.warp(4 hours); // jump 4 hours + + vm.startPrank(liquidator); + + BatchLiquidator.FlowLiquidationData[] memory data = new BatchLiquidator.FlowLiquidationData[](2); + data[0] = _createCFAFlowLiquidationData(alice, bob); + data[1] = _createCFAFlowLiquidationData(bob, carol); + + batchLiquidator.deleteFlows(address(superToken), data); + _assertNoCFAFlow(alice, bob); + _assertNoCFAFlow(bob, carol); + } } diff --git a/packages/ethereum-contracts/test/ops-scripts/deployment.test.js b/packages/ethereum-contracts/test/ops-scripts/deployment.test.js index ee85a72150..f718d5a168 100644 --- a/packages/ethereum-contracts/test/ops-scripts/deployment.test.js +++ b/packages/ethereum-contracts/test/ops-scripts/deployment.test.js @@ -555,6 +555,7 @@ contract("Embedded deployment scripts", (accounts) => { s.superfluid.address, s.superfluid.address, // a dead loop proxy [], + ZERO_ADDRESS, ZERO_ADDRESS ); } catch (err) { diff --git a/packages/ethereum-contracts/truffle-config.js b/packages/ethereum-contracts/truffle-config.js index 406dbe9f92..71d5140a13 100644 --- a/packages/ethereum-contracts/truffle-config.js +++ b/packages/ethereum-contracts/truffle-config.js @@ -207,7 +207,7 @@ const E = (module.exports = { ...createNetworkDefaultConfiguration("polygon-mainnet"), network_id: 137, maxPriorityFeePerGas: 31e9, - maxFeePerGas: 500e9, + maxFeePerGas: 1500e9, }, "polygon-mumbai": { diff --git a/packages/hot-fuzz/contracts/HotFuzzBase.sol b/packages/hot-fuzz/contracts/HotFuzzBase.sol index 8b489b0834..7f3d776eaa 100644 --- a/packages/hot-fuzz/contracts/HotFuzzBase.sol +++ b/packages/hot-fuzz/contracts/HotFuzzBase.sol @@ -47,6 +47,7 @@ contract HotFuzzBase { SuperfluidTester[] internal testers; address[] internal otherAccounts; uint256 internal expectedTotalSupply = 0; + bool internal liquidationFails; constructor(uint nTesters_) { _sfDeployer = new SuperfluidFrameworkDeployer(); @@ -109,7 +110,7 @@ contract HotFuzzBase { tester = testers[a % _numAccounts()]; } - /// @dev The testers returned will never be the same + /// @dev The testers returned may be the same function _getTwoTesters(uint8 a, uint8 b) internal view returns (SuperfluidTester testerA, SuperfluidTester testerB) @@ -118,6 +119,16 @@ contract HotFuzzBase { testerB = _getOneTester(b); } + /// @dev The testers returned may be the same + function _getThreeTesters(uint8 a, uint8 b, uint8 c) + internal view + returns (SuperfluidTester testerA, SuperfluidTester testerB, SuperfluidTester testerC) + { + testerA = _getOneTester(a); + testerB = _getOneTester(b); + testerC = _getOneTester(c); + } + function _superTokenBalanceOfNow(address a) internal view returns (int256 avb) { (avb,,,) = superToken.realtimeBalanceOfNow(a); } @@ -154,4 +165,10 @@ contract HotFuzzBase { assert(netFlowRateSum == 0); return netFlowRateSum == 0; } + + function echidna_check_validLiquidationNeverRevertsInvariant() public view returns (bool) { + bool liquidationNeverFails = !liquidationFails; + assert(liquidationNeverFails); + return liquidationNeverFails; + } } diff --git a/packages/hot-fuzz/contracts/SuperfluidTester.sol b/packages/hot-fuzz/contracts/SuperfluidTester.sol index 73ee58fb87..b6e1cf3e53 100644 --- a/packages/hot-fuzz/contracts/SuperfluidTester.sol +++ b/packages/hot-fuzz/contracts/SuperfluidTester.sol @@ -75,6 +75,10 @@ contract SuperfluidTester { } } + function cfaLiquidate(address sender, address receiver) public { + superToken.deleteFlow(sender, receiver); + } + function setFlowPermissions( address flowOperator, bool allowCreate, @@ -165,14 +169,18 @@ contract SuperfluidTester { superToken.disconnectPool(pool); } - function distributeToPool(ISuperfluidPool pool, address from, uint256 requestedAmount) public { + function distributeToPool(address from, ISuperfluidPool pool, uint256 requestedAmount) public { superToken.distributeToPool(from, pool, requestedAmount); } - function distributeFlow(ISuperfluidPool pool, address from, int96 flowRate) public { + function distributeFlow(address from, ISuperfluidPool pool, int96 flowRate) public { superToken.distributeFlow(from, pool, flowRate); } + function gdaLiquidate(address from, ISuperfluidPool pool) public { + superToken.distributeFlow(from, pool, 0); + } + // SuperfluidPool function updateMemberUnits(ISuperfluidPool pool, address member, uint128 units) public { pool.updateMemberUnits(member, units); diff --git a/packages/hot-fuzz/contracts/superfluid-tests/ConstantFlowAgreementV1.hott.sol b/packages/hot-fuzz/contracts/superfluid-tests/ConstantFlowAgreementV1.hott.sol index 8488933322..680ed89373 100644 --- a/packages/hot-fuzz/contracts/superfluid-tests/ConstantFlowAgreementV1.hott.sol +++ b/packages/hot-fuzz/contracts/superfluid-tests/ConstantFlowAgreementV1.hott.sol @@ -2,9 +2,13 @@ // solhint-disable reason-string pragma solidity >= 0.8.0; +import {SuperToken} from "@superfluid-finance/ethereum-contracts/contracts/superfluid/SuperToken.sol"; +import {SuperTokenV1Library} from "@superfluid-finance/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol"; import "../HotFuzzBase.sol"; abstract contract CFAHotFuzzMixin is HotFuzzBase { + using SuperTokenV1Library for SuperToken; + function createFlow(uint8 a, uint8 b, int64 flowRate) public { require(flowRate > 0); (SuperfluidTester testerA, SuperfluidTester testerB) = _getTwoTesters(a, b); @@ -18,6 +22,29 @@ abstract contract CFAHotFuzzMixin is HotFuzzBase { testerA.flow(address(testerB), 0); } + /// @notice testerA liquidates a flow from testerB to testerC + /// @dev testerA can be the same as testerB or testerC + function cfaLiquidateFlow(uint8 a, uint8 b, uint8 c) public { + (SuperfluidTester liquidator, SuperfluidTester sender, SuperfluidTester recipient) = _getThreeTesters(a, b, c); + + // we first check the condition for whether a flow exists + bool flowExists = superToken.getFlowRate(address(sender), address(recipient)) > 0; + + // then we ensure that the sender has a critical balance + (int256 availableBalance,,,) = superToken.realtimeBalanceOfNow(address(sender)); + bool isSenderCritical = availableBalance < 0; + + // if both conditions are met, a liquidation should occur without fail + bool isLiquidationValid = flowExists && isSenderCritical; + if (isLiquidationValid) { + // solhint-disable-next-line no-empty-blocks + try liquidator.cfaLiquidate(address(sender), address(recipient)) {} + catch { + liquidationFails = true; + } + } + } + function setFlowPermissions( uint8 a, uint8 b, @@ -63,11 +90,7 @@ abstract contract CFAHotFuzzMixin is HotFuzzBase { ) public { (SuperfluidTester testerA, SuperfluidTester testerB) = _getTwoTesters(a, b); - testerA.increaseFlowRateAllowanceWithPermissions( - address(testerB), - permissionsToAdd, - addedFlowRateAllowance - ); + testerA.increaseFlowRateAllowanceWithPermissions(address(testerB), permissionsToAdd, addedFlowRateAllowance); } function decreaseFlowRateAllowanceWithPermissions( @@ -79,9 +102,7 @@ abstract contract CFAHotFuzzMixin is HotFuzzBase { (SuperfluidTester testerA, SuperfluidTester testerB) = _getTwoTesters(a, b); testerA.decreaseFlowRateAllowanceWithPermissions( - address(testerB), - permissionsToRemove, - subtractedFlowRateAllowance + address(testerB), permissionsToRemove, subtractedFlowRateAllowance ); } } diff --git a/packages/hot-fuzz/contracts/superfluid-tests/GeneralDistributionAgreementV1.hott.sol b/packages/hot-fuzz/contracts/superfluid-tests/GeneralDistributionAgreementV1.hott.sol index f95e9b4b06..b1ad780664 100644 --- a/packages/hot-fuzz/contracts/superfluid-tests/GeneralDistributionAgreementV1.hott.sol +++ b/packages/hot-fuzz/contracts/superfluid-tests/GeneralDistributionAgreementV1.hott.sol @@ -2,13 +2,17 @@ // solhint-disable reason-string pragma solidity >= 0.8.0; -import {HotFuzzBase, SuperfluidTester} from "../HotFuzzBase.sol"; +import {SuperToken} from "@superfluid-finance/ethereum-contracts/contracts/superfluid/SuperToken.sol"; +import {SuperTokenV1Library} from "@superfluid-finance/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol"; import {ISuperfluidPool} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/gdav1/ISuperfluidPool.sol"; import {PoolConfig} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/gdav1/IGeneralDistributionAgreementV1.sol"; +import {HotFuzzBase, SuperfluidTester} from "../HotFuzzBase.sol"; abstract contract GDAHotFuzzMixin is HotFuzzBase { + using SuperTokenV1Library for SuperToken; + ISuperfluidPool[] public pools; function getRandomPool(uint8 input) public view returns (ISuperfluidPool pool) { @@ -37,14 +41,38 @@ abstract contract GDAHotFuzzMixin is HotFuzzBase { (SuperfluidTester tester) = _getOneTester(a); ISuperfluidPool pool = getRandomPool(b); - tester.distributeToPool(pool, address(tester), requestedAmount); + tester.distributeToPool(address(tester), pool, requestedAmount); } function distributeFlow(uint8 a, uint8 b, uint8 c, int96 flowRate) public { (SuperfluidTester testerA, SuperfluidTester testerB) = _getTwoTesters(a, b); ISuperfluidPool pool = getRandomPool(c); - testerA.distributeFlow(pool, address(testerB), flowRate); + testerA.distributeFlow(address(testerB), pool, flowRate); + } + + /// @notice testerA liquidates a flow from testerB to pool + /// @dev testerA can be the same as testerB + function gdaLiquidateFlow(uint8 a, uint8 b, uint8 c) public { + (SuperfluidTester liquidator, SuperfluidTester distributor) = _getTwoTesters(a, b); + ISuperfluidPool pool = getRandomPool(c); + + // we first check the condition for whether a flow exists + bool flowExists = superToken.getFlowDistributionFlowRate(address(distributor), pool) > 0; + + // then we ensure that the sender has a critical balance + (int256 availableBalance,,,) = superToken.realtimeBalanceOfNow(address(distributor)); + bool isDistributorCritical = availableBalance < 0; + + // if both conditions are met, a liquidation should occur without fail + bool isLiquidationValid = flowExists && isDistributorCritical; + if (isLiquidationValid) { + // solhint-disable-next-line no-empty-blocks + try liquidator.gdaLiquidate(address(distributor), pool) {} + catch { + liquidationFails = true; + } + } } function updateMemberUnits(uint8 a, uint8 b, uint128 units) public { @@ -116,10 +144,7 @@ contract GDAHotFuzz is HotFuzzBase(10), GDAHotFuzzMixin { constructor() { _initTesters(); - PoolConfig memory config = PoolConfig({ - transferabilityForUnitsOwner: true, - distributionFromAnyAddress: true - }); + PoolConfig memory config = PoolConfig({transferabilityForUnitsOwner: true, distributionFromAnyAddress: true}); for (uint256 i; i < NUM_POOLS; i++) { (SuperfluidTester tester) = _getOneTester(uint8(i)); diff --git a/packages/js-sdk/package.json b/packages/js-sdk/package.json index 4163284e82..f2b9c858da 100644 --- a/packages/js-sdk/package.json +++ b/packages/js-sdk/package.json @@ -43,7 +43,7 @@ "cloc": "sh tasks/cloc.sh" }, "dependencies": { - "@superfluid-finance/metadata": "1.1.17", + "@superfluid-finance/metadata": "1.1.21", "@truffle/contract": "4.6.29", "auto-bind": "4.0.0", "node-fetch": "2.7.0" diff --git a/packages/metadata/CHANGELOG.md b/packages/metadata/CHANGELOG.md index b6aa04fce1..6e09b6b4ce 100644 --- a/packages/metadata/CHANGELOG.md +++ b/packages/metadata/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to the metadata will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v1.1.21] +### Changed +- New contract addresses for Resolver and SuperfluidLoader on xdai-mainnet and polygon-mainnet + +## [v1.1.20] +### Changed +- New contract addresses for Resolver and SuperfluidLoader on eth-goerli and polygon-mumbai + +## [v1.1.19] +### Added +- `cliName` property under "subgraphV1" for the canonical subgraph network names, see [here](https://thegraph.com/docs/en/developing/supported-networks/#hosted-service) + +## [v1.1.18] +### Fixed +- Changed the `module/networks/list.d.ts` file to correctly reflect the `contractsV1` object in our `networks.json` file. + ## [v1.1.17] ### Fixed - Removed `governance` from testnets, changes frequently and can't be reliably kept up to date here diff --git a/packages/metadata/main/networks/list.cjs b/packages/metadata/main/networks/list.cjs index dc8e71be28..94ebd270e2 100644 --- a/packages/metadata/main/networks/list.cjs +++ b/packages/metadata/main/networks/list.cjs @@ -13,18 +13,18 @@ module.exports = "nativeTokenSymbol": "ETH", "nativeTokenWrapper": "0x5943f705abb6834cad767e6e4bb258bc48d9c947", "contractsV1": { - "resolver": "0x3710AB3fDE2B61736B8BB0CE845D6c61F667a78E", + "resolver": "0x071077b24943D4DC09a6A57B8aFfE2BdE9bD4B89", "host": "0x22ff293e14F1EC3A09B137e9e06084AFd63adDF9", "governance": "0x3a648764a6d66440ca096343937c711a7ac1b1e9", "cfaV1": "0xEd6BcbF6907D4feEEe8a8875543249bEa9D308E8", "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0xfDdcdac21D64B639546f3Ce2868C7EF06036990c", "gdaV1": "0x3dB8Abd8B696F6c4150212A85961f954825Dd4B9", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0x94f26B4c8AD12B18c12f38E878618f7664bdcCE2", "constantOutflowNFT": "0xB18cbFeA12b5CB2626C74c94920dB1B37Ae91506", "constantInflowNFT": "0xF07df8b66ed80399B1E00981D61aD34EB4293032", - "superfluidLoader": "0x406970c5934f034a7f1aAC0AEBca31F329158981", + "superfluidLoader": "0x08C6Ad85c040076dD3e33Bbd963C4c37DBF6fCc4", "toga": "0xa54FC15FC75693447d70a57262F37a70B614721b", "flowScheduler": "0xf428308b426D7cD7Ad8eBE549d750f31C8E060Ca", "vestingScheduler": "0xF9240F930d847F70ad900aBEE8949F25649Bf24a", @@ -38,6 +38,7 @@ module.exports = "logsQueryRange": 10000, "explorer": "https://goerli.etherscan.io", "subgraphV1": { + "cliName": "goerli", "name": "protocol-v1-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-goerli" }, @@ -75,17 +76,17 @@ module.exports = "nativeTokenSymbol": "MATIC", "nativeTokenWrapper": "0x96B82B65ACF7072eFEb00502F45757F254c2a0D4", "contractsV1": { - "resolver": "0x8C54C83FbDe3C59e59dd6E324531FB93d4F504d3", + "resolver": "0x2feFd8B23e4770B674b0d2fAda5EE8a2bE0B525F", "host": "0xEB796bdb90fFA0f28255275e16936D25d3418603", "cfaV1": "0x49e565Ed1bdc17F3d220f72DF0857C26FA83F873", "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x804348D4960a61f2d5F9ce9103027A3E849E09b8", "gdaV1": "0x63ab406B6eF6c8be732c1edbd15464de16a8F46D", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xB798553db6EB3D3C56912378409370145E97324B", "constantOutflowNFT": "0x502CC982947216C0f94e433BC78c413806301C07", "constantInflowNFT": "0x9906A7e948C642B6bc74b9A5EAfCddB3580b44e0", - "superfluidLoader": "0x74eF01eDbabFc49A4f2aEF766228809bd64A5BEE", + "superfluidLoader": "0xFcc617a382988a6d081B1821c8d17C47DFF9EDE1", "toga": "0x38DD80876DBA048d0050D28828522c313967D073", "superSpreader": "0x74CDF863b00789c29734F8dFd9F83423Bc55E4cE", "flowScheduler": "0x59A3Ba9d34c387FB70b4f4e4Fbc9eD7519194139", @@ -100,6 +101,7 @@ module.exports = "logsQueryRange": 10000, "explorer": "https://mumbai.polygonscan.com", "subgraphV1": { + "cliName": "mumbai", "name": "protocol-v1-mumbai", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-mumbai" }, @@ -144,7 +146,7 @@ module.exports = "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x96215257F2FcbB00135578f766c0449d239bd92F", "gdaV1": "0xe87F46A15C410F151309Bf7516e130087Fc6a5E5", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xfafe31cf998Df4e5D8310B03EBa8fb5bF327Eaf5", "constantOutflowNFT": "0xDF874BA132D8C68FEb5De513790f7612Fe20dDbd", "constantInflowNFT": "0xf88dd7208438Fdc5Ad05857eA701b7b51cdae0a9", @@ -155,6 +157,7 @@ module.exports = "logsQueryRange": 50000, "explorer": "https://goerli-optimism.etherscan.io", "subgraphV1": { + "cliName": "optimism-goerli", "name": "protocol-v1-optimism-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-optimism-goerli" }, @@ -186,7 +189,7 @@ module.exports = "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x96215257F2FcbB00135578f766c0449d239bd92F", "gdaV1": "0xe87F46A15C410F151309Bf7516e130087Fc6a5E5", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xfafe31cf998Df4e5D8310B03EBa8fb5bF327Eaf5", "constantOutflowNFT": "0xDF874BA132D8C68FEb5De513790f7612Fe20dDbd", "constantInflowNFT": "0xf88dd7208438Fdc5Ad05857eA701b7b51cdae0a9", @@ -197,6 +200,7 @@ module.exports = "logsQueryRange": 50000, "explorer": "https://goerli.arbiscan.io", "subgraphV1": { + "cliName": "arbitrum-goerli", "name": "protocol-v1-arbitrum-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-arbitrum-goerli" }, @@ -227,7 +231,7 @@ module.exports = "cfaV1Forwarder": "0x2CDd45c5182602a36d391F7F16DD9f8386C3bD8D", "idaV1": "0xA44dEC7A0Dde1a56AeDe4143C1ef89cf5d956782", "gdaV1": "0x51f571D934C59185f13d17301a36c07A2268B814", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0x1C92042426B6bAAe497bEf461B6d8342D03aEc92", "constantOutflowNFT": "0x49583f57EFeBe733EC872c5d5437116085a3eE3c", "constantInflowNFT": "0x67d0Efab10b390206b356BA7FB453Ab56AAB7480", @@ -242,6 +246,7 @@ module.exports = "logsQueryRange": 50000, "explorer": "https://testnet.snowtrace.io", "subgraphV1": { + "cliName": "fuji", "name": "protocol-v1-avalanche-fuji", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-avalanche-fuji" }, @@ -282,6 +287,7 @@ module.exports = "logsQueryRange": 10000, "explorer": "https://sepolia.etherscan.io", "subgraphV1": { + "cliName": "sepolia", "name": "protocol-v1-eth-sepolia", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/eth-sepolia/api" }, @@ -355,6 +361,7 @@ module.exports = "logsQueryRange": 20000, "explorer": "https://testnet-zkevm.polygonscan.org/", "subgraphV1": { + "cliName": "polygon-zkevm-testnet", "name": "protocol-v1-polygon-zkevm-testnet" }, "publicRPCs": ["https://rpc.public.zkevm-test.net"], @@ -375,7 +382,7 @@ module.exports = "nativeTokenSymbol": "xDAI", "nativeTokenWrapper": "0x59988e47A3503AaFaA0368b9deF095c818Fdca01", "contractsV1": { - "resolver": "0xD2009765189164b495c110D61e4D301729079911", + "resolver": "0x9634Fa35188C59DD3B0ADa0Dd9adD7e4ECefc0a9", "host": "0x2dFe937cD98Ab92e59cF3139138f18c823a4efE7", "governance": "0xaCc7380323681fdb8a0B9F2FE7d69dDFf0664478", "cfaV1": "0xEbdA4ceF883A7B12c4E669Ebc58927FBa8447C7D", @@ -384,7 +391,7 @@ module.exports = "superTokenFactory": "0x23410e2659380784498509698ed70E414D384880", "constantOutflowNFT": "0xfC00dEE8a980110c5608A823a5B3af3872635456", "constantInflowNFT": "0x1497440B4E92DC4ca0F76223b28C20Cb9cB8a0f1", - "superfluidLoader": "0x21d4E9fbB9DB742E6ef4f29d189a7C18B0b59136", + "superfluidLoader": "0xf941528d82D0eD2314FaBBA8bC8f285D1956A657", "toga": "0xb7DE52F4281a7a276E18C40F94cd93159C4A2d22", "batchLiquidator": "0x27636F8E129cdd4ccA0F30E2b4C116DDaC773bE5", "superSpreader": "0x74CDF863b00789c29734F8dFd9F83423Bc55E4cE", @@ -401,6 +408,7 @@ module.exports = "logsQueryRange": 20000, "explorer": "https://gnosisscan.io", "subgraphV1": { + "cliName": "gnosis", "name": "protocol-v1-xdai", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-xdai", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/xdai/api" @@ -435,7 +443,7 @@ module.exports = "nativeTokenSymbol": "MATIC", "nativeTokenWrapper": "0x3aD736904E9e65189c3000c7DD2c8AC8bB7cD4e3", "contractsV1": { - "resolver": "0xE0cc76334405EE8b39213E620587d815967af39C", + "resolver": "0x8bDCb5613153f41B2856F71Bd7A7e0432F6dbe58", "host": "0x3E14dC1b13c488a8d5D310918780c983bD5982E7", "governance": "0x3AD3f7A0965Ce6f9358AD5CCE86Bc2b05F1EE087", "cfaV1": "0x6EeE6060f715257b970700bc2656De21dEdF074C", @@ -444,7 +452,7 @@ module.exports = "superTokenFactory": "0x2C90719f25B10Fc5646c82DA3240C76Fa5BcCF34", "constantOutflowNFT": "0x554e2bbaCF43FD87417b7201A9F1649a3ED89d68", "constantInflowNFT": "0x55909bB8cd8276887Aae35118d60b19755201c68", - "superfluidLoader": "0x15F0Ca26781C3852f8166eD2ebce5D18265cceb7", + "superfluidLoader": "0xA3d2A6Db274722e802AC025d667041ecAb094FE7", "toga": "0x6AEAeE5Fd4D05A741723D752D30EE4D72690A8f7", "batchLiquidator": "0xA6Cdb472e7E22Bf30ae6fB752E4a13eBF3c12165", "flowScheduler": "0x55F7758dd99d5e185f4CC08d4Ad95B71f598264D", @@ -459,6 +467,7 @@ module.exports = "logsQueryRange": 10000, "explorer": "https://polygonscan.com", "subgraphV1": { + "cliName": "matic", "name": "protocol-v1-matic", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-matic", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/matic/api" @@ -517,6 +526,7 @@ module.exports = "logsQueryRange": 50000, "explorer": "https://optimistic.etherscan.io", "subgraphV1": { + "cliName": "optimism", "name": "protocol-v1-optimism-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-optimism-mainnet" }, @@ -574,6 +584,7 @@ module.exports = "logsQueryRange": 50000, "explorer": "https://arbiscan.io", "subgraphV1": { + "cliName": "arbitrum-one", "name": "protocol-v1-arbitrum-one", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-arbitrum-one" }, @@ -631,6 +642,7 @@ module.exports = "logsQueryRange": 50000, "explorer": "https://snowtrace.io", "subgraphV1": { + "cliName": "avalanche", "name": "protocol-v1-avalanche-c", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-avalanche-c" }, @@ -688,6 +700,7 @@ module.exports = "logsQueryRange": 5000, "explorer": "https://bscscan.com", "subgraphV1": { + "cliName": "bsc", "name": "protocol-v1-bsc-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-bsc-mainnet" }, @@ -742,6 +755,7 @@ module.exports = "logsQueryRange": 10000, "explorer": "https://etherscan.io", "subgraphV1": { + "cliName": "mainnet", "name": "protocol-v1-eth-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-eth-mainnet", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/eth-mainnet/api" @@ -794,6 +808,7 @@ module.exports = "logsQueryRange": 20000, "explorer": "https://celoscan.io", "subgraphV1": { + "cliName": "celo", "name": "protocol-v1-celo-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-celo-mainnet" }, @@ -830,6 +845,7 @@ module.exports = "logsQueryRange": 20000, "explorer": "https://basescan.org", "subgraphV1": { + "cliName": "base", "name": "protocol-v1-base-mainnet" }, "publicRPCs": ["https://developer-access-mainnet.base.org"], diff --git a/packages/metadata/module/networks/list.d.ts b/packages/metadata/module/networks/list.d.ts index 620a360eeb..30b36a3b3e 100644 --- a/packages/metadata/module/networks/list.d.ts +++ b/packages/metadata/module/networks/list.d.ts @@ -5,7 +5,7 @@ interface AutowrapAddresses { interface ContractAddresses { readonly resolver: string; readonly host: string; - readonly governance: string; + readonly governance?: string; readonly cfaV1: string; readonly cfaV1Forwarder: string; readonly idaV1: string; @@ -14,15 +14,17 @@ interface ContractAddresses { readonly constantOutflowNFT?: string; readonly constantInflowNFT?: string; readonly superfluidLoader: string; - readonly toga: string; - readonly vestingScheduler: string; - readonly flowScheduler: string; - readonly batchLiquidator: string; - readonly autowrap: AutowrapAddresses; + readonly toga?: string; + readonly vestingScheduler?: string; + readonly flowScheduler?: string; + readonly batchLiquidator?: string; + readonly superSpreader?: string; + readonly autowrap?: AutowrapAddresses; readonly existentialNFTCloneFactory: string; } interface SubgraphData { readonly name: string; + readonly cliName?: string; readonly hostedEndpoint?: string; readonly satsumaEndpoint?: string; } diff --git a/packages/metadata/module/networks/list.js b/packages/metadata/module/networks/list.js index e54cfd1477..652c2a704d 100644 --- a/packages/metadata/module/networks/list.js +++ b/packages/metadata/module/networks/list.js @@ -13,18 +13,18 @@ export default "nativeTokenSymbol": "ETH", "nativeTokenWrapper": "0x5943f705abb6834cad767e6e4bb258bc48d9c947", "contractsV1": { - "resolver": "0x3710AB3fDE2B61736B8BB0CE845D6c61F667a78E", + "resolver": "0x071077b24943D4DC09a6A57B8aFfE2BdE9bD4B89", "host": "0x22ff293e14F1EC3A09B137e9e06084AFd63adDF9", "governance": "0x3a648764a6d66440ca096343937c711a7ac1b1e9", "cfaV1": "0xEd6BcbF6907D4feEEe8a8875543249bEa9D308E8", "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0xfDdcdac21D64B639546f3Ce2868C7EF06036990c", "gdaV1": "0x3dB8Abd8B696F6c4150212A85961f954825Dd4B9", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0x94f26B4c8AD12B18c12f38E878618f7664bdcCE2", "constantOutflowNFT": "0xB18cbFeA12b5CB2626C74c94920dB1B37Ae91506", "constantInflowNFT": "0xF07df8b66ed80399B1E00981D61aD34EB4293032", - "superfluidLoader": "0x406970c5934f034a7f1aAC0AEBca31F329158981", + "superfluidLoader": "0x08C6Ad85c040076dD3e33Bbd963C4c37DBF6fCc4", "toga": "0xa54FC15FC75693447d70a57262F37a70B614721b", "flowScheduler": "0xf428308b426D7cD7Ad8eBE549d750f31C8E060Ca", "vestingScheduler": "0xF9240F930d847F70ad900aBEE8949F25649Bf24a", @@ -38,6 +38,7 @@ export default "logsQueryRange": 10000, "explorer": "https://goerli.etherscan.io", "subgraphV1": { + "cliName": "goerli", "name": "protocol-v1-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-goerli" }, @@ -75,17 +76,17 @@ export default "nativeTokenSymbol": "MATIC", "nativeTokenWrapper": "0x96B82B65ACF7072eFEb00502F45757F254c2a0D4", "contractsV1": { - "resolver": "0x8C54C83FbDe3C59e59dd6E324531FB93d4F504d3", + "resolver": "0x2feFd8B23e4770B674b0d2fAda5EE8a2bE0B525F", "host": "0xEB796bdb90fFA0f28255275e16936D25d3418603", "cfaV1": "0x49e565Ed1bdc17F3d220f72DF0857C26FA83F873", "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x804348D4960a61f2d5F9ce9103027A3E849E09b8", "gdaV1": "0x63ab406B6eF6c8be732c1edbd15464de16a8F46D", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xB798553db6EB3D3C56912378409370145E97324B", "constantOutflowNFT": "0x502CC982947216C0f94e433BC78c413806301C07", "constantInflowNFT": "0x9906A7e948C642B6bc74b9A5EAfCddB3580b44e0", - "superfluidLoader": "0x74eF01eDbabFc49A4f2aEF766228809bd64A5BEE", + "superfluidLoader": "0xFcc617a382988a6d081B1821c8d17C47DFF9EDE1", "toga": "0x38DD80876DBA048d0050D28828522c313967D073", "superSpreader": "0x74CDF863b00789c29734F8dFd9F83423Bc55E4cE", "flowScheduler": "0x59A3Ba9d34c387FB70b4f4e4Fbc9eD7519194139", @@ -100,6 +101,7 @@ export default "logsQueryRange": 10000, "explorer": "https://mumbai.polygonscan.com", "subgraphV1": { + "cliName": "mumbai", "name": "protocol-v1-mumbai", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-mumbai" }, @@ -144,7 +146,7 @@ export default "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x96215257F2FcbB00135578f766c0449d239bd92F", "gdaV1": "0xe87F46A15C410F151309Bf7516e130087Fc6a5E5", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xfafe31cf998Df4e5D8310B03EBa8fb5bF327Eaf5", "constantOutflowNFT": "0xDF874BA132D8C68FEb5De513790f7612Fe20dDbd", "constantInflowNFT": "0xf88dd7208438Fdc5Ad05857eA701b7b51cdae0a9", @@ -155,6 +157,7 @@ export default "logsQueryRange": 50000, "explorer": "https://goerli-optimism.etherscan.io", "subgraphV1": { + "cliName": "optimism-goerli", "name": "protocol-v1-optimism-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-optimism-goerli" }, @@ -186,7 +189,7 @@ export default "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x96215257F2FcbB00135578f766c0449d239bd92F", "gdaV1": "0xe87F46A15C410F151309Bf7516e130087Fc6a5E5", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xfafe31cf998Df4e5D8310B03EBa8fb5bF327Eaf5", "constantOutflowNFT": "0xDF874BA132D8C68FEb5De513790f7612Fe20dDbd", "constantInflowNFT": "0xf88dd7208438Fdc5Ad05857eA701b7b51cdae0a9", @@ -197,6 +200,7 @@ export default "logsQueryRange": 50000, "explorer": "https://goerli.arbiscan.io", "subgraphV1": { + "cliName": "arbitrum-goerli", "name": "protocol-v1-arbitrum-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-arbitrum-goerli" }, @@ -227,7 +231,7 @@ export default "cfaV1Forwarder": "0x2CDd45c5182602a36d391F7F16DD9f8386C3bD8D", "idaV1": "0xA44dEC7A0Dde1a56AeDe4143C1ef89cf5d956782", "gdaV1": "0x51f571D934C59185f13d17301a36c07A2268B814", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0x1C92042426B6bAAe497bEf461B6d8342D03aEc92", "constantOutflowNFT": "0x49583f57EFeBe733EC872c5d5437116085a3eE3c", "constantInflowNFT": "0x67d0Efab10b390206b356BA7FB453Ab56AAB7480", @@ -242,6 +246,7 @@ export default "logsQueryRange": 50000, "explorer": "https://testnet.snowtrace.io", "subgraphV1": { + "cliName": "fuji", "name": "protocol-v1-avalanche-fuji", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-avalanche-fuji" }, @@ -282,6 +287,7 @@ export default "logsQueryRange": 10000, "explorer": "https://sepolia.etherscan.io", "subgraphV1": { + "cliName": "sepolia", "name": "protocol-v1-eth-sepolia", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/eth-sepolia/api" }, @@ -355,6 +361,7 @@ export default "logsQueryRange": 20000, "explorer": "https://testnet-zkevm.polygonscan.org/", "subgraphV1": { + "cliName": "polygon-zkevm-testnet", "name": "protocol-v1-polygon-zkevm-testnet" }, "publicRPCs": ["https://rpc.public.zkevm-test.net"], @@ -375,7 +382,7 @@ export default "nativeTokenSymbol": "xDAI", "nativeTokenWrapper": "0x59988e47A3503AaFaA0368b9deF095c818Fdca01", "contractsV1": { - "resolver": "0xD2009765189164b495c110D61e4D301729079911", + "resolver": "0x9634Fa35188C59DD3B0ADa0Dd9adD7e4ECefc0a9", "host": "0x2dFe937cD98Ab92e59cF3139138f18c823a4efE7", "governance": "0xaCc7380323681fdb8a0B9F2FE7d69dDFf0664478", "cfaV1": "0xEbdA4ceF883A7B12c4E669Ebc58927FBa8447C7D", @@ -384,7 +391,7 @@ export default "superTokenFactory": "0x23410e2659380784498509698ed70E414D384880", "constantOutflowNFT": "0xfC00dEE8a980110c5608A823a5B3af3872635456", "constantInflowNFT": "0x1497440B4E92DC4ca0F76223b28C20Cb9cB8a0f1", - "superfluidLoader": "0x21d4E9fbB9DB742E6ef4f29d189a7C18B0b59136", + "superfluidLoader": "0xf941528d82D0eD2314FaBBA8bC8f285D1956A657", "toga": "0xb7DE52F4281a7a276E18C40F94cd93159C4A2d22", "batchLiquidator": "0x27636F8E129cdd4ccA0F30E2b4C116DDaC773bE5", "superSpreader": "0x74CDF863b00789c29734F8dFd9F83423Bc55E4cE", @@ -401,6 +408,7 @@ export default "logsQueryRange": 20000, "explorer": "https://gnosisscan.io", "subgraphV1": { + "cliName": "gnosis", "name": "protocol-v1-xdai", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-xdai", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/xdai/api" @@ -435,7 +443,7 @@ export default "nativeTokenSymbol": "MATIC", "nativeTokenWrapper": "0x3aD736904E9e65189c3000c7DD2c8AC8bB7cD4e3", "contractsV1": { - "resolver": "0xE0cc76334405EE8b39213E620587d815967af39C", + "resolver": "0x8bDCb5613153f41B2856F71Bd7A7e0432F6dbe58", "host": "0x3E14dC1b13c488a8d5D310918780c983bD5982E7", "governance": "0x3AD3f7A0965Ce6f9358AD5CCE86Bc2b05F1EE087", "cfaV1": "0x6EeE6060f715257b970700bc2656De21dEdF074C", @@ -444,7 +452,7 @@ export default "superTokenFactory": "0x2C90719f25B10Fc5646c82DA3240C76Fa5BcCF34", "constantOutflowNFT": "0x554e2bbaCF43FD87417b7201A9F1649a3ED89d68", "constantInflowNFT": "0x55909bB8cd8276887Aae35118d60b19755201c68", - "superfluidLoader": "0x15F0Ca26781C3852f8166eD2ebce5D18265cceb7", + "superfluidLoader": "0xA3d2A6Db274722e802AC025d667041ecAb094FE7", "toga": "0x6AEAeE5Fd4D05A741723D752D30EE4D72690A8f7", "batchLiquidator": "0xA6Cdb472e7E22Bf30ae6fB752E4a13eBF3c12165", "flowScheduler": "0x55F7758dd99d5e185f4CC08d4Ad95B71f598264D", @@ -459,6 +467,7 @@ export default "logsQueryRange": 10000, "explorer": "https://polygonscan.com", "subgraphV1": { + "cliName": "matic", "name": "protocol-v1-matic", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-matic", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/matic/api" @@ -517,6 +526,7 @@ export default "logsQueryRange": 50000, "explorer": "https://optimistic.etherscan.io", "subgraphV1": { + "cliName": "optimism", "name": "protocol-v1-optimism-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-optimism-mainnet" }, @@ -574,6 +584,7 @@ export default "logsQueryRange": 50000, "explorer": "https://arbiscan.io", "subgraphV1": { + "cliName": "arbitrum-one", "name": "protocol-v1-arbitrum-one", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-arbitrum-one" }, @@ -631,6 +642,7 @@ export default "logsQueryRange": 50000, "explorer": "https://snowtrace.io", "subgraphV1": { + "cliName": "avalanche", "name": "protocol-v1-avalanche-c", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-avalanche-c" }, @@ -688,6 +700,7 @@ export default "logsQueryRange": 5000, "explorer": "https://bscscan.com", "subgraphV1": { + "cliName": "bsc", "name": "protocol-v1-bsc-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-bsc-mainnet" }, @@ -742,6 +755,7 @@ export default "logsQueryRange": 10000, "explorer": "https://etherscan.io", "subgraphV1": { + "cliName": "mainnet", "name": "protocol-v1-eth-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-eth-mainnet", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/eth-mainnet/api" @@ -794,6 +808,7 @@ export default "logsQueryRange": 20000, "explorer": "https://celoscan.io", "subgraphV1": { + "cliName": "celo", "name": "protocol-v1-celo-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-celo-mainnet" }, @@ -830,6 +845,7 @@ export default "logsQueryRange": 20000, "explorer": "https://basescan.org", "subgraphV1": { + "cliName": "base", "name": "protocol-v1-base-mainnet" }, "publicRPCs": ["https://developer-access-mainnet.base.org"], diff --git a/packages/metadata/networks.json b/packages/metadata/networks.json index 262d31ede5..6a9f1b756e 100644 --- a/packages/metadata/networks.json +++ b/packages/metadata/networks.json @@ -11,18 +11,18 @@ "nativeTokenSymbol": "ETH", "nativeTokenWrapper": "0x5943f705abb6834cad767e6e4bb258bc48d9c947", "contractsV1": { - "resolver": "0x3710AB3fDE2B61736B8BB0CE845D6c61F667a78E", + "resolver": "0x071077b24943D4DC09a6A57B8aFfE2BdE9bD4B89", "host": "0x22ff293e14F1EC3A09B137e9e06084AFd63adDF9", "governance": "0x3a648764a6d66440ca096343937c711a7ac1b1e9", "cfaV1": "0xEd6BcbF6907D4feEEe8a8875543249bEa9D308E8", "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0xfDdcdac21D64B639546f3Ce2868C7EF06036990c", "gdaV1": "0x3dB8Abd8B696F6c4150212A85961f954825Dd4B9", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0x94f26B4c8AD12B18c12f38E878618f7664bdcCE2", "constantOutflowNFT": "0xB18cbFeA12b5CB2626C74c94920dB1B37Ae91506", "constantInflowNFT": "0xF07df8b66ed80399B1E00981D61aD34EB4293032", - "superfluidLoader": "0x406970c5934f034a7f1aAC0AEBca31F329158981", + "superfluidLoader": "0x08C6Ad85c040076dD3e33Bbd963C4c37DBF6fCc4", "toga": "0xa54FC15FC75693447d70a57262F37a70B614721b", "flowScheduler": "0xf428308b426D7cD7Ad8eBE549d750f31C8E060Ca", "vestingScheduler": "0xF9240F930d847F70ad900aBEE8949F25649Bf24a", @@ -36,6 +36,7 @@ "logsQueryRange": 10000, "explorer": "https://goerli.etherscan.io", "subgraphV1": { + "cliName": "goerli", "name": "protocol-v1-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-goerli" }, @@ -73,17 +74,17 @@ "nativeTokenSymbol": "MATIC", "nativeTokenWrapper": "0x96B82B65ACF7072eFEb00502F45757F254c2a0D4", "contractsV1": { - "resolver": "0x8C54C83FbDe3C59e59dd6E324531FB93d4F504d3", + "resolver": "0x2feFd8B23e4770B674b0d2fAda5EE8a2bE0B525F", "host": "0xEB796bdb90fFA0f28255275e16936D25d3418603", "cfaV1": "0x49e565Ed1bdc17F3d220f72DF0857C26FA83F873", "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x804348D4960a61f2d5F9ce9103027A3E849E09b8", "gdaV1": "0x63ab406B6eF6c8be732c1edbd15464de16a8F46D", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xB798553db6EB3D3C56912378409370145E97324B", "constantOutflowNFT": "0x502CC982947216C0f94e433BC78c413806301C07", "constantInflowNFT": "0x9906A7e948C642B6bc74b9A5EAfCddB3580b44e0", - "superfluidLoader": "0x74eF01eDbabFc49A4f2aEF766228809bd64A5BEE", + "superfluidLoader": "0xFcc617a382988a6d081B1821c8d17C47DFF9EDE1", "toga": "0x38DD80876DBA048d0050D28828522c313967D073", "superSpreader": "0x74CDF863b00789c29734F8dFd9F83423Bc55E4cE", "flowScheduler": "0x59A3Ba9d34c387FB70b4f4e4Fbc9eD7519194139", @@ -98,6 +99,7 @@ "logsQueryRange": 10000, "explorer": "https://mumbai.polygonscan.com", "subgraphV1": { + "cliName": "mumbai", "name": "protocol-v1-mumbai", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-mumbai" }, @@ -142,7 +144,7 @@ "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x96215257F2FcbB00135578f766c0449d239bd92F", "gdaV1": "0xe87F46A15C410F151309Bf7516e130087Fc6a5E5", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xfafe31cf998Df4e5D8310B03EBa8fb5bF327Eaf5", "constantOutflowNFT": "0xDF874BA132D8C68FEb5De513790f7612Fe20dDbd", "constantInflowNFT": "0xf88dd7208438Fdc5Ad05857eA701b7b51cdae0a9", @@ -153,6 +155,7 @@ "logsQueryRange": 50000, "explorer": "https://goerli-optimism.etherscan.io", "subgraphV1": { + "cliName": "optimism-goerli", "name": "protocol-v1-optimism-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-optimism-goerli" }, @@ -184,7 +187,7 @@ "cfaV1Forwarder": "0xcfA132E353cB4E398080B9700609bb008eceB125", "idaV1": "0x96215257F2FcbB00135578f766c0449d239bd92F", "gdaV1": "0xe87F46A15C410F151309Bf7516e130087Fc6a5E5", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0xfafe31cf998Df4e5D8310B03EBa8fb5bF327Eaf5", "constantOutflowNFT": "0xDF874BA132D8C68FEb5De513790f7612Fe20dDbd", "constantInflowNFT": "0xf88dd7208438Fdc5Ad05857eA701b7b51cdae0a9", @@ -195,6 +198,7 @@ "logsQueryRange": 50000, "explorer": "https://goerli.arbiscan.io", "subgraphV1": { + "cliName": "arbitrum-goerli", "name": "protocol-v1-arbitrum-goerli", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-arbitrum-goerli" }, @@ -225,7 +229,7 @@ "cfaV1Forwarder": "0x2CDd45c5182602a36d391F7F16DD9f8386C3bD8D", "idaV1": "0xA44dEC7A0Dde1a56AeDe4143C1ef89cf5d956782", "gdaV1": "0x51f571D934C59185f13d17301a36c07A2268B814", - "gdaV1Forwarder": "0x6dA170169d5Fca20F902b7E5755346a97c94B07c", + "gdaV1Forwarder": "0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08", "superTokenFactory": "0x1C92042426B6bAAe497bEf461B6d8342D03aEc92", "constantOutflowNFT": "0x49583f57EFeBe733EC872c5d5437116085a3eE3c", "constantInflowNFT": "0x67d0Efab10b390206b356BA7FB453Ab56AAB7480", @@ -240,6 +244,7 @@ "logsQueryRange": 50000, "explorer": "https://testnet.snowtrace.io", "subgraphV1": { + "cliName": "fuji", "name": "protocol-v1-avalanche-fuji", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-avalanche-fuji" }, @@ -280,6 +285,7 @@ "logsQueryRange": 10000, "explorer": "https://sepolia.etherscan.io", "subgraphV1": { + "cliName": "sepolia", "name": "protocol-v1-eth-sepolia", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/eth-sepolia/api" }, @@ -353,6 +359,7 @@ "logsQueryRange": 20000, "explorer": "https://testnet-zkevm.polygonscan.org/", "subgraphV1": { + "cliName": "polygon-zkevm-testnet", "name": "protocol-v1-polygon-zkevm-testnet" }, "publicRPCs": ["https://rpc.public.zkevm-test.net"], @@ -373,7 +380,7 @@ "nativeTokenSymbol": "xDAI", "nativeTokenWrapper": "0x59988e47A3503AaFaA0368b9deF095c818Fdca01", "contractsV1": { - "resolver": "0xD2009765189164b495c110D61e4D301729079911", + "resolver": "0x9634Fa35188C59DD3B0ADa0Dd9adD7e4ECefc0a9", "host": "0x2dFe937cD98Ab92e59cF3139138f18c823a4efE7", "governance": "0xaCc7380323681fdb8a0B9F2FE7d69dDFf0664478", "cfaV1": "0xEbdA4ceF883A7B12c4E669Ebc58927FBa8447C7D", @@ -382,7 +389,7 @@ "superTokenFactory": "0x23410e2659380784498509698ed70E414D384880", "constantOutflowNFT": "0xfC00dEE8a980110c5608A823a5B3af3872635456", "constantInflowNFT": "0x1497440B4E92DC4ca0F76223b28C20Cb9cB8a0f1", - "superfluidLoader": "0x21d4E9fbB9DB742E6ef4f29d189a7C18B0b59136", + "superfluidLoader": "0xf941528d82D0eD2314FaBBA8bC8f285D1956A657", "toga": "0xb7DE52F4281a7a276E18C40F94cd93159C4A2d22", "batchLiquidator": "0x27636F8E129cdd4ccA0F30E2b4C116DDaC773bE5", "superSpreader": "0x74CDF863b00789c29734F8dFd9F83423Bc55E4cE", @@ -399,6 +406,7 @@ "logsQueryRange": 20000, "explorer": "https://gnosisscan.io", "subgraphV1": { + "cliName": "gnosis", "name": "protocol-v1-xdai", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-xdai", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/xdai/api" @@ -433,7 +441,7 @@ "nativeTokenSymbol": "MATIC", "nativeTokenWrapper": "0x3aD736904E9e65189c3000c7DD2c8AC8bB7cD4e3", "contractsV1": { - "resolver": "0xE0cc76334405EE8b39213E620587d815967af39C", + "resolver": "0x8bDCb5613153f41B2856F71Bd7A7e0432F6dbe58", "host": "0x3E14dC1b13c488a8d5D310918780c983bD5982E7", "governance": "0x3AD3f7A0965Ce6f9358AD5CCE86Bc2b05F1EE087", "cfaV1": "0x6EeE6060f715257b970700bc2656De21dEdF074C", @@ -442,7 +450,7 @@ "superTokenFactory": "0x2C90719f25B10Fc5646c82DA3240C76Fa5BcCF34", "constantOutflowNFT": "0x554e2bbaCF43FD87417b7201A9F1649a3ED89d68", "constantInflowNFT": "0x55909bB8cd8276887Aae35118d60b19755201c68", - "superfluidLoader": "0x15F0Ca26781C3852f8166eD2ebce5D18265cceb7", + "superfluidLoader": "0xA3d2A6Db274722e802AC025d667041ecAb094FE7", "toga": "0x6AEAeE5Fd4D05A741723D752D30EE4D72690A8f7", "batchLiquidator": "0xA6Cdb472e7E22Bf30ae6fB752E4a13eBF3c12165", "flowScheduler": "0x55F7758dd99d5e185f4CC08d4Ad95B71f598264D", @@ -457,6 +465,7 @@ "logsQueryRange": 10000, "explorer": "https://polygonscan.com", "subgraphV1": { + "cliName": "matic", "name": "protocol-v1-matic", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-matic", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/matic/api" @@ -515,6 +524,7 @@ "logsQueryRange": 50000, "explorer": "https://optimistic.etherscan.io", "subgraphV1": { + "cliName": "optimism", "name": "protocol-v1-optimism-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-optimism-mainnet" }, @@ -572,6 +582,7 @@ "logsQueryRange": 50000, "explorer": "https://arbiscan.io", "subgraphV1": { + "cliName": "arbitrum-one", "name": "protocol-v1-arbitrum-one", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-arbitrum-one" }, @@ -629,6 +640,7 @@ "logsQueryRange": 50000, "explorer": "https://snowtrace.io", "subgraphV1": { + "cliName": "avalanche", "name": "protocol-v1-avalanche-c", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-avalanche-c" }, @@ -686,6 +698,7 @@ "logsQueryRange": 5000, "explorer": "https://bscscan.com", "subgraphV1": { + "cliName": "bsc", "name": "protocol-v1-bsc-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-bsc-mainnet" }, @@ -740,6 +753,7 @@ "logsQueryRange": 10000, "explorer": "https://etherscan.io", "subgraphV1": { + "cliName": "mainnet", "name": "protocol-v1-eth-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-eth-mainnet", "satsumaEndpoint": "https://subgraph.satsuma-prod.com/c5br3jaVlJI6/superfluid/eth-mainnet/api" @@ -792,6 +806,7 @@ "logsQueryRange": 20000, "explorer": "https://celoscan.io", "subgraphV1": { + "cliName": "celo", "name": "protocol-v1-celo-mainnet", "hostedEndpoint": "https://api.thegraph.com/subgraphs/name/superfluid-finance/protocol-v1-celo-mainnet" }, @@ -828,6 +843,7 @@ "logsQueryRange": 20000, "explorer": "https://basescan.org", "subgraphV1": { + "cliName": "base", "name": "protocol-v1-base-mainnet" }, "publicRPCs": ["https://developer-access-mainnet.base.org"], diff --git a/packages/metadata/package.json b/packages/metadata/package.json index 403de30760..9f38f431e0 100644 --- a/packages/metadata/package.json +++ b/packages/metadata/package.json @@ -1,6 +1,6 @@ { "name": "@superfluid-finance/metadata", - "version": "1.1.17", + "version": "1.1.21", "description": "Superfluid Metadata", "main": "main/index.cjs", "module": "module/index.js", diff --git a/packages/sdk-core/CHANGELOG.md b/packages/sdk-core/CHANGELOG.md index 2272bec2a7..47721636b8 100644 --- a/packages/sdk-core/CHANGELOG.md +++ b/packages/sdk-core/CHANGELOG.md @@ -1,336 +1,424 @@ # Changelog + All notable changes to the SDK-core will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Map the name from subgraph to an unknown event, instead of "\_Unknown". + +## [0.6.12] - 2023-10-23 + +### Fixed + +- Support for `CustomSuperToken` contracts without `CONSTANT_OUTFLOW_NFT()` and `CONSTANT_INFLOW_NFT()` function implemented + +## [0.6.11] - 2023-10-20 + +### Fixed + +- Handle the case when `networkData.addresses.governance` is null. This was due to a removal of the `governance` address from the metadata for test networks in `metadata@v1.1.17`. + +## [0.6.10] - 2023-10-16 + ### Added -- Support for `ConstantOutflowNFT` and `ConstantInflowNFT` functions + +- Support for `ConstantOutflowNFT` and `ConstantInflowNFT` functions + +### Fixed + +- Support for `CustomSuperToken` contracts without `getUnderlyingToken()` function implemented ## [0.6.9] - 2023-09-11 ### Added -- Support for new `increaseFlowRateAllowanceWithPermissions` and `decreaseFlowRateAllowanceWithPermissions` functions on `CFAv1` class + +- Support for new `increaseFlowRateAllowanceWithPermissions` and `decreaseFlowRateAllowanceWithPermissions` functions on `CFAv1` class ### Changed -- Node dependency updates. +- Node dependency updates. ## [0.6.8] - 2023-07-25 ### Updated -- Metadata changes for recently added networks + +- Metadata changes for recently added networks ## [0.6.7] - 2023-07-13 ### Added -- `BatchCall.toOperation` function which unifies `BatchCall` to `Operation` type -- `Operation.toOperationStruct` moved from `BatchCall` to `Operation` class + +- `BatchCall.toOperation` function which unifies `BatchCall` to `Operation` type +- `Operation.toOperationStruct` moved from `BatchCall` to `Operation` class ### Updated -- Bump version to support metadata v1.1.8. + +- Bump version to support metadata v1.1.8. ## [0.6.6] - 2023-05-17 ### Added -- Subgraph query support for `FlowOperator` + +- Subgraph query support for `FlowOperator` ## [0.6.5] - 2023-05-12 ### Fixed -- `hostedEndpoint` might be nullable so we handle this case. + +- `hostedEndpoint` might be nullable so we handle this case. ### Added -- Support for `sepolia` network + +- Support for `sepolia` network ## [0.6.4] - 2023-05-07 ### Changed -- `getPopulatedTransactionRequest` doesn't use the signer to populate the transaction anymore as `signer.sendTransaction` does it already. The double `signer.populateTransaction` was causing issues with some wallets (e.g. Rainbow Wallet) -- Map `isNativeAssetSuperToken` to `Token` from Subgraph + +- `getPopulatedTransactionRequest` doesn't use the signer to populate the transaction anymore as `signer.sendTransaction` does it already. The double `signer.populateTransaction` was causing issues with some wallets (e.g. Rainbow Wallet) +- Map `isNativeAssetSuperToken` to `Token` from Subgraph ## [0.6.3] - 2023-03-14 ### Added -- `increaseAllowance` and `decreaseAllowance` functions to SuperToken class -- Batch call support for `increaseAllowance` and `decreaseAllowance` -- `increaseFlowRateAllowance` and `decreaseFlowRateAllowance` functions to CFAv1 class -- Add support for `activeOutgoingStreamCount`, `activeIncomingStreamCount`, `inactiveOutgoingStreamCount`, `inactiveIncomingStreamCount` properties in query for `AccountTokenSnapshot` entity -- Add support for `rewardAddress`, `liquidationPeriod`, `patricianPeriod`, and `minimumDeposit` properties in query for `Token` entity -- Add support for `userData` property in query for `Stream` entity -- Add `index` (the Subgraph entity ID) field to Index events when querying from Subgraph + +- `increaseAllowance` and `decreaseAllowance` functions to SuperToken class +- Batch call support for `increaseAllowance` and `decreaseAllowance` +- `increaseFlowRateAllowance` and `decreaseFlowRateAllowance` functions to CFAv1 class +- Add support for `activeOutgoingStreamCount`, `activeIncomingStreamCount`, `inactiveOutgoingStreamCount`, `inactiveIncomingStreamCount` properties in query for `AccountTokenSnapshot` entity +- Add support for `rewardAddress`, `liquidationPeriod`, `patricianPeriod`, and `minimumDeposit` properties in query for `Token` entity +- Add support for `userData` property in query for `Stream` entity +- Add `index` (the Subgraph entity ID) field to Index events when querying from Subgraph ### Changed -- `.exec` or `.execForward` will throw an error if the operations array is empty + +- `.exec` or `.execForward` will throw an error if the operations array is empty ## [0.6.2] - 2023-02-07 + ### Added -- `streamId` to `FlowUpdatedEvent` when querying from Subgraph -- Support for Celo + +- `streamId` to `FlowUpdatedEvent` when querying from Subgraph +- Support for Celo ## [0.6.1] - 2022-12-20 ### Changed -- Subgraph endpoints all use hosted service endpoints by default + +- Subgraph endpoints all use hosted service endpoints by default ## [0.6.0] - 2022-12-19 ### Added -- `SuperToken` class has `send` function -- `batchCall` supports new `send` batch operation -- Added `downgradeTo` function on `SuperToken` class -- Added toga events to be part of query + +- `SuperToken` class has `send` function +- `batchCall` supports new `send` batch operation +- Added `downgradeTo` function on `SuperToken` class +- Added toga events to be part of query ### Changed -- Make `sender` field optional in CFAv1 write functions + +- Make `sender` field optional in CFAv1 write functions ## [0.5.9] - 2022-12-05 ### Added -- Map `deposit` to Stream when querying from Subgraph + +- Map `deposit` to Stream when querying from Subgraph ### Fixes -- Fix `@nomiclabs/hardhat-ethers/types` dependency error + +- Fix `@nomiclabs/hardhat-ethers/types` dependency error ## [0.5.8] - 2022-11-02 ### Added -- Support for mainnet + +- Support for mainnet ### Changed -- Framework initialization for supported networks utilizes `@superfluid-finance/metadata`, but still uses the resolver for unsupported/local testing environments - - > NOTE: This will not create any changes when doing `Framework.create` and is just a minor optimization. -- All transactions executed via SDK-Core have a default multiplier (1.2x) applied to the provider estimated gas limit **unless** an ethers `Overrides` object is passed during creation of the `Operation`. -- There is also the option to pass in an explicit multiplier when executing transactions: `Operation.exec(signer, 1.32)`. + +- Framework initialization for supported networks utilizes `@superfluid-finance/metadata`, but still uses the resolver for unsupported/local testing environments + - > NOTE: This will not create any changes when doing `Framework.create` and is just a minor optimization. +- All transactions executed via SDK-Core have a default multiplier (1.2x) applied to the provider estimated gas limit **unless** an ethers `Overrides` object is passed during creation of the `Operation`. +- There is also the option to pass in an explicit multiplier when executing transactions: `Operation.exec(signer, 1.32)`. ## [0.5.7] - 2022-10-13 + ### Breaking + - `CFAv1Forwarder` integrated into SDK-Core and will be the default way of calling CFA agreements and `sender` is now a required property. - - Migration: pass sender into the affected CFAv1 callAgreement functions - `create/update/deleteFlow`. - > NOTE: You must pass `shouldUseCallAgreement` explicitly as a property if you want to execute these calls via the Host. +- Migration: pass sender into the affected CFAv1 callAgreement functions - `create/update/deleteFlow`. + > NOTE: You must pass `shouldUseCallAgreement` explicitly as a property if you want to execute these calls via the Host. ### Added + - typechain files consumed from `@superfluid-finance/ethereum-contracts` and exported from SDK-Core ## [0.5.6] - 2022-09-07 + ### Fixes -- Correct `subgraphAPIEndpoint` in `getResolverData` + +- Correct `subgraphAPIEndpoint` in `getResolverData` ### Breaking -- Don't wrap `SubgraphClient` with `SFError` + +- Don't wrap `SubgraphClient` with `SFError` ## [0.5.5] - 2022-08-31 + ### Added -- Support for: `optimism-goerli` and `arbitrum-goerli` added + +- Support for: `optimism-goerli` and `arbitrum-goerli` added ### Breaking -- Support for: `rinkeby`, `ropsten`, `kovan`, `optimism-kovan` and `arbitrum-rinkeby` removed -- Don't throw `SFError` when executing `Operation` or `BatchCall`; let the original error bubble up + +- Support for: `rinkeby`, `ropsten`, `kovan`, `optimism-kovan` and `arbitrum-rinkeby` removed +- Don't throw `SFError` when executing `Operation` or `BatchCall`; let the original error bubble up ### Fixes -- Serialize a much smaller version of the cause in `SFError` (only `name`, `message`, `code`) -- Change `SFError.name` from "Error" to "SFError" + +- Serialize a much smaller version of the cause in `SFError` (only `name`, `message`, `code`) +- Change `SFError.name` from "Error" to "SFError" # [0.5.4] - 2022-08-19 ### Fixes -- Properly console the cause, not the caught serialization error + +- Properly console the cause, not the caught serialization error ## [0.5.3] - 2022-08-15 ### Added -- Map `indexId` to `IndexSubscription` when querying from Subgraph + +- Map `indexId` to `IndexSubscription` when querying from Subgraph ### Fixes -- Catch and handle serialization error + +- Catch and handle serialization error ## [0.5.2] - 2022-07-26 ### Added -- Support for `isNativeAssetSuperToken` property on SuperToken entity queries -- `callAppAction` Operation creator added to `Host` class + +- Support for `isNativeAssetSuperToken` property on SuperToken entity queries +- `callAppAction` Operation creator added to `Host` class ### Breaking -- `BatchCall.getCallDataFunctionArgs` deprecates the old `BatchCall.getCallAgreementFunctionArgs` - - Migration: - - Replace `getCallAgreementFunctionArgs` with `getCallDataFunctionArgs` and pass in the fragment/ABI as the first argument, whilst keeping the same `callData` argument. -- `Host.populateCallAgreementTxnAndReturnOperation` is replaced by `Host.callAgreement` - - Migration: - - Replace instances of `populateCallAgreementTxnAndReturnOperation` with `callAgreement` + +- `BatchCall.getCallDataFunctionArgs` deprecates the old `BatchCall.getCallAgreementFunctionArgs` + - Migration: + - Replace `getCallAgreementFunctionArgs` with `getCallDataFunctionArgs` and pass in the fragment/ABI as the first argument, whilst keeping the same `callData` argument. +- `Host.populateCallAgreementTxnAndReturnOperation` is replaced by `Host.callAgreement` + - Migration: + - Replace instances of `populateCallAgreementTxnAndReturnOperation` with `callAgreement` ### Fixes -- Handle `CALL_APP_ACTION` operation type correctly in SDK-Core when doing a batch call -- Undefined `process` in `constants.ts` in React and client-side apps using SDK-Core directly + +- Handle `CALL_APP_ACTION` operation type correctly in SDK-Core when doing a batch call +- Undefined `process` in `constants.ts` in React and client-side apps using SDK-Core directly ## [0.5.1] - 2022-07-26 ### Fixes -- Patch fix serializeError strange serialization + +- Patch fix serializeError strange serialization ## [0.5.0] - 2022-07-14 ### Added -- Support for SetEvent and Subgraph v1.4.4 -- `Framework.operation` method for easily creating `Operation` instances + +- Support for SetEvent and Subgraph v1.4.4 +- `Framework.operation` method for easily creating `Operation` instances ### Fixes -- Compile AJV validations to prevent unsafe-eval and did not allow SDK-Core usage inside Google Chrome extension due to unsafe-eval CSP + +- Compile AJV validations to prevent unsafe-eval and did not allow SDK-Core usage inside Google Chrome extension due to unsafe-eval CSP ### Changed -- `SFError` refactor to be more conventional. It inherits `Error` and uses `cause` to wrap internal errors. -- Use `serialize-error` for serializing error object inside the message. -- Export Operation & OperationType + +- `SFError` refactor to be more conventional. It inherits `Error` and uses `cause` to wrap internal errors. +- Use `serialize-error` for serializing error object inside the message. +- Export Operation & OperationType ### Breaking -- `SFError.errorObject` renamed to `SFError.cause` + +- `SFError.errorObject` renamed to `SFError.cause` ## [0.4.4] - 2022-06-30 ### Added -- Support for new event properties for Subgraph v1.4.1 + +- Support for new event properties for Subgraph v1.4.1 ### Breaking -- Subgraph Query: `rewardAccount` renamed to `rewardAmountReceiver` on `AgreementLiquidatedV2Event` entity -- `chainId` is a required property for framework initialization -- `networkId` and `dataMode` no longer exist as properties for framework initialization + +- Subgraph Query: `rewardAccount` renamed to `rewardAmountReceiver` on `AgreementLiquidatedV2Event` entity +- `chainId` is a required property for framework initialization +- `networkId` and `dataMode` no longer exist as properties for framework initialization ## [0.4.3] - 2022-06-29 ### Added -- BNB Chain support added + +- BNB Chain support added ### Changed -- `maybeCriticalAtTimestamp` is a nullable property now + +- `maybeCriticalAtTimestamp` is a nullable property now ## [0.4.2] - 2022-05-17 ### Added -- `QueryHandler` for transfer events + +- `QueryHandler` for transfer events ## [0.4.2] - 2022-05-17 ### Fixed -- Patched SDK-Core Subgraph files to be in sync with V1 Subgraph endpoint + +- Patched SDK-Core Subgraph files to be in sync with V1 Subgraph endpoint ## [0.4.1] - 2022-05-14 ### Added -- Avalanche Network Support + +- Avalanche Network Support ### Changed -- Network constants consistent with canonical Superfluid name + +- Network constants consistent with canonical Superfluid name ## [0.4.0] - 2022-05-06 ### Added -- Added option to specify block details when querying through a `SubgraphQueryHandler` -- Added Subgraph's `_meta` table query -- Added `tokenSymbol` for `SubgraphQueryHandler` entity queries where `token` (token ID) was previously included -- Added `PageNumberPaging` for UI development friendly pagination API -- Added `AllPaging` to recursively query all results from Subgraph -- Added support for `TypedDocumentNode` for `SubgraphClient` -- Expose underlying ethers.js contracts for each class: CFAv1, Host, IDAv1 and `contracts` property in `Framework` class -- Added new ACL function support: authorizing flow operator permissions and create/update/delete flow by operator -- Added `nativeTokenSymbol` property to `constants.ts` -- Split `SuperToken` class into: `WrapperSuperToken`, `PureSuperToken` and `NativeAssetSuperToken` classes -- Added `loadWrapperSuperToken`, `loadNativeAssetSuperToken`, and `loadPureSuperToken` super token initialization functions -- Support `upgrade`, `upgradeTo` and `downgrade` functions via `NativeAssetSuperToken` -- Added `upgradeTo` to `WrapperSuperToken` class as this was missing as well + +- Added option to specify block details when querying through a `SubgraphQueryHandler` +- Added Subgraph's `_meta` table query +- Added `tokenSymbol` for `SubgraphQueryHandler` entity queries where `token` (token ID) was previously included +- Added `PageNumberPaging` for UI development friendly pagination API +- Added `AllPaging` to recursively query all results from Subgraph +- Added support for `TypedDocumentNode` for `SubgraphClient` +- Expose underlying ethers.js contracts for each class: CFAv1, Host, IDAv1 and `contracts` property in `Framework` class +- Added new ACL function support: authorizing flow operator permissions and create/update/delete flow by operator +- Added `nativeTokenSymbol` property to `constants.ts` +- Split `SuperToken` class into: `WrapperSuperToken`, `PureSuperToken` and `NativeAssetSuperToken` classes +- Added `loadWrapperSuperToken`, `loadNativeAssetSuperToken`, and `loadPureSuperToken` super token initialization functions +- Support `upgrade`, `upgradeTo` and `downgrade` functions via `NativeAssetSuperToken` +- Added `upgradeTo` to `WrapperSuperToken` class as this was missing as well ### Changed -- Renamed `Token` to `ERC20Token` -- Exported `ERC20Token` -- Renamed `PagedResult.data` to `PagedResult.items` -- Moved `listAllResults` into separate function from `Query` object -- Removed `SubgraphClient.batchRequests` because Subgraph Node didn't support it + +- Renamed `Token` to `ERC20Token` +- Exported `ERC20Token` +- Renamed `PagedResult.data` to `PagedResult.items` +- Moved `listAllResults` into separate function from `Query` object +- Removed `SubgraphClient.batchRequests` because Subgraph Node didn't support it ### Internal -- Use `eslint-plugin-prettier` over separate `prettier` instance + +- Use `eslint-plugin-prettier` over separate `prettier` instance ### Breaking -- The `SuperToken` class is now an abstract base class and no longer contains the functions `upgrade` and `downgrade`. -- `underlyingToken` is possibly undefined on `SuperToken`: `WrapperSuperToken` has `underlyingToken`, but `PureSuperToken` and `NativeAssetSuperToken` do not. -> NOTE: These changes are due to the split of `SuperToken` into `WrapperSuperToken`, `PureSuperToken` and `NativeAssetSuperToken` classes. - - Migration: - - if you are unsure of the type of the super token, you can use: `await framework.loadSuperToken("0x...");` - - if you want to load a wrapper super token, use: `await framework.loadWrapperSuperToken("DAIx");` - - if you want to load a native asset super token, use: `await framework.loadNativeAssetSuperToken("ETHx");` - - if you want to load a pure super token, use: `await framework.loadPureSuperToken("0x...");` + +- The `SuperToken` class is now an abstract base class and no longer contains the functions `upgrade` and `downgrade`. +- `underlyingToken` is possibly undefined on `SuperToken`: `WrapperSuperToken` has `underlyingToken`, but `PureSuperToken` and `NativeAssetSuperToken` do not. + > NOTE: These changes are due to the split of `SuperToken` into `WrapperSuperToken`, `PureSuperToken` and `NativeAssetSuperToken` classes. + - Migration: + - if you are unsure of the type of the super token, you can use: `await framework.loadSuperToken("0x...");` + - if you want to load a wrapper super token, use: `await framework.loadWrapperSuperToken("DAIx");` + - if you want to load a native asset super token, use: `await framework.loadNativeAssetSuperToken("ETHx");` + - if you want to load a pure super token, use: `await framework.loadPureSuperToken("0x...");` ## [0.3.2] - 2022-03-16 ### Added -- Added "optimism-mainnet" and "arbitrum-one" support +- Added "optimism-mainnet" and "arbitrum-one" support ## [0.3.1] - 2022-02-16 ### Added -- Added `indexValueCurrent` to `IndexSubscription` query to optimize calculating "total amount distributed" in consuming applications ([#629]) -- Added `indexTotalUnits` to `IndexSubscription` query to optimize calculating "pool percentage" in consuming applications ([#630]) + +- Added `indexValueCurrent` to `IndexSubscription` query to optimize calculating "total amount distributed" in consuming applications ([#629]) +- Added `indexTotalUnits` to `IndexSubscription` query to optimize calculating "pool percentage" in consuming applications ([#630]) ### Fixed -- Typo for `networkName: "arbitrum-rinkeby"` fixed (was expecting `"arbitrium-rinkeby"`) in `Framework.create` ([#637]) + +- Typo for `networkName: "arbitrum-rinkeby"` fixed (was expecting `"arbitrium-rinkeby"`) in `Framework.create` ([#637]) ### Breaking -- Using `"xdai"` as the `networkName` will no longer work. Updated to `"gnosis"` - - Migration: change `networkName` from `"xdai"` to `"gnosis"` + +- Using `"xdai"` as the `networkName` will no longer work. Updated to `"gnosis"` + - Migration: change `networkName` from `"xdai"` to `"gnosis"` ## [0.3.0] - 2022-02-02 + ### Added -- New query handlers to cover full spectrum of Subgraph querying capabilities - - Used by the new release of SDK-redux - - Lacks an easy-to-use API for average SDK-core user + +- New query handlers to cover full spectrum of Subgraph querying capabilities + - Used by the new release of SDK-redux + - Lacks an easy-to-use API for average SDK-core user ### Changed -- `_ethers` is not exported for UMD build anymore. Use `window._ethers` instead. -- `SFError` and `ErrorType` are now exported -- Generated Subgraph types are now exported (`*_Filter` and `*_OrderBy` types) - - There are a lot of Subgraph types, so it does make the namespace crowded. We'll alleviate it in a later release. + +- `_ethers` is not exported for UMD build anymore. Use `window._ethers` instead. +- `SFError` and `ErrorType` are now exported +- Generated Subgraph types are now exported (`*_Filter` and `*_OrderBy` types) + - There are a lot of Subgraph types, so it does make the namespace crowded. We'll alleviate it in a later release. ## [0.2.1] - 2022-01-31 ### Added -- Load `SuperToken` by token symbol as long as the token is listed on the resolver ([#588]) + +- Load `SuperToken` by token symbol as long as the token is listed on the resolver ([#588]) ## [0.2.0] - 2022-01-14 + ### Added -- Support for new testnets: Optimism Kovan, Avalanche Fuji, and Arbitrum Rinkeby ([#526]) -- Working UMD build added to package and removed duplicated .d.ts typing files from package ([#535]) -- ethers.js overrides object support added to all `Operation` creation functions ([#540]) -- `Query` class overhaul: fuller filter and ordering and more generation of types + +- Support for new testnets: Optimism Kovan, Avalanche Fuji, and Arbitrum Rinkeby ([#526]) +- Working UMD build added to package and removed duplicated .d.ts typing files from package ([#535]) +- ethers.js overrides object support added to all `Operation` creation functions ([#540]) +- `Query` class overhaul: fuller filter and ordering and more generation of types ### Changed -- package.json cleanup and subgraph schema updated ([#522]) -- Simpler provider logic for Framework creation ([#537]) -- Use V1 instead of devSubgraph endpoints ([#550]) -- `superTokenFactoryAddress` removed from `IConfig` interface ([#556]) + +- package.json cleanup and subgraph schema updated ([#522]) +- Simpler provider logic for Framework creation ([#537]) +- Use V1 instead of devSubgraph endpoints ([#550]) +- `superTokenFactoryAddress` removed from `IConfig` interface ([#556]) ### Fixed -- Outdated README.md cleanup and updates ([#520], [#524], [#526], [#530], [#537], [#549], [#556]) -- `BatchCall` for callAgreement functions fixed, flow rate calculation utils logic fixed ([#526]) -- Improper base 18 number for flow rate calculation utils ([#545]) -- single network deploy implemented ([#506]) -- eslint errors and .json imports fixed ([#535]) + +- Outdated README.md cleanup and updates ([#520], [#524], [#526], [#530], [#537], [#549], [#556]) +- `BatchCall` for callAgreement functions fixed, flow rate calculation utils logic fixed ([#526]) +- Improper base 18 number for flow rate calculation utils ([#545]) +- single network deploy implemented ([#506]) +- eslint errors and .json imports fixed ([#535]) ### Breaking -- Breaking change: Framework.create interface breaking change:`web3Ethers` and `hardhatEthers` properties removed ([#537]) - - Migration: if you were using one of these two properties, change the property `web3Ethers` and `hardhatEthers` to `provider` -- Breaking change: non Framework initialized `batchCall` constructor arguments interface change: `config` property removed ([#556]) - - Migration: if you instantiated a `BatchCall` without using Framework, you need to remove the config property and replace it with the property: `hostAddress` + +- Breaking change: Framework.create interface breaking change:`web3Ethers` and `hardhatEthers` properties removed ([#537]) + - Migration: if you were using one of these two properties, change the property `web3Ethers` and `hardhatEthers` to `provider` +- Breaking change: non Framework initialized `batchCall` constructor arguments interface change: `config` property removed ([#556]) + - Migration: if you instantiated a `BatchCall` without using Framework, you need to remove the config property and replace it with the property: `hostAddress` ## [0.1.0] - 2021-12-01 + ### Added -- Initial preview version of SDK-Core -- Features: - - New `Framework` initialization pattern - - Built with `ethers.js` and `TypeScript` from the ground up - - `Query` class which leverages the Subgraph for queries with simple filters - - New `Operation` class for executing transactions/batching transactions - - `ConstantFlowAgreementV1` and `InstantDistributionAgreementV1` helper classes with create, read, update and delete functionality - - New `SuperToken` class with `SuperToken` CRUD functionality and an underlying `Token` class with basic `ERC20` functionality - - New `BatchCall` class for creating and executing batch calls with supported `Operation's` + +- Initial preview version of SDK-Core +- Features: + - New `Framework` initialization pattern + - Built with `ethers.js` and `TypeScript` from the ground up + - `Query` class which leverages the Subgraph for queries with simple filters + - New `Operation` class for executing transactions/batching transactions + - `ConstantFlowAgreementV1` and `InstantDistributionAgreementV1` helper classes with create, read, update and delete functionality + - New `SuperToken` class with `SuperToken` CRUD functionality and an underlying `Token` class with basic `ERC20` functionality + - New `BatchCall` class for creating and executing batch calls with supported `Operation's` [Unreleased]: https://github.com/superfluid-finance/protocol-monorepo/compare/sdk-core%40v0.6.3...HEAD [0.6.3]: https://github.com/superfluid-finance/protocol-monorepo/compare/sdk-core%40v0.6.2...sdk-core%40v0.6.3 @@ -358,8 +446,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm [0.2.1]: https://github.com/superfluid-finance/protocol-monorepo/compare/sdk-core%40v0.2.0...sdk-core%40v0.2.1 [0.2.0]: https://github.com/superfluid-finance/protocol-monorepo/compare/sdk-core%40v0.1.0...sdk-core%40v0.2.0 [0.1.0]: https://github.com/superfluid-finance/protocol-monorepo/releases/tag/sdk-core%40v0.1.0 - - [#506]: https://github.com/superfluid-finance/protocol-monorepo/pull/506 [#515]: https://github.com/superfluid-finance/protocol-monorepo/pull/515 [#520]: https://github.com/superfluid-finance/protocol-monorepo/pull/520 diff --git a/packages/sdk-core/contracts/NoGetUnderlyingToken.sol b/packages/sdk-core/contracts/NoGetUnderlyingToken.sol new file mode 100644 index 0000000000..cad87d06a9 --- /dev/null +++ b/packages/sdk-core/contracts/NoGetUnderlyingToken.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +contract NoGetUnderlyingToken { + + // solhint-disable-next-line var-name-mixedcase + address public CONSTANT_OUTFLOW_NFT; + + // solhint-disable-next-line var-name-mixedcase + address public CONSTANT_INFLOW_NFT; + + function symbol() public pure returns (string memory) { + return "NOGET"; + } +} diff --git a/packages/sdk-core/package.json b/packages/sdk-core/package.json index e2c570143a..6d2f72554a 100644 --- a/packages/sdk-core/package.json +++ b/packages/sdk-core/package.json @@ -1,6 +1,6 @@ { "name": "@superfluid-finance/sdk-core", - "version": "0.6.9", + "version": "0.6.13", "description": "SDK Core for building with Superfluid Protocol", "homepage": "https://github.com/superfluid-finance/protocol-monorepo/tree/dev/packages/sdk-core#readme", "repository": { @@ -57,7 +57,7 @@ }, "dependencies": { "@superfluid-finance/ethereum-contracts": "1.8.1", - "@superfluid-finance/metadata": "1.1.17", + "@superfluid-finance/metadata": "1.1.21", "browserify": "^17.0.0", "graphql-request": "^6.1.0", "lodash": "^4.17.21", diff --git a/packages/sdk-core/previous-versions-testing/yarn.lock b/packages/sdk-core/previous-versions-testing/yarn.lock index e540c14abc..b927199b2a 100644 --- a/packages/sdk-core/previous-versions-testing/yarn.lock +++ b/packages/sdk-core/previous-versions-testing/yarn.lock @@ -449,11 +449,16 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1: +bn.js@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== +bn.js@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -517,7 +522,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== @@ -526,19 +531,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" + integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.4" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.6" + readable-stream "^3.6.2" + safe-buffer "^5.2.1" browserify-zlib@~0.2.0: version "0.2.0" @@ -830,7 +835,7 @@ duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: dependencies: readable-stream "^2.0.2" -elliptic@6.5.4, elliptic@^6.5.3: +elliptic@6.5.4, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -1452,7 +1457,7 @@ parents@^1.0.0, parents@^1.0.1: dependencies: path-platform "~0.11.15" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: +parse-asn1@^5.0.0, parse-asn1@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== @@ -1592,6 +1597,15 @@ readable-stream@^3.5.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -1623,7 +1637,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== diff --git a/packages/sdk-core/src/Framework.ts b/packages/sdk-core/src/Framework.ts index 4cfe1f4934..80893b60dd 100644 --- a/packages/sdk-core/src/Framework.ts +++ b/packages/sdk-core/src/Framework.ts @@ -184,10 +184,14 @@ export default class Framework { }; // supported networks scenario - if ( - networkData != null && - baseSettings.protocolReleaseVersion === V1 - ) { + if (networkData && baseSettings.protocolReleaseVersion === V1) { + const governanceAddress = networkData.addresses.governance + ? networkData.addresses.governance + : await Superfluid__factory.connect( + networkData.addresses.host, + provider + ).getGovernance(); + const settings: IFrameworkSettings = { ...baseSettings, config: { @@ -203,7 +207,7 @@ export default class Framework { gdaV1ForwarderAddress: (networkData.addresses as any).gdaV1Forwarder || networkData.addresses.idaV1, - governanceAddress: networkData.addresses.governance, + governanceAddress, cfaV1ForwarderAddress: networkData.addresses.cfaV1Forwarder, }, diff --git a/packages/sdk-core/src/GeneralDistributionAgreementV1.ts b/packages/sdk-core/src/GeneralDistributionAgreementV1.ts index e29b7ab52b..acd8563d85 100644 --- a/packages/sdk-core/src/GeneralDistributionAgreementV1.ts +++ b/packages/sdk-core/src/GeneralDistributionAgreementV1.ts @@ -3,6 +3,7 @@ import { ethers } from "ethers"; import Host from "./Host"; import { SFError } from "./SFError"; import SuperfluidAgreement from "./SuperfluidAgreement"; +import SuperfluidPoolClass from "./SuperfluidPool"; import { ConnectPoolParams, CreatePoolParams, @@ -265,10 +266,7 @@ export default class GeneralDistributionAgreementV1 extends SuperfluidAgreement try { return await this.contract .connect(params.providerOrSigner) - ["isMemberConnected(address,address)"]( - normalizedPool, - normalizedMember - ); + .isMemberConnected(normalizedPool, normalizedMember); } catch (err) { throw new SFError({ type: "GDAV1_READ", @@ -315,9 +313,14 @@ export default class GeneralDistributionAgreementV1 extends SuperfluidAgreement * * @param token The token address. * @param admin The admin address. - * @returns The created pool. + * @returns CreatePoolTxn and SuperfluidPool instance */ - createPool = async (params: CreatePoolParams) => { + createPool = async ( + params: CreatePoolParams + ): Promise<{ + createPoolTxn: ethers.ContractTransaction; + pool: SuperfluidPoolClass; + }> => { const normalizedToken = normalizeAddress(params.token); const normalizedAdmin = normalizeAddress(params.admin); @@ -333,7 +336,7 @@ export default class GeneralDistributionAgreementV1 extends SuperfluidAgreement poolCreatedEvent?.args?.pool || ethers.constants.AddressZero; return { createPoolTxn, - poolAddress, + pool: new SuperfluidPoolClass(poolAddress), }; } catch (err) { throw new SFError({ @@ -352,7 +355,7 @@ export default class GeneralDistributionAgreementV1 extends SuperfluidAgreement * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - connectPool = async (params: ConnectPoolParams) => { + connectPool = (params: ConnectPoolParams) => { const normalizedPool = normalizeAddress(params.pool); const callData = gdaInterface.encodeFunctionData("connectPool", [ normalizedPool, @@ -388,7 +391,7 @@ export default class GeneralDistributionAgreementV1 extends SuperfluidAgreement * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - disconnectPool = async (params: DisconnectPoolParams) => { + disconnectPool = (params: DisconnectPoolParams) => { const normalizedPool = normalizeAddress(params.pool); const callData = gdaInterface.encodeFunctionData("disconnectPool", [ normalizedPool, @@ -427,7 +430,7 @@ export default class GeneralDistributionAgreementV1 extends SuperfluidAgreement * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - distribute = async (params: DistributeParams) => { + distribute = (params: DistributeParams) => { const normalizedToken = normalizeAddress(params.token); const normalizedFrom = normalizeAddress(params.from); const normalizedPool = normalizeAddress(params.pool); @@ -475,7 +478,7 @@ export default class GeneralDistributionAgreementV1 extends SuperfluidAgreement * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - distributeFlow = async (params: DistributeFlowParams) => { + distributeFlow = (params: DistributeFlowParams) => { const normalizedToken = normalizeAddress(params.token); const normalizedFrom = normalizeAddress(params.from); const normalizedPool = normalizeAddress(params.pool); diff --git a/packages/sdk-core/src/SuperToken.ts b/packages/sdk-core/src/SuperToken.ts index a2b524c8e9..b44286b5d4 100644 --- a/packages/sdk-core/src/SuperToken.ts +++ b/packages/sdk-core/src/SuperToken.ts @@ -69,6 +69,7 @@ import { getSanitizedTimestamp, getStringCurrentTimeInSeconds, normalizeAddress, + tryGet, } from "./utils"; export interface NFTAddresses { @@ -156,9 +157,13 @@ export default abstract class SuperToken extends ERC20Token { options.address, options.provider ); - const underlyingTokenAddress = await superToken + const getUnderlyingTokenPromise = superToken .connect(options.provider) .getUnderlyingToken(); + const underlyingTokenAddress = await tryGet( + getUnderlyingTokenPromise, + ethers.constants.AddressZero + ); const settings: ITokenSettings = { address: options.address, config: options.config, @@ -178,10 +183,48 @@ export default abstract class SuperToken extends ERC20Token { const nativeTokenSymbol = resolverData.nativeTokenSymbol || "ETH"; const nativeSuperTokenSymbol = nativeTokenSymbol + "x"; - const constantOutflowNFTProxy = - await superToken.CONSTANT_OUTFLOW_NFT(); - const constantInflowNFTProxy = - await superToken.CONSTANT_INFLOW_NFT(); + // @note This is tech debt and should be reverted once GoodDollar upgrades their token contract + // @note We are using tryGet here just to handle GoodDollar not having + // CONSTANT_OUTFLOW_NFT in its SuperToken implementation. + let constantOutflowNFTProxy = await tryGet( + superToken.CONSTANT_OUTFLOW_NFT(), + ethers.constants.AddressZero + ); + let constantInflowNFTProxy = await tryGet( + superToken.CONSTANT_INFLOW_NFT(), + ethers.constants.AddressZero + ); + + // @note We only want to run this bit of code for GoodDollar SuperTokens + // (dev and mainnet) + const GOOD_DOLLAR_SYMBOL = "G$"; + if (tokenSymbol === GOOD_DOLLAR_SYMBOL) { + // @note we need to create a new interface for the old GoodDollar SuperToken + // which contains the functions for constantInflowNFT and constantOutflowNFT + const oldSuperTokenInterface = new ethers.utils.Interface([ + "function constantInflowNFT() view returns (address)", + "function constantOutflowNFT() view returns (address)", + ]); + const goodDollarSpecificToken = new ethers.Contract( + superToken.address, + oldSuperTokenInterface + ); + + // @note we attempt to get the constantInflowNFT and constantOutflowNFT + if (constantOutflowNFTProxy === ethers.constants.AddressZero) { + constantOutflowNFTProxy = await tryGet( + goodDollarSpecificToken.constantOutflowNFT(), + ethers.constants.AddressZero + ); + } + if (constantInflowNFTProxy === ethers.constants.AddressZero) { + constantInflowNFTProxy = await tryGet( + goodDollarSpecificToken.constantInflowNFT(), + ethers.constants.AddressZero + ); + } + } + const nftAddresses: NFTAddresses = { constantOutflowNFTProxy, constantInflowNFTProxy, @@ -928,8 +971,8 @@ export default abstract class SuperToken extends ERC20Token { * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - connectPool = async (params: ConnectPoolParams): Promise => { - return await this.gdaV1.connectPool({ + connectPool = (params: ConnectPoolParams): Operation => { + return this.gdaV1.connectPool({ ...params, }); }; @@ -942,10 +985,8 @@ export default abstract class SuperToken extends ERC20Token { * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - disconnectPool = async ( - params: DisconnectPoolParams - ): Promise => { - return await this.gdaV1.disconnectPool({ + disconnectPool = (params: DisconnectPoolParams): Operation => { + return this.gdaV1.disconnectPool({ ...params, }); }; @@ -960,10 +1001,8 @@ export default abstract class SuperToken extends ERC20Token { * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - distributeWithGDA = async ( - params: SuperTokenDistributeParams - ): Promise => { - return await this.gdaV1.distribute({ + distributeWithGDA = (params: SuperTokenDistributeParams): Operation => { + return this.gdaV1.distribute({ token: this.settings.address, ...params, }); @@ -979,10 +1018,8 @@ export default abstract class SuperToken extends ERC20Token { * @param overrides The transaction overrides. * @returns The call agreement operation result. */ - distributeFlow = async ( - params: SuperTokenDistributeFlowParams - ): Promise => { - return await this.gdaV1.distributeFlow({ + distributeFlow = (params: SuperTokenDistributeFlowParams): Operation => { + return this.gdaV1.distributeFlow({ token: this.settings.address, ...params, }); diff --git a/packages/sdk-core/src/SuperfluidPool.ts b/packages/sdk-core/src/SuperfluidPool.ts index bb421497ea..62312f1cfe 100644 --- a/packages/sdk-core/src/SuperfluidPool.ts +++ b/packages/sdk-core/src/SuperfluidPool.ts @@ -25,7 +25,7 @@ import { normalizeAddress } from "./utils"; * Superfluid Pool Helper Class * @description A helper class to interact with the SuperfluidPool contract. */ -export default class SuperfluidPool { +export default class SuperfluidPoolClass { readonly contract: ISuperfluidPool; constructor(poolAddress: string) { diff --git a/packages/sdk-core/src/events.ts b/packages/sdk-core/src/events.ts index 3855686467..6f06fa367d 100644 --- a/packages/sdk-core/src/events.ts +++ b/packages/sdk-core/src/events.ts @@ -6,6 +6,7 @@ export type EventBase = { order: number; timestamp: number; logIndex: number; + name: string; }; export interface IEventFilter { @@ -435,5 +436,6 @@ export interface BondIncreasedEvent extends EventBase { } export interface UnknownEvent extends EventBase { - name: "_Unknown"; + // @note using the string type breaks the type guard + name: ""; } diff --git a/packages/sdk-core/src/index.ts b/packages/sdk-core/src/index.ts index 037dba5181..6834a8bc16 100644 --- a/packages/sdk-core/src/index.ts +++ b/packages/sdk-core/src/index.ts @@ -4,6 +4,7 @@ import BatchCall from "./BatchCall"; import ConstantFlowAgreementV1 from "./ConstantFlowAgreementV1"; import ERC20Token from "./ERC20Token"; import Framework from "./Framework"; +import GeneralDistributionAgreementV1 from "./GeneralDistributionAgreementV1"; import Governance from "./Governance"; import Host from "./Host"; import InstantDistributionAgreementV1 from "./InstantDistributionAgreementV1"; @@ -14,6 +15,7 @@ import SuperToken, { PureSuperToken, WrapperSuperToken, } from "./SuperToken"; +import SuperfluidPoolClass from "./SuperfluidPool"; export * from "./interfaces"; export * from "./constants"; @@ -32,6 +34,8 @@ export { Framework }; export { Governance }; export { Host }; export { InstantDistributionAgreementV1 }; +export { GeneralDistributionAgreementV1 }; +export { SuperfluidPoolClass }; export { NativeAssetSuperToken }; export { PureSuperToken }; export { Query }; diff --git a/packages/sdk-core/src/mapGetAllEventsQueryEvents.ts b/packages/sdk-core/src/mapGetAllEventsQueryEvents.ts index 4b35ace004..4323613dae 100644 --- a/packages/sdk-core/src/mapGetAllEventsQueryEvents.ts +++ b/packages/sdk-core/src/mapGetAllEventsQueryEvents.ts @@ -674,18 +674,21 @@ export const mapGetAllEventsQueryEvents = ( additionalBond: x.additionalBond, }); default: + // eslint-disable-next-line no-case-declarations + const eventBase = x as events.EventBase; console.warn( - "An unknown event was detected which couldn't be mapped. Please update to the latest version of @superfluid-finance/sdk-core." + `An unknown event [${eventBase.name}] was detected which couldn't be properly mapped. Please update to the latest version of @superfluid-finance/sdk-core.` ); return typeGuard({ - name: "_Unknown", - id: (x as events.EventBase).id, - blockNumber: (x as events.EventBase).blockNumber, - transactionHash: (x as events.EventBase).transactionHash, - gasPrice: (x as events.EventBase).gasPrice, - order: (x as events.EventBase).order, - timestamp: (x as events.EventBase).timestamp, - logIndex: (x as events.EventBase).logIndex, + // force casted as empty string for the type system + name: eventBase.name as "", + id: eventBase.id, + blockNumber: eventBase.blockNumber, + transactionHash: eventBase.transactionHash, + gasPrice: eventBase.gasPrice, + order: eventBase.order, + timestamp: eventBase.timestamp, + logIndex: eventBase.logIndex, }); } }); diff --git a/packages/sdk-core/src/types.ts b/packages/sdk-core/src/types.ts index 16704db8fa..70a02cc864 100644 --- a/packages/sdk-core/src/types.ts +++ b/packages/sdk-core/src/types.ts @@ -11,12 +11,12 @@ export type NetworkData = { addresses: { resolver: string; host: string; - governance: string; + governance?: string; cfaV1: string; cfaV1Forwarder: string; idaV1: string; superTokenFactory: string; superfluidLoader: string; - toga: string; + toga?: string; }; }; diff --git a/packages/sdk-core/src/utils.ts b/packages/sdk-core/src/utils.ts index 258a34702d..32741e0240 100644 --- a/packages/sdk-core/src/utils.ts +++ b/packages/sdk-core/src/utils.ts @@ -314,3 +314,14 @@ export const clipDepositNumber = (deposit: BigNumber, roundingDown = false) => { : 1; return deposit.shr(32).add(toBN(rounding)).shl(32); }; + +export async function tryGet( + somePromise: Promise, + defaultReturnValue: T +): Promise { + try { + return await somePromise; + } catch { + return defaultReturnValue; + } +} diff --git a/packages/sdk-core/test/1.0_supertoken.test.ts b/packages/sdk-core/test/1.0_supertoken.test.ts index 7b498c0cf8..1bd2107ff2 100644 --- a/packages/sdk-core/test/1.0_supertoken.test.ts +++ b/packages/sdk-core/test/1.0_supertoken.test.ts @@ -1,3 +1,4 @@ +import hre from "hardhat"; import { expect } from "chai"; import { NativeAssetSuperToken, SuperToken, toBN } from "../src"; import { ethers } from "ethers"; @@ -125,6 +126,17 @@ makeSuite("SuperToken Tests", (testEnv: TestEnvironment) => { } }); + it("Should support SuperToken without getUnderlyingToken() function implemented",async () => { + const noGetUnderlyingTokenFactory = await hre.ethers.getContractFactory("NoGetUnderlyingToken"); + const noGetUnderlyingToken = await noGetUnderlyingTokenFactory.deploy(); + await SuperToken.create({ + address: noGetUnderlyingToken.address, + provider: testEnv.alice.provider!, + config: testEnv.sdkFramework.settings.config, + networkName: "custom", + }); + }); + it("Should properly return totalSupply", async () => { const totalSupply = await testEnv.wrapperSuperToken.totalSupply({ providerOrSigner: testEnv.alice, diff --git a/packages/sdk-core/test/1.4_supertoken_gda.test.ts b/packages/sdk-core/test/1.4_supertoken_gda.test.ts index 32af84d7b2..c0043e7542 100644 --- a/packages/sdk-core/test/1.4_supertoken_gda.test.ts +++ b/packages/sdk-core/test/1.4_supertoken_gda.test.ts @@ -768,11 +768,11 @@ const shouldCreatePool = async ( expect( await superToken.isPool({ - account: data.poolAddress, + account: data.pool.contract.address, providerOrSigner: signer, }) ).to.be.true; - const pool = new SuperfluidPool(data.poolAddress); + const pool = new SuperfluidPool(data.pool.contract.address); expect(await pool.getPoolAdmin(signer)).to.be.equal(signer.address); expect(await pool.getSuperToken(signer)).to.be.equal(superToken.address); diff --git a/packages/subgraph/package.json b/packages/subgraph/package.json index 5bcc4b7580..f776c09a9d 100644 --- a/packages/subgraph/package.json +++ b/packages/subgraph/package.json @@ -18,6 +18,7 @@ "pretest": "yarn testenv:start", "test": "npx hardhat test", "matchstick": "run-s matchstick:*", + "matchstick:build-network-config": "npx ts-node scripts/buildNetworkConfig.ts polygon-mainnet", "matchstick:prepare-manifest": "mustache config/polygon-mainnet.json subgraph.template.yaml > subgraph.yaml", "matchstick:prepare-addresses": "mustache config/polygon-mainnet.json src/addresses.template.ts > src/addresses.ts", "matchstick:prepare-generated": "yarn getAbi && yarn codegen && yarn generate-sf-meta-local", @@ -51,11 +52,11 @@ "dependencies": { "@graphprotocol/graph-cli": "0.57.0", "@graphprotocol/graph-ts": "0.31.0", - "@superfluid-finance/sdk-core": "0.6.8", + "@superfluid-finance/sdk-core": "0.6.13", "mustache": "^4.2.0" }, "devDependencies": { - "@superfluid-finance/metadata": "1.1.17", + "@superfluid-finance/metadata": "1.1.21", "coingecko-api": "^1.0.10", "graphql": "^16.8.0", "graphql-request": "^6.1.0", diff --git a/packages/subgraph/schema.graphql b/packages/subgraph/schema.graphql index 2aaed85a02..8fd3b4a12d 100644 --- a/packages/subgraph/schema.graphql +++ b/packages/subgraph/schema.graphql @@ -722,6 +722,7 @@ type InstantDistributionUpdatedEvent implements Event @entity(immutable: true) { operator: Bytes! requestedAmount: BigInt! actualAmount: BigInt! + totalUnits: BigInt! userData: Bytes! pool: Pool! @@ -755,6 +756,7 @@ type FlowDistributionUpdatedEvent implements Event @entity(immutable: true) { newTotalDistributionFlowRate: BigInt! adjustmentFlowRecipient: Bytes! adjustmentFlowRate: BigInt! + totalUnits: BigInt! userData: Bytes! pool: Pool! @@ -811,6 +813,7 @@ type MemberUnitsUpdatedEvent implements Event @entity(immutable: true) { token: Bytes! oldUnits: BigInt! units: BigInt! + totalUnits: BigInt! pool: Pool! poolMember: PoolMember! diff --git a/packages/subgraph/scripts/buildNetworkConfig.ts b/packages/subgraph/scripts/buildNetworkConfig.ts index e2dd21ef26..fbf0aec5f2 100644 --- a/packages/subgraph/scripts/buildNetworkConfig.ts +++ b/packages/subgraph/scripts/buildNetworkConfig.ts @@ -26,8 +26,10 @@ function main() { if (!networkMetadata) { throw new Error("No metadata found"); } + const subgraphConfig: SubgraphConfig = { - network: networkMetadata.shortName, + // cliName exists for networks supported by the hosted service + network: networkMetadata.subgraphV1.cliName || networkMetadata.shortName, hostStartBlock: networkMetadata.startBlockV1, hostAddress: networkMetadata.contractsV1.host, cfaAddress: networkMetadata.contractsV1.cfaV1, @@ -36,14 +38,11 @@ function main() { superTokenFactoryAddress: networkMetadata.contractsV1.superTokenFactory, resolverV1Address: networkMetadata.contractsV1.resolver, nativeAssetSuperTokenAddress: networkMetadata.nativeTokenWrapper, - constantOutflowNFTAddress: - networkMetadata.contractsV1.constantOutflowNFT || ADDRESS_ZERO, - constantInflowNFTAddress: - networkMetadata.contractsV1.constantInflowNFT || ADDRESS_ZERO, + constantOutflowNFTAddress: networkMetadata.contractsV1.constantOutflowNFT || ADDRESS_ZERO, + constantInflowNFTAddress: networkMetadata.contractsV1.constantInflowNFT || ADDRESS_ZERO, }; - const writeToDir = - __dirname.split("subgraph")[0] + `subgraph/config/${networkName}.json`; + const writeToDir = __dirname.split("subgraph")[0] + `subgraph/config/${networkName}.json`; fs.writeFile(writeToDir, JSON.stringify(subgraphConfig), (err) => { if (err) { @@ -55,4 +54,4 @@ function main() { }); } -main(); \ No newline at end of file +main(); diff --git a/packages/subgraph/src/addresses.template.ts b/packages/subgraph/src/addresses.template.ts index 4edf31d65b..ad6559454c 100644 --- a/packages/subgraph/src/addresses.template.ts +++ b/packages/subgraph/src/addresses.template.ts @@ -15,7 +15,3 @@ export function getResolverAddress(): Address { export function getNativeAssetSuperTokenAddress(): Address { return Address.fromString("{{nativeAssetSuperTokenAddress}}"); } - -export function getIsLocalIntegrationTesting(): boolean { - return "{{testNetwork}}".length > 0; -} \ No newline at end of file diff --git a/packages/subgraph/src/mappingHelpers.ts b/packages/subgraph/src/mappingHelpers.ts index 672dc74581..65632f86b6 100644 --- a/packages/subgraph/src/mappingHelpers.ts +++ b/packages/subgraph/src/mappingHelpers.ts @@ -119,6 +119,7 @@ export function getOrInitSuperToken( ); token = handleTokenRPCCalls(token, resolverAddress); + token.isListed = false; const underlyingAddress = token.underlyingAddress; token.underlyingToken = underlyingAddress.toHexString(); diff --git a/packages/subgraph/src/mappings/flowNFT.ts b/packages/subgraph/src/mappings/flowNFT.ts index 9ac82c6ebe..a070abf8dd 100644 --- a/packages/subgraph/src/mappings/flowNFT.ts +++ b/packages/subgraph/src/mappings/flowNFT.ts @@ -15,6 +15,7 @@ import { createEventID, initializeEventEntity } from "../utils"; export function handleApproval(event: Approval): void { const eventId = createEventID("Approval", event); const ev = new ApprovalEvent(eventId); + initializeEventEntity(ev, event, []); ev.owner = event.params.owner.toHex(); ev.to = event.params.approved.toHex(); ev.tokenId = event.params.tokenId; diff --git a/packages/subgraph/src/mappings/gdav1.ts b/packages/subgraph/src/mappings/gdav1.ts index c66179c0ec..58f57be3ae 100644 --- a/packages/subgraph/src/mappings/gdav1.ts +++ b/packages/subgraph/src/mappings/gdav1.ts @@ -1,3 +1,4 @@ +import { BigInt } from "@graphprotocol/graph-ts"; import { BufferAdjusted, FlowDistributionUpdated, @@ -24,6 +25,7 @@ import { updateAggregateDistributionAgreementData, updatePoolDistributorTotalAmountFlowedAndDistributed, updatePoolTotalAmountFlowedAndDistributed, + updateSenderATSStreamData, updateTokenStatisticStreamData, updateTokenStatsStreamedUntilUpdatedAt, } from "../mappingHelpers"; @@ -167,7 +169,7 @@ export function handlePoolConnectionUpdated( _createTokenStatisticLogEntity(event, event.params.token, eventName); // Create Event Entity - _createPoolConnectionUpdatedEntity(event); + _createPoolConnectionUpdatedEntity(event, poolMember.id); } export function handleBufferAdjusted(event: BufferAdjusted): void { @@ -201,7 +203,7 @@ export function handleBufferAdjusted(event: BufferAdjusted): void { tokenStatistic.save(); // Create Event Entity - _createBufferAdjustedEntity(event); + _createBufferAdjustedEntity(event, poolDistributor.id); } export function handleFlowDistributionUpdated( @@ -252,6 +254,17 @@ export function handleFlowDistributionUpdated( _createTokenStatisticLogEntity(event, event.params.token, eventName); // Update ATS + updateSenderATSStreamData( + event.params.distributor, + event.params.token, + event.params.newDistributorToPoolFlowRate, + flowRateDelta, + BIG_INT_ZERO, + isCreate, + isDelete, + false, + event.block + ); updateATSStreamedAndBalanceUntilUpdatedAt( event.params.distributor, event.params.token, @@ -266,7 +279,7 @@ export function handleFlowDistributionUpdated( ); // Create Event Entity - _createFlowDistributionUpdatedEntity(event); + _createFlowDistributionUpdatedEntity(event, poolDistributor.id, pool.totalUnits); } export function handleInstantDistributionUpdated( @@ -344,7 +357,7 @@ export function handleInstantDistributionUpdated( ); // Create Event Entity - _createInstantDistributionUpdatedEntity(event); + _createInstantDistributionUpdatedEntity(event, poolDistributor.id, pool.totalUnits); } // Event Entity Creation Functions @@ -369,7 +382,8 @@ function _createPoolCreatedEntity(event: PoolCreated): PoolCreatedEvent { } function _createPoolConnectionUpdatedEntity( - event: PoolConnectionUpdated + event: PoolConnectionUpdated, + poolMemberId: string ): PoolConnectionUpdatedEvent { const ev = new PoolConnectionUpdatedEvent( createEventID("PoolConnectionUpdated", event) @@ -383,7 +397,7 @@ function _createPoolConnectionUpdatedEntity( ev.token = event.params.token; ev.connected = event.params.connected; ev.pool = event.params.pool.toHex(); - ev.poolMember = event.params.account.toHex(); + ev.poolMember = poolMemberId; ev.userData = event.params.userData; ev.save(); @@ -392,7 +406,8 @@ function _createPoolConnectionUpdatedEntity( } function _createBufferAdjustedEntity( - event: BufferAdjusted + event: BufferAdjusted, + poolDistributorId: string ): BufferAdjustedEvent { const ev = new BufferAdjustedEvent(createEventID("BufferAdjusted", event)); initializeEventEntity(ev, event, [ @@ -406,7 +421,7 @@ function _createBufferAdjustedEntity( ev.newBufferAmount = event.params.newBufferAmount; ev.totalBufferAmount = event.params.totalBufferAmount; ev.pool = event.params.pool.toHex(); - ev.poolDistributor = event.params.from.toHex(); + ev.poolDistributor = poolDistributorId; ev.save(); @@ -414,7 +429,9 @@ function _createBufferAdjustedEntity( } function _createInstantDistributionUpdatedEntity( - event: InstantDistributionUpdated + event: InstantDistributionUpdated, + poolDistributorId: string, + totalUnits: BigInt ): InstantDistributionUpdatedEvent { const ev = new InstantDistributionUpdatedEvent( createEventID("InstantDistributionUpdated", event) @@ -431,7 +448,8 @@ function _createInstantDistributionUpdatedEntity( ev.requestedAmount = event.params.requestedAmount; ev.actualAmount = event.params.actualAmount; ev.pool = event.params.pool.toHex(); - ev.poolDistributor = event.params.distributor.toHex(); + ev.poolDistributor = poolDistributorId; + ev.totalUnits = totalUnits; ev.userData = event.params.userData; ev.save(); @@ -440,7 +458,9 @@ function _createInstantDistributionUpdatedEntity( } function _createFlowDistributionUpdatedEntity( - event: FlowDistributionUpdated + event: FlowDistributionUpdated, + poolDistributorId: string, + totalUnits: BigInt ): FlowDistributionUpdatedEvent { const ev = new FlowDistributionUpdatedEvent( createEventID("FlowDistributionUpdated", event) @@ -460,7 +480,8 @@ function _createFlowDistributionUpdatedEntity( ev.adjustmentFlowRecipient = event.params.adjustmentFlowRecipient; ev.adjustmentFlowRate = event.params.adjustmentFlowRate; ev.pool = event.params.pool.toHex(); - ev.poolDistributor = event.params.distributor.toHex(); + ev.poolDistributor = poolDistributorId; + ev.totalUnits = totalUnits; ev.userData = event.params.userData; ev.save(); diff --git a/packages/subgraph/src/mappings/superfluidPool.ts b/packages/subgraph/src/mappings/superfluidPool.ts index da956f802a..cdc3e5eb6d 100644 --- a/packages/subgraph/src/mappings/superfluidPool.ts +++ b/packages/subgraph/src/mappings/superfluidPool.ts @@ -1,4 +1,4 @@ -import { log } from "@graphprotocol/graph-ts"; +import { BigInt } from "@graphprotocol/graph-ts"; import { DistributionClaimed, MemberUnitsUpdated, @@ -41,7 +41,7 @@ export function handleDistributionClaimed(event: DistributionClaimed): void { _createAccountTokenSnapshotLogEntity(event, event.params.member, token, eventName); // Create Event Entity - _createDistributionClaimedEntity(event); + _createDistributionClaimedEntity(event, poolMember.id); } export function handleMemberUnitsUpdated(event: MemberUnitsUpdated): void { @@ -125,10 +125,10 @@ export function handleMemberUnitsUpdated(event: MemberUnitsUpdated): void { } // Create Event Entity - _createMemberUnitsUpdatedEntity(event); + _createMemberUnitsUpdatedEntity(event, poolMember.id, pool.totalUnits); } -function _createDistributionClaimedEntity(event: DistributionClaimed): DistributionClaimedEvent { +function _createDistributionClaimedEntity(event: DistributionClaimed, poolMemberId: string): DistributionClaimedEvent { const ev = new DistributionClaimedEvent(createEventID("DistributionClaimed", event)); initializeEventEntity(ev, event, [event.params.token, event.address, event.params.member]); @@ -136,21 +136,26 @@ function _createDistributionClaimedEntity(event: DistributionClaimed): Distribut ev.claimedAmount = event.params.claimedAmount; ev.totalClaimed = event.params.totalClaimed; ev.pool = event.address.toHex(); - ev.poolMember = event.params.member.toHex(); + ev.poolMember = poolMemberId; ev.save(); return ev; } -function _createMemberUnitsUpdatedEntity(event: MemberUnitsUpdated): MemberUnitsUpdatedEvent { +function _createMemberUnitsUpdatedEntity( + event: MemberUnitsUpdated, + poolMemberId: string, + totalUnits: BigInt +): MemberUnitsUpdatedEvent { const ev = new MemberUnitsUpdatedEvent(createEventID("MemberUnitsUpdated", event)); initializeEventEntity(ev, event, [event.params.token, event.address, event.params.member]); ev.token = event.params.token; ev.oldUnits = event.params.oldUnits; ev.units = event.params.newUnits; + ev.totalUnits = totalUnits; ev.pool = event.address.toHex(); - ev.poolMember = event.params.member.toHex(); + ev.poolMember = poolMemberId; ev.save(); return ev; diff --git a/packages/subgraph/src/utils.ts b/packages/subgraph/src/utils.ts index bcd5a8dfe2..1d11509bc2 100644 --- a/packages/subgraph/src/utils.ts +++ b/packages/subgraph/src/utils.ts @@ -9,9 +9,12 @@ import { Value, } from "@graphprotocol/graph-ts"; import { ISuperToken as SuperToken } from "../generated/templates/SuperToken/ISuperToken"; -import { Resolver } from "../generated/ResolverV1/Resolver"; -import { IndexSubscription, PoolMember, Token, TokenStatistic } from "../generated/schema"; -import { getIsLocalIntegrationTesting } from "./addresses"; +import { + IndexSubscription, + Token, + TokenStatistic, + PoolMember, +} from "../generated/schema"; /************************************************************************** * Constants @@ -114,9 +117,6 @@ export function handleTokenRPCCalls( if (token.name.length == 0 || token.symbol.length == 0) { token = getTokenInfoAndReturn(token); } - - // we do getIsListedToken after getTokenInfoAndReturn because it requires the token symbol - token = getIsListedToken(token, resolverAddress); return token; } @@ -137,22 +137,6 @@ export function getTokenInfoAndReturn(token: Token): Token { return token; } -export function getIsListedToken( - token: Token, - resolverAddress: Address -): Token { - const resolverContract = Resolver.bind(resolverAddress); - const isLocalIntegrationTesting = getIsLocalIntegrationTesting(); - const version = isLocalIntegrationTesting ? "test" : "v1"; - const result = resolverContract.try_get( - "supertokens." + version + "." + token.symbol - ); - const superTokenAddress = result.reverted ? ZERO_ADDRESS : result.value; - token.isListed = token.id == superTokenAddress.toHex(); - - return token; -} - /** * Gets and sets the total supply for TokenStatistic of a SuperToken upon initial creation * @param tokenStatistic diff --git a/packages/subgraph/subgraph.template.yaml b/packages/subgraph/subgraph.template.yaml index 774e2e886b..ab144634cf 100644 --- a/packages/subgraph/subgraph.template.yaml +++ b/packages/subgraph/subgraph.template.yaml @@ -415,12 +415,6 @@ templates: - event: Approval(indexed address,indexed address,uint256) handler: handleApproval receipt: true - - event: ConstantOutflowNFTCreated(indexed address) - handler: handleConstantOutflowNFTCreated - receipt: true - - event: ConstantInflowNFTCreated(indexed address) - handler: handleConstantInflowNFTCreated - receipt: true - kind: ethereum/contract name: SuperfluidGovernance network: {{ network }} diff --git a/packages/subgraph/tasks/deploy.sh b/packages/subgraph/tasks/deploy.sh index b1f17b04ea..5afb9e84ec 100755 --- a/packages/subgraph/tasks/deploy.sh +++ b/packages/subgraph/tasks/deploy.sh @@ -15,7 +15,13 @@ GRAPH_NETWORKS=( $($JQ -r .[] ./hosted-service-networks.json) ) || exit 1 # shellcheck disable=SC2034 SATSUMA_NETWORKS=( "polygon-mainnet" "xdai-mainnet" "eth-mainnet" "eth-sepolia" "optimism-mainnet" "base-mainnet") # shellcheck disable=SC2034 -SUPERFLUID_NETWORKS=( "polygon-zkevm-testnet" "polygon-mainnet" "eth-sepolia" "base-goerli" "eth-mainnet" "xdai-mainnet" "base-mainnet" "optimism-mainnet" "arbitrum-one") +SUPERFLUID_NETWORKS=( "polygon-zkevm-testnet" "polygon-mainnet" "eth-sepolia" "base-goerli" "eth-mainnet" "xdai-mainnet" "base-mainnet" "optimism-mainnet" "arbitrum-one" "celo-mainnet" "bsc-mainnet" "avalanche-c") + +declare -A VENDOR_NETWORKS=( + ["graph"]="${GRAPH_NETWORKS[@]}" + ["satsuma"]="${SATSUMA_NETWORKS[@]}" + ["superfluid"]="${SUPERFLUID_NETWORKS[@]}" +) VENDOR="" NETWORK="" @@ -90,7 +96,7 @@ deploy_to_satsuma() { echo "********* Deploying $network subgraph to Satsuma. **********" $GRAPH_CLI deploy "$satsumaNetwork" \ --version-label "$VERSION_LABEL" \ - --node https://app.satsuma.xyz/api/subgraphs/deploy \ + --node https://subgraphs.alchemy.com/api/subgraphs/deploy \ --deploy-key "$SATSUMA_DEPLOY_KEY" \ --ipfs https://ipfs.satsuma.xyz } @@ -163,7 +169,7 @@ fi # Handle all vs specific network if [ "$NETWORK" == "all" ]; then - for network in "${NETWORKS_REF[@]}"; do + for network in ${VENDOR_NETWORKS[$VENDOR]}; do deploy_to "$VENDOR" "$network" done else diff --git a/packages/subgraph/tests/cfav1/cfav1.helper.ts b/packages/subgraph/tests/cfav1/cfav1.helper.ts index 3da3522fea..da77b88aa5 100644 --- a/packages/subgraph/tests/cfav1/cfav1.helper.ts +++ b/packages/subgraph/tests/cfav1/cfav1.helper.ts @@ -89,7 +89,7 @@ export function createFlowOperatorUpdatedEvent( * @param flowRate * @param previousSenderFlowRate * @param previousReceiverFlowRate - * @param isListed + * @param stringUserData * @returns FlowUpdated event */ export function modifyFlowAndAssertFlowUpdatedEventProperties( @@ -104,7 +104,6 @@ export function createFlowOperatorUpdatedEvent( flowRate: BigInt, previousSenderFlowRate: BigInt, previousReceiverFlowRate: BigInt, - isListed: boolean, stringUserData: string ): FlowUpdated { const oldFlowRate = previousSenderFlowRate.abs(); @@ -133,8 +132,7 @@ export function createFlowOperatorUpdatedEvent( tokenSymbol, underlyingToken, deposit, - expectedOwedDeposit, - isListed + expectedOwedDeposit ); handleFlowUpdated(flowUpdatedEvent); diff --git a/packages/subgraph/tests/cfav1/event/cfav1.event.test.ts b/packages/subgraph/tests/cfav1/event/cfav1.event.test.ts index 1223eeecf2..0403885aeb 100644 --- a/packages/subgraph/tests/cfav1/event/cfav1.event.test.ts +++ b/packages/subgraph/tests/cfav1/event/cfav1.event.test.ts @@ -6,17 +6,25 @@ import { describe, test, } from "matchstick-as/assembly/index"; +import { handleFlowOperatorUpdated } from "../../../src/mappings/cfav1"; import { - handleFlowOperatorUpdated, -} from "../../../src/mappings/cfav1"; -import { BIG_INT_ZERO, getFlowOperatorID, ZERO_ADDRESS } from "../../../src/utils"; -import {assertEventBaseProperties } from "../../assertionHelpers"; -import { alice, bob, maticXAddress, maticXName, maticXSymbol } from "../../constants"; + BIG_INT_ZERO, + getFlowOperatorID, + ZERO_ADDRESS, +} from "../../../src/utils"; +import { assertEventBaseProperties } from "../../assertionHelpers"; +import { + alice, + bob, + maticXAddress, + maticXName, + maticXSymbol, +} from "../../constants"; import { createFlowOperatorUpdatedEvent, modifyFlowAndAssertFlowUpdatedEventProperties, } from "../cfav1.helper"; -import {mockedApprove} from "../../mockedFunctions"; +import { mockedApprove } from "../../mockedFunctions"; const initialFlowRate = BigInt.fromI32(100); @@ -39,7 +47,6 @@ describe("ConstantFlowAgreementV1 Event Entity Unit Tests", () => { initialFlowRate, // flowRate BIG_INT_ZERO, // previousSenderFlowRate BIG_INT_ZERO, // previousReceiverFlowRate - true, // isListed, "" // userData ); }); @@ -58,7 +65,6 @@ describe("ConstantFlowAgreementV1 Event Entity Unit Tests", () => { initialFlowRate, // flowRate BIG_INT_ZERO, // previousSenderFlowRate BIG_INT_ZERO, // previousReceiverFlowRate - true, // isListed, "" // userData ); @@ -76,7 +82,6 @@ describe("ConstantFlowAgreementV1 Event Entity Unit Tests", () => { increasedFlowRate, // flowRate initialFlowRate, // previousSenderFlowRate initialFlowRate, // previousReceiverFlowRate - true, // isListed, "" // userData ); @@ -93,7 +98,6 @@ describe("ConstantFlowAgreementV1 Event Entity Unit Tests", () => { initialFlowRate, // flowRate increasedFlowRate, // previousSenderFlowRate increasedFlowRate, // previousReceiverFlowRate - true, // isListed, "" // userData ); }); @@ -112,7 +116,6 @@ describe("ConstantFlowAgreementV1 Event Entity Unit Tests", () => { initialFlowRate, // flowRate BIG_INT_ZERO, // previousSenderFlowRate BIG_INT_ZERO, // previousReceiverFlowRate - true, // isListed, "" // userData ); @@ -130,7 +133,6 @@ describe("ConstantFlowAgreementV1 Event Entity Unit Tests", () => { increasedFlowRate, // flowRate initialFlowRate, // previousSenderFlowRate initialFlowRate, // previousReceiverFlowRate - true, // isListed, "" // userData ); @@ -148,7 +150,6 @@ describe("ConstantFlowAgreementV1 Event Entity Unit Tests", () => { BIG_INT_ZERO, // flowRate increasedFlowRate, // previousSenderFlowRate increasedFlowRate, // previousReceiverFlowRate - true, // isListed, "" // userData ); }); diff --git a/packages/subgraph/tests/cfav1/hol/cfav1.hol.test.ts b/packages/subgraph/tests/cfav1/hol/cfav1.hol.test.ts index 90b4a83a78..5beb4a9368 100644 --- a/packages/subgraph/tests/cfav1/hol/cfav1.hol.test.ts +++ b/packages/subgraph/tests/cfav1/hol/cfav1.hol.test.ts @@ -27,19 +27,18 @@ describe("ConstantFlowAgreementV1 Higher Order Level Entity Unit Tests", () => { test("handleFlowUpdated() - Should create a new Stream entity (create)", () => { // create flow const flowUpdatedEvent = modifyFlowAndAssertFlowUpdatedEventProperties( - maticXAddress, // superToken - maticXName, // tokenName - maticXSymbol, // tokenSymbol - alice, // sender - bob, // receiver - ZERO_ADDRESS, // underlyingToken - "0", // expectedType - BIG_INT_ZERO, // expectedOwedDeposit - initialFlowRate, // flowRate - BIG_INT_ZERO, // previousSenderFlowRate - BIG_INT_ZERO, // previousReceiverFlowRate - true, // isListed, - "henlo" // userData + maticXAddress, // superToken + maticXName, // tokenName + maticXSymbol, // tokenSymbol + alice, // sender + bob, // receiver + ZERO_ADDRESS, // underlyingToken + "0", // expectedType + BIG_INT_ZERO, // expectedOwedDeposit + initialFlowRate, // flowRate + BIG_INT_ZERO, // previousSenderFlowRate + BIG_INT_ZERO, // previousReceiverFlowRate + "henlo" // userData ); const id = getStreamID( diff --git a/packages/subgraph/tests/gdav1/event/gdav1.event.test.ts b/packages/subgraph/tests/gdav1/event/gdav1.event.test.ts index 916709892e..ee21c7b029 100644 --- a/packages/subgraph/tests/gdav1/event/gdav1.event.test.ts +++ b/packages/subgraph/tests/gdav1/event/gdav1.event.test.ts @@ -1,13 +1,12 @@ -import { BigInt } from "@graphprotocol/graph-ts"; +import { Address, BigInt } from "@graphprotocol/graph-ts"; import { assert, beforeEach, clearStore, describe, test } from "matchstick-as/assembly/index"; import { handleBufferAdjusted, handleFlowDistributionUpdated, handleInstantDistributionUpdated, - handlePoolConnectionUpdated, } from "../../../src/mappings/gdav1"; -import { handleDistributionClaimed, handleMemberUnitsUpdated } from "../../../src/mappings/superfluidPool"; -import { BIG_INT_ZERO } from "../../../src/utils"; +import { handleDistributionClaimed } from "../../../src/mappings/superfluidPool"; +import { BIG_INT_ZERO, getPoolDistributorID, getPoolMemberID } from "../../../src/utils"; import { assertEventBaseProperties } from "../../assertionHelpers"; import { FAKE_INITIAL_BALANCE, FALSE, TRUE, alice, bob, maticXAddress, superfluidPool } from "../../constants"; import { @@ -15,9 +14,7 @@ import { createDistributionClaimedEvent, createFlowDistributionUpdatedEvent, createInstantDistributionUpdatedEvent, - createMemberUnitsUpdatedEvent, - createPoolAndReturnPoolCreatedEvent, - createPoolConnectionUpdatedEvent, + createPoolAndReturnPoolCreatedEvent } from "../gdav1.helper"; import { mockedGetAppManifest, mockedRealtimeBalanceOf } from "../../mockedFunctions"; import { updatePoolConnectionAndReturnPoolConnectionUpdatedEvent } from "../gdav1.helper"; @@ -57,11 +54,13 @@ describe("GeneralDistributionAgreementV1 Event Entity Unit Tests", () => { userData ); + const poolMemberId = getPoolMemberID(Address.fromString(superfluidPool), Address.fromString(account)); + const id = assertEventBaseProperties(poolConnectionUpdatedEvent, "PoolConnectionUpdated"); assert.fieldEquals("PoolConnectionUpdatedEvent", id, "token", superToken); assert.fieldEquals("PoolConnectionUpdatedEvent", id, "connected", TRUE); assert.fieldEquals("PoolConnectionUpdatedEvent", id, "pool", superfluidPool); - assert.fieldEquals("PoolConnectionUpdatedEvent", id, "poolMember", account); + assert.fieldEquals("PoolConnectionUpdatedEvent", id, "poolMember", poolMemberId); }); test("handlePoolConnectionUpdated() - Should create a new handlePoolConnectionUpdatedEvent entity (disconnected)", () => { @@ -78,11 +77,13 @@ describe("GeneralDistributionAgreementV1 Event Entity Unit Tests", () => { userData ); + const poolMemberId = getPoolMemberID(Address.fromString(superfluidPool), Address.fromString(account)); + const id = assertEventBaseProperties(poolConnectionUpdatedEvent, "PoolConnectionUpdated"); assert.fieldEquals("PoolConnectionUpdatedEvent", id, "token", superToken); assert.fieldEquals("PoolConnectionUpdatedEvent", id, "connected", FALSE); assert.fieldEquals("PoolConnectionUpdatedEvent", id, "pool", superfluidPool); - assert.fieldEquals("PoolConnectionUpdatedEvent", id, "poolMember", account); + assert.fieldEquals("PoolConnectionUpdatedEvent", id, "poolMember", poolMemberId); }); test("handleBufferAdjusted() - Should create a new handleBufferAdjustedEvent entity", () => { @@ -100,12 +101,17 @@ describe("GeneralDistributionAgreementV1 Event Entity Unit Tests", () => { totalBufferAmount ); + const poolDistributorId = getPoolDistributorID( + Address.fromString(superfluidPool), + Address.fromString(poolDistributor) + ); + handleBufferAdjusted(bufferAdjustedEvent); const id = assertEventBaseProperties(bufferAdjustedEvent, "BufferAdjusted"); assert.fieldEquals("BufferAdjustedEvent", id, "token", maticXAddress); assert.fieldEquals("BufferAdjustedEvent", id, "pool", superfluidPool); - assert.fieldEquals("BufferAdjustedEvent", id, "poolDistributor", poolDistributor); + assert.fieldEquals("BufferAdjustedEvent", id, "poolDistributor", poolDistributorId.toString()); assert.fieldEquals("BufferAdjustedEvent", id, "bufferDelta", bufferDelta.toString()); assert.fieldEquals("BufferAdjustedEvent", id, "newBufferAmount", newBufferAmount.toString()); assert.fieldEquals("BufferAdjustedEvent", id, "totalBufferAmount", totalBufferAmount.toString()); @@ -128,12 +134,17 @@ describe("GeneralDistributionAgreementV1 Event Entity Unit Tests", () => { userData ); + const poolDistributorId = getPoolDistributorID( + Address.fromString(superfluidPool), + Address.fromString(poolDistributor) + ); + handleInstantDistributionUpdated(instantDistributionUpdatedEvent); const id = assertEventBaseProperties(instantDistributionUpdatedEvent, "InstantDistributionUpdated"); assert.fieldEquals("InstantDistributionUpdatedEvent", id, "token", superToken); assert.fieldEquals("InstantDistributionUpdatedEvent", id, "pool", superfluidPool); - assert.fieldEquals("InstantDistributionUpdatedEvent", id, "poolDistributor", poolDistributor); + assert.fieldEquals("InstantDistributionUpdatedEvent", id, "poolDistributor", poolDistributorId.toString()); assert.fieldEquals("InstantDistributionUpdatedEvent", id, "operator", operator); assert.fieldEquals("InstantDistributionUpdatedEvent", id, "requestedAmount", requestedAmount.toString()); assert.fieldEquals("InstantDistributionUpdatedEvent", id, "actualAmount", actualAmount.toString()); @@ -162,12 +173,17 @@ describe("GeneralDistributionAgreementV1 Event Entity Unit Tests", () => { userData ); + const poolDistributorId = getPoolDistributorID( + Address.fromString(superfluidPool), + Address.fromString(poolDistributor) + ); + handleFlowDistributionUpdated(flowDistributionUpdatedEvent); const id = assertEventBaseProperties(flowDistributionUpdatedEvent, "FlowDistributionUpdated"); assert.fieldEquals("FlowDistributionUpdatedEvent", id, "token", superToken); assert.fieldEquals("FlowDistributionUpdatedEvent", id, "pool", superfluidPool); - assert.fieldEquals("FlowDistributionUpdatedEvent", id, "poolDistributor", poolDistributor); + assert.fieldEquals("FlowDistributionUpdatedEvent", id, "poolDistributor", poolDistributorId.toString()); assert.fieldEquals("FlowDistributionUpdatedEvent", id, "operator", operator); assert.fieldEquals("FlowDistributionUpdatedEvent", id, "oldFlowRate", oldFlowRate.toString()); assert.fieldEquals( @@ -211,13 +227,15 @@ describe("GeneralDistributionAgreementV1 Event Entity Unit Tests", () => { BIG_INT_ZERO ); + const poolMemberId = getPoolMemberID(distributionClaimedEvent.address, Address.fromString(poolMember)); + handleDistributionClaimed(distributionClaimedEvent); const id = assertEventBaseProperties(distributionClaimedEvent, "DistributionClaimed"); assert.fieldEquals("DistributionClaimedEvent", id, "token", superToken); assert.fieldEquals("DistributionClaimedEvent", id, "claimedAmount", claimedAmount.toString()); assert.fieldEquals("DistributionClaimedEvent", id, "totalClaimed", totalClaimed.toString()); - assert.fieldEquals("DistributionClaimedEvent", id, "poolMember", poolMember); + assert.fieldEquals("DistributionClaimedEvent", id, "poolMember", poolMemberId.toString()); }); test("handleMemberUnitsUpdated() - Should create a new MemberUnitsUpdatedEvent entity", () => { @@ -232,9 +250,11 @@ describe("GeneralDistributionAgreementV1 Event Entity Unit Tests", () => { newUnits ); + const poolMemberId = getPoolMemberID(memberUnitsUpdatedEvent.address, Address.fromString(poolMember)); + const id = assertEventBaseProperties(memberUnitsUpdatedEvent, "MemberUnitsUpdated"); assert.fieldEquals("MemberUnitsUpdatedEvent", id, "token", superToken); - assert.fieldEquals("MemberUnitsUpdatedEvent", id, "poolMember", poolMember); + assert.fieldEquals("MemberUnitsUpdatedEvent", id, "poolMember", poolMemberId.toString()); assert.fieldEquals("MemberUnitsUpdatedEvent", id, "units", newUnits.toString()); }); }); diff --git a/packages/subgraph/tests/idav1/event/idav1.event.test.ts b/packages/subgraph/tests/idav1/event/idav1.event.test.ts index 3e67090161..7bc6e08288 100644 --- a/packages/subgraph/tests/idav1/event/idav1.event.test.ts +++ b/packages/subgraph/tests/idav1/event/idav1.event.test.ts @@ -57,8 +57,7 @@ describe("InstantDistributionV1 Event Entity Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, maticXName, - maticXSymbol, - true + maticXSymbol ); // getOrInitIndex(event) => getOrInitAccount(publisher) => host.try_getAppManifest(sender) diff --git a/packages/subgraph/tests/mockedEntities.ts b/packages/subgraph/tests/mockedEntities.ts index d553ebbad8..46fa90597f 100644 --- a/packages/subgraph/tests/mockedEntities.ts +++ b/packages/subgraph/tests/mockedEntities.ts @@ -5,8 +5,6 @@ import { getStreamID } from "../src/utils"; /** * Creates a SuperToken entity - * Note: this is needed otherwise we get a null error when we try - * run getIsListedToken and it tries to access token.symbol * @param tokenAddress the address of the token * @param block transaction block object * @param decimals number of decimals diff --git a/packages/subgraph/tests/mockedFunctions.ts b/packages/subgraph/tests/mockedFunctions.ts index 4a4eba20f5..88629bdc57 100644 --- a/packages/subgraph/tests/mockedFunctions.ts +++ b/packages/subgraph/tests/mockedFunctions.ts @@ -1,12 +1,11 @@ import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; import { createMockedFunction } from "matchstick-as/assembly/index"; import { FlowUpdated } from "../generated/ConstantFlowAgreementV1/IConstantFlowAgreementV1"; -import { BIG_INT_ZERO, ZERO_ADDRESS } from "../src/utils"; +import { BIG_INT_ZERO } from "../src/utils"; import { FAKE_INITIAL_BALANCE, FAKE_SUPER_TOKEN_TOTAL_SUPPLY, hostAddress, - resolverAddress, } from "./constants"; import { getETHAddress, @@ -28,15 +27,13 @@ import { * @param underlyingAddress * @param tokenName * @param tokenSymbol - * @param isListed */ export function mockedHandleSuperTokenInitRPCCalls( superToken: string, decimals: i32, underlyingAddress: Address, tokenName: string, - tokenSymbol: string, - isListed: boolean + tokenSymbol: string ): void { // [START] getTokenInfoAndReturn => // token.try_getUnderlyingToken() @@ -49,13 +46,6 @@ export function mockedHandleSuperTokenInitRPCCalls( mockedTokenDecimals(superToken, decimals); // [END] getTokenInfoAndReturn - // getIsListedToken(token, resolver) => resolver.try_get(key) - mockedResolverGet( - resolverAddress, - "supertokens.v1." + tokenSymbol, - isListed ? superToken : ZERO_ADDRESS.toHexString() - ); - // updateTotalSupplyForNativeSuperToken(token, tokenStatistic, tokenAddress) mockedTokenTotalSupply(superToken, FAKE_SUPER_TOKEN_TOTAL_SUPPLY); } @@ -70,7 +60,6 @@ export function mockedHandleSuperTokenInitRPCCalls( * @param underlyingAddress * @param expectedDeposit * @param expectedOwedDeposit - * @param isListed */ export function mockedHandleFlowUpdatedRPCCalls( flowUpdatedEvent: FlowUpdated, @@ -80,8 +69,7 @@ export function mockedHandleFlowUpdatedRPCCalls( tokenSymbol: string, underlyingAddress: Address, expectedDeposit: BigInt, - expectedOwedDeposit: BigInt, - isListed: boolean + expectedOwedDeposit: BigInt ): void { const sender = flowUpdatedEvent.params.sender.toHex(); const receiver = flowUpdatedEvent.params.receiver.toHex(); @@ -113,8 +101,7 @@ export function mockedHandleFlowUpdatedRPCCalls( decimals, underlyingAddress, tokenName, - tokenSymbol, - isListed + tokenSymbol ); // [END] getOrInitStream(event) => getOrInitSuperToken(token, block) => handleTokenRPCCalls(token, resolverAddress) diff --git a/packages/subgraph/tests/superToken/event/superToken.event.test.ts b/packages/subgraph/tests/superToken/event/superToken.event.test.ts index 0f4a3d1440..4a335bd4c0 100644 --- a/packages/subgraph/tests/superToken/event/superToken.event.test.ts +++ b/packages/subgraph/tests/superToken/event/superToken.event.test.ts @@ -96,8 +96,7 @@ describe("SuperToken Mapper Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, maticXName, - maticXSymbol, - false + maticXSymbol ); mockedRealtimeBalanceOf( @@ -211,8 +210,7 @@ describe("SuperToken Mapper Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, maticXName, - maticXSymbol, - false + maticXSymbol ); mockedRealtimeBalanceOf( diff --git a/packages/subgraph/tests/superTokenFactory/superTokenFactory.test.ts b/packages/subgraph/tests/superTokenFactory/superTokenFactory.test.ts index 9e984c3b27..f070724e68 100644 --- a/packages/subgraph/tests/superTokenFactory/superTokenFactory.test.ts +++ b/packages/subgraph/tests/superTokenFactory/superTokenFactory.test.ts @@ -55,8 +55,7 @@ describe("SuperTokenFactory Mapper Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, maticXName, - maticXSymbol, - false + maticXSymbol ); handleSuperTokenCreated(SuperTokenCreatedEvent); @@ -83,8 +82,7 @@ describe("SuperTokenFactory Mapper Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, maticXName, - maticXSymbol, - false + maticXSymbol ); handleCustomSuperTokenCreated(CustomSuperTokenCreatedEvent); @@ -138,8 +136,7 @@ describe("SuperTokenFactory Mapper Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, maticXName, - maticXSymbol, - false // isListed + maticXSymbol ); handleSuperTokenCreated(SuperTokenCreatedEvent); @@ -168,8 +165,7 @@ describe("SuperTokenFactory Mapper Unit Tests", () => { DEFAULT_DECIMALS, Address.fromString(daiAddress), daiXName, - daiXSymbol, - false + daiXSymbol ); // for getOrInitToken ((PoS) Dai Stablecoin (DAI)) mockedHandleSuperTokenInitRPCCalls( @@ -177,8 +173,7 @@ describe("SuperTokenFactory Mapper Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, daiName, - daiSymbol, - false + daiSymbol ); handleSuperTokenCreated(SuperTokenCreatedEvent); @@ -226,8 +221,7 @@ describe("SuperTokenFactory Mapper Unit Tests", () => { DEFAULT_DECIMALS, ZERO_ADDRESS, maticXName, - maticXSymbol, - false // isListed + maticXSymbol ); handleSuperTokenCreated(SuperTokenCreatedEvent); diff --git a/yarn.lock b/yarn.lock index ef69c46735..4cc83819f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -168,6 +168,14 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.5": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" @@ -240,6 +248,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -300,6 +318,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" @@ -313,20 +336,13 @@ "@babel/template" "^7.20.7" "@babel/types" "^7.21.0" -"@babel/helper-function-name@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" - integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: - "@babel/template" "^7.22.5" - "@babel/types" "^7.22.5" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" @@ -460,6 +476,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" @@ -502,6 +523,15 @@ chalk "^2.4.2" js-tokens "^4.0.0" +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.14.0", "@babel/parser@^7.16.8", "@babel/parser@^7.20.7", "@babel/parser@^7.21.3": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3" @@ -512,6 +542,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55" integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ== +"@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + "@babel/plugin-proposal-class-properties@^7.0.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" @@ -754,6 +789,15 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" +"@babel/template@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + "@babel/template@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -763,35 +807,19 @@ "@babel/parser" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3": - version "7.21.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.3.tgz#4747c5e7903d224be71f90788b06798331896f67" - integrity sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.3" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.3" - "@babel/types" "^7.21.3" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa" - integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig== +"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3", "@babel/traverse@^7.22.10": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== dependencies: - "@babel/code-frame" "^7.22.10" - "@babel/generator" "^7.22.10" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.10" - "@babel/types" "^7.22.10" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" debug "^4.1.0" globals "^11.1.0" @@ -813,6 +841,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.22.15", "@babel/types@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@chainsafe/as-sha256@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" @@ -1416,6 +1453,11 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" +"@fastify/busboy@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" + integrity sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ== + "@float-capital/float-subgraph-uncrashable@^0.0.0-alpha.4": version "0.0.0-internal-testing.5" resolved "https://registry.yarnpkg.com/@float-capital/float-subgraph-uncrashable/-/float-subgraph-uncrashable-0.0.0-internal-testing.5.tgz#060f98440f6e410812766c5b040952d2d02e2b73" @@ -2588,7 +2630,7 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" -"@nomiclabs/hardhat-ethers@^2.2.1", "@nomiclabs/hardhat-ethers@^2.2.3": +"@nomiclabs/hardhat-ethers@^2.2.3": version "2.2.3" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== @@ -2985,11 +3027,6 @@ find-up "^4.1.0" fs-extra "^8.1.0" -"@openzeppelin/contracts@4.8.2": - version "4.8.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.2.tgz#d815ade0027b50beb9bcca67143c6bcc3e3923d6" - integrity sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g== - "@openzeppelin/contracts@4.9.3": version "4.9.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.3.tgz#00d7a8cf35a475b160b3f0293a6403c511099364" @@ -3482,37 +3519,6 @@ dependencies: antlr4ts "^0.5.0-alpha.4" -"@superfluid-finance/ethereum-contracts@1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@superfluid-finance/ethereum-contracts/-/ethereum-contracts-1.7.1.tgz#e2f08bed42694e94980199607ed9d3222faeb477" - integrity sha512-MPimKMSbvJOUkbMzGA2oNdGZrKpJnja3OGS4NdsRO+OxBya2XOTvoy55nb3H/u63IFagoKt6L7eSoJapKtjDrA== - dependencies: - "@decentral.ee/web3-helpers" "0.5.3" - "@openzeppelin/contracts" "4.8.2" - "@superfluid-finance/js-sdk" "0.6.3" - "@truffle/contract" "4.6.18" - ethereumjs-tx "2.1.2" - ethereumjs-util "7.1.5" - stack-trace "0.0.10" - -"@superfluid-finance/metadata@1.1.10": - version "1.1.10" - resolved "https://registry.yarnpkg.com/@superfluid-finance/metadata/-/metadata-1.1.10.tgz#980991d60066f21646d29eb01a9080c7fae1493d" - integrity sha512-IbcpfB/pOwjl/Vam0d1WXNJaeA0bUW/CkQEZlEhUpL+DQh01d6TnxneEjw3VsT9alqamtycKoi6+2uPHAzyvFA== - -"@superfluid-finance/sdk-core@0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@superfluid-finance/sdk-core/-/sdk-core-0.6.8.tgz#9ca45546cab97de47eb7e8f4ea190bd7a62fc440" - integrity sha512-OoID1Hmu3OJxXmU7P8+VFsU1sFw587Bak27pzwltm64Te7v0lY7HutcOUL4LaHFmqWhaxKoKqwDPNodxU4hVHA== - dependencies: - "@nomiclabs/hardhat-ethers" "^2.2.1" - "@superfluid-finance/ethereum-contracts" "1.7.1" - "@superfluid-finance/metadata" "1.1.10" - browserify "^17.0.0" - graphql-request "^4.3.0" - lodash "^4.17.21" - tsify "^5.0.4" - "@szmarczak/http-timer@^4.0.5": version "4.0.6" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" @@ -3722,26 +3728,6 @@ debug "^4.3.1" glob "^7.1.6" -"@truffle/contract@4.6.18", "@truffle/contract@^4.0.35", "@truffle/contract@^4.6.18": - version "4.6.18" - resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.6.18.tgz#096f82dbc05060acc9ed0bd8bb5811f497b8e3ad" - integrity sha512-x49EWZI16VMdYV8pH2LYM1AMFM3xAZ6ZFT2dG9Y71nIDZHdh+HKdlPSL40CqFtzpeoEk9UQoSJL99D/DXtpaog== - dependencies: - "@ensdomains/ensjs" "^2.1.0" - "@truffle/blockchain-utils" "^0.1.7" - "@truffle/contract-schema" "^3.4.13" - "@truffle/debug-utils" "^6.0.47" - "@truffle/error" "^0.2.0" - "@truffle/interface-adapter" "^0.5.31" - bignumber.js "^7.2.1" - debug "^4.3.1" - ethers "^4.0.32" - web3 "1.8.2" - web3-core-helpers "1.8.2" - web3-core-promievent "1.8.2" - web3-eth-abi "1.8.2" - web3-utils "1.8.2" - "@truffle/contract@4.6.29": version "4.6.29" resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.6.29.tgz#c1f0b9f65985ba5d8f35626a612dd31205cfcd6b" @@ -3762,6 +3748,26 @@ web3-eth-abi "1.10.0" web3-utils "1.10.0" +"@truffle/contract@^4.0.35", "@truffle/contract@^4.6.18": + version "4.6.18" + resolved "https://registry.yarnpkg.com/@truffle/contract/-/contract-4.6.18.tgz#096f82dbc05060acc9ed0bd8bb5811f497b8e3ad" + integrity sha512-x49EWZI16VMdYV8pH2LYM1AMFM3xAZ6ZFT2dG9Y71nIDZHdh+HKdlPSL40CqFtzpeoEk9UQoSJL99D/DXtpaog== + dependencies: + "@ensdomains/ensjs" "^2.1.0" + "@truffle/blockchain-utils" "^0.1.7" + "@truffle/contract-schema" "^3.4.13" + "@truffle/debug-utils" "^6.0.47" + "@truffle/error" "^0.2.0" + "@truffle/interface-adapter" "^0.5.31" + bignumber.js "^7.2.1" + debug "^4.3.1" + ethers "^4.0.32" + web3 "1.8.2" + web3-core-helpers "1.8.2" + web3-core-promievent "1.8.2" + web3-eth-abi "1.8.2" + web3-utils "1.8.2" + "@truffle/dashboard-message-bus-client@^0.1.10": version "0.1.10" resolved "https://registry.yarnpkg.com/@truffle/dashboard-message-bus-client/-/dashboard-message-bus-client-0.1.10.tgz#bd1cef19956f06716d55a327b8ea6f983e41f0b0" @@ -6036,7 +6042,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2.1: +bn.js@^5.0.0, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== @@ -6186,7 +6192,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== @@ -6195,19 +6201,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" + integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.4" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.6" + readable-stream "^3.6.2" + safe-buffer "^5.2.1" browserify-zlib@~0.2.0: version "0.2.0" @@ -10562,15 +10568,6 @@ graphql-import-node@^0.0.5: resolved "https://registry.yarnpkg.com/graphql-import-node/-/graphql-import-node-0.0.5.tgz#caf76a6cece10858b14f27cce935655398fc1bf0" integrity sha512-OXbou9fqh9/Lm7vwXT0XoRN9J5+WCYKnbiTalgFDvkQERITRmcfncZs6aVABedd5B85yQU5EULS4a5pnbpuI0Q== -graphql-request@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" - integrity sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow== - dependencies: - cross-fetch "^3.1.5" - extract-files "^9.0.0" - form-data "^3.0.0" - graphql-request@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-5.2.0.tgz#a05fb54a517d91bb2d7aefa17ade4523dc5ebdca" @@ -14884,7 +14881,7 @@ parents@^1.0.0, parents@^1.0.1: dependencies: path-platform "~0.11.15" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: +parse-asn1@^5.0.0, parse-asn1@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== @@ -15954,7 +15951,7 @@ readable-stream@1.1.14, readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0, readable-stream@^3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -18433,11 +18430,11 @@ underscore@^1.8.3: integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== undici@^5.14.0: - version "5.21.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.21.0.tgz#b00dfc381f202565ab7f52023222ab862bb2494f" - integrity sha512-HOjK8l6a57b2ZGXOcUsI5NLfoTrfmbOl90ixJDl0AEFG4wgHNDQxtZy15/ZQp7HhjkpaGlp/eneMgtsu1dIlUA== + version "5.26.3" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.26.3.tgz#ab3527b3d5bb25b12f898dfd22165d472dd71b79" + integrity sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw== dependencies: - busboy "^1.6.0" + "@fastify/busboy" "^2.0.0" unique-filename@^3.0.0: version "3.0.0"