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 @@
-
+
-
+
-
+
-
+
-
+
-
+
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