@gooddollar/goodcollective-contracts 1.0.6-beta.0b8171a → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/contracts/DirectPayments/DirectPaymentsFactory.sol +31 -13
- package/contracts/DirectPayments/DirectPaymentsPool.sol +25 -9
- package/contracts/GoodCollective/GoodCollectiveSuperApp.sol +35 -53
- package/contracts/GoodCollective/IGoodCollectiveSuperApp.sol +6 -0
- package/contracts/UBI/UBIPool.sol +400 -0
- package/contracts/UBI/UBIPoolFactory.sol +168 -0
- package/contracts/test/HelperLibraryTest.sol +16 -0
- package/contracts/utils/HelperLibrary.sol +77 -11
- package/contracts/utils/SwapRouterMock.sol +3 -3
- package/package.json +7 -5
- package/releases/deployment.json +25493 -306
- package/typechain-types/@gooddollar/goodprotocol/contracts/token/index.ts +0 -2
- package/typechain-types/@gooddollar/goodprotocol/contracts/token/superfluid/ISuperGoodDollar.sol/ISuperGoodDollar.ts +30 -30
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/IConstantFlowAgreementV1.ts +122 -0
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperToken.ts +30 -30
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.ts +7 -2
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidGovernance.ts +57 -8
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/ISETH.sol/ISETH.ts +2905 -0
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/ISETH.sol/ISETHCustom.ts +170 -0
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/ISETH.sol/index.ts +5 -0
- package/typechain-types/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/index.ts +2 -0
- package/typechain-types/@uniswap/index.ts +2 -2
- package/typechain-types/@uniswap/{v3-periphery/contracts/interfaces/ISwapRouter.ts → swap-router-contracts/contracts/interfaces/IV3SwapRouter.ts} +32 -44
- package/typechain-types/{@gooddollar/goodprotocol/contracts/token/FeesFormula.sol → @uniswap/swap-router-contracts/contracts/interfaces}/index.ts +1 -1
- package/typechain-types/contracts/DirectPayments/DirectPaymentsFactory.sol/DirectPaymentsFactory.ts +1327 -0
- package/typechain-types/contracts/DirectPayments/DirectPaymentsFactory.sol/IRegistry.ts +102 -0
- package/typechain-types/contracts/DirectPayments/DirectPaymentsFactory.sol/index.ts +5 -0
- package/typechain-types/contracts/DirectPayments/DirectPaymentsFactory.ts +139 -0
- package/typechain-types/contracts/DirectPayments/DirectPaymentsPool.sol/DirectPaymentsPool.ts +49 -0
- package/typechain-types/contracts/DirectPayments/DirectPaymentsPool.sol/IIdentityV2.ts +6 -8
- package/typechain-types/contracts/GoodCollective/GoodCollectiveSuperApp.ts +49 -0
- package/typechain-types/contracts/GoodCollective/IGoodCollectiveSuperApp.sol/IRegistry.ts +102 -0
- package/typechain-types/{@uniswap/v3-periphery/contracts/interfaces → contracts/GoodCollective/IGoodCollectiveSuperApp.sol}/index.ts +1 -1
- package/typechain-types/contracts/GoodCollective/index.ts +2 -0
- package/typechain-types/{@gooddollar/goodprotocol/contracts/token/FeesFormula.sol/IFeesFormula.ts → contracts/UBI/UBIPool.sol/IIdentityV2.ts} +25 -37
- package/typechain-types/contracts/UBI/UBIPool.sol/IMembersValidator.ts +125 -0
- package/typechain-types/contracts/UBI/UBIPool.sol/UBIPool.ts +2377 -0
- package/typechain-types/contracts/UBI/UBIPool.sol/index.ts +6 -0
- package/typechain-types/contracts/UBI/UBIPoolFactory.ts +1317 -0
- package/typechain-types/contracts/UBI/index.ts +6 -0
- package/typechain-types/contracts/index.ts +4 -0
- package/typechain-types/contracts/test/HelperLibraryTest.ts +147 -0
- package/typechain-types/contracts/test/index.ts +4 -0
- package/typechain-types/contracts/utils/SwapRouterMock.ts +15 -21
- package/typechain-types/factories/@gooddollar/goodprotocol/contracts/token/index.ts +0 -1
- package/typechain-types/factories/@gooddollar/goodprotocol/contracts/token/superfluid/ISuperGoodDollar.sol/ISuperGoodDollar__factory.ts +6 -6
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/IConstantFlowAgreementV1__factory.ts +78 -0
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperToken__factory.ts +6 -6
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluidGovernance__factory.ts +23 -5
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid__factory.ts +5 -0
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/ISETH.sol/ISETHCustom__factory.ts +59 -0
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/ISETH.sol/ISETH__factory.ts +1869 -0
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/ISETH.sol/index.ts +5 -0
- package/typechain-types/factories/@superfluid-finance/ethereum-contracts/contracts/interfaces/tokens/index.ts +1 -0
- package/typechain-types/factories/@uniswap/index.ts +1 -1
- package/typechain-types/factories/@uniswap/{v3-periphery/contracts/interfaces/ISwapRouter__factory.ts → swap-router-contracts/contracts/interfaces/IV3SwapRouter__factory.ts} +12 -32
- package/typechain-types/factories/{@gooddollar/goodprotocol/contracts/token/FeesFormula.sol → @uniswap/swap-router-contracts/contracts/interfaces}/index.ts +1 -1
- package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsFactory.sol/DirectPaymentsFactory__factory.ts +1004 -0
- package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsFactory.sol/IRegistry__factory.ts +52 -0
- package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsFactory.sol/index.ts +5 -0
- package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsFactory__factory.ts +75 -1
- package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsPool.sol/DirectPaymentsPool__factory.ts +60 -4
- package/typechain-types/factories/contracts/DirectPayments/DirectPaymentsPool.sol/IIdentityV2__factory.ts +1 -1
- package/typechain-types/factories/contracts/GoodCollective/GoodCollectiveSuperApp__factory.ts +58 -2
- package/typechain-types/factories/contracts/GoodCollective/IGoodCollectiveSuperApp.sol/IRegistry__factory.ts +52 -0
- package/typechain-types/factories/contracts/GoodCollective/IGoodCollectiveSuperApp.sol/index.ts +4 -0
- package/typechain-types/factories/contracts/GoodCollective/index.ts +1 -0
- package/typechain-types/factories/contracts/UBI/UBIPool.sol/IIdentityV2__factory.ts +45 -0
- package/typechain-types/factories/{@gooddollar/goodprotocol/contracts/token/FeesFormula.sol/IFeesFormula__factory.ts → contracts/UBI/UBIPool.sol/IMembersValidator__factory.ts} +21 -21
- package/typechain-types/factories/contracts/UBI/UBIPool.sol/UBIPool__factory.ts +1916 -0
- package/typechain-types/factories/contracts/UBI/UBIPool.sol/index.ts +6 -0
- package/typechain-types/factories/contracts/UBI/UBIPoolFactory__factory.ts +982 -0
- package/typechain-types/factories/contracts/UBI/index.ts +5 -0
- package/typechain-types/factories/contracts/index.ts +2 -0
- package/typechain-types/factories/contracts/test/HelperLibraryTest__factory.ts +154 -0
- package/typechain-types/factories/contracts/test/index.ts +4 -0
- package/typechain-types/factories/contracts/utils/HelperLibrary__factory.ts +1 -1
- package/typechain-types/factories/contracts/utils/SwapRouterMock__factory.ts +3 -13
- package/typechain-types/hardhat.d.ts +80 -17
- package/typechain-types/index.ts +16 -4
- package/typechain-types/factories/@uniswap/v3-periphery/contracts/interfaces/index.ts +0 -4
- /package/typechain-types/@uniswap/{v3-periphery → swap-router-contracts}/contracts/index.ts +0 -0
- /package/typechain-types/@uniswap/{v3-periphery → swap-router-contracts}/index.ts +0 -0
- /package/typechain-types/factories/@uniswap/{v3-periphery → swap-router-contracts}/contracts/index.ts +0 -0
- /package/typechain-types/factories/@uniswap/{v3-periphery → swap-router-contracts}/index.ts +0 -0
package/README.md
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Contracts
|
|
2
|
+
|
|
3
|
+
## Structs
|
|
4
|
+
|
|
5
|
+
### Pool Settings
|
|
6
|
+
|
|
7
|
+
- `nftType`: 1, // when you update the settings with setPoolSettings, `nftType` should always match what has been set when creating the pool
|
|
8
|
+
- `uniquenessValidator`: `ethers.constants.AddressZero`,
|
|
9
|
+
- `rewardPerEvent`: `[100, 300]`,
|
|
10
|
+
- `validEvents`: `[1, 2]`, // to be defined
|
|
11
|
+
- `manager`: `<address of the owner/creator of the pool>`,
|
|
12
|
+
- `membersValidator`: `ethers.constants.AddressZero`, // used to only accept certain members (address zero for anyone can join)
|
|
13
|
+
- `rewardToken`: `'0x62B8B11039FcfE5aB0C56E502b1C372A3d2a9c7A'`, // what token will a steward/member receive. currently only supports production G$'s
|
|
14
|
+
- `allowRewardOverride`: `false`,
|
|
@@ -15,6 +15,7 @@ import "hardhat/console.sol";
|
|
|
15
15
|
|
|
16
16
|
contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
|
|
17
17
|
error NOT_PROJECT_OWNER();
|
|
18
|
+
error NOT_POOL();
|
|
18
19
|
|
|
19
20
|
event PoolCreated(
|
|
20
21
|
address indexed pool,
|
|
@@ -45,6 +46,9 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
|
|
|
45
46
|
address public feeRecipient;
|
|
46
47
|
uint32 public feeBps;
|
|
47
48
|
|
|
49
|
+
mapping(address => address[]) public memberPools;
|
|
50
|
+
address[] public pools;
|
|
51
|
+
|
|
48
52
|
modifier onlyProjectOwnerOrNon(string memory projectId) {
|
|
49
53
|
DirectPaymentsPool controlPool = projectIdToControlPool[keccak256(bytes(projectId))];
|
|
50
54
|
// console.log("result %s", controlPool.hasRole(controlPool.DEFAULT_ADMIN_ROLE(), msg.sender));
|
|
@@ -56,16 +60,21 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
|
|
|
56
60
|
_;
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
modifier
|
|
60
|
-
|
|
61
|
-
DirectPaymentsPool controlPool = projectIdToControlPool[keccak256(bytes(projectId))];
|
|
62
|
-
if (controlPool.hasRole(controlPool.DEFAULT_ADMIN_ROLE(), msg.sender) == false) {
|
|
63
|
+
modifier onlyPoolOwner(DirectPaymentsPool pool) {
|
|
64
|
+
if (pool.hasRole(pool.DEFAULT_ADMIN_ROLE(), msg.sender) == false) {
|
|
63
65
|
revert NOT_PROJECT_OWNER();
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
_;
|
|
67
69
|
}
|
|
68
70
|
|
|
71
|
+
modifier onlyPool() {
|
|
72
|
+
if (bytes(registry[msg.sender].projectId).length == 0) {
|
|
73
|
+
revert NOT_POOL();
|
|
74
|
+
}
|
|
75
|
+
_;
|
|
76
|
+
}
|
|
77
|
+
|
|
69
78
|
function _authorizeUpgrade(address _impl) internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
|
|
70
79
|
|
|
71
80
|
function initialize(
|
|
@@ -113,13 +122,7 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
|
|
|
113
122
|
//TODO: add check if msg.sender is whitelisted
|
|
114
123
|
|
|
115
124
|
_settings.nftType = nextNftType;
|
|
116
|
-
bytes memory initCall = abi.
|
|
117
|
-
DirectPaymentsPool.initialize.selector,
|
|
118
|
-
nft,
|
|
119
|
-
_settings,
|
|
120
|
-
_limits,
|
|
121
|
-
address(this)
|
|
122
|
-
);
|
|
125
|
+
bytes memory initCall = abi.encodeCall(DirectPaymentsPool.initialize, (nft, _settings, _limits, this));
|
|
123
126
|
|
|
124
127
|
if (useBeacon) {
|
|
125
128
|
pool = DirectPaymentsPool(address(new BeaconProxy(address(impl), initCall)));
|
|
@@ -129,7 +132,6 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
|
|
|
129
132
|
|
|
130
133
|
nft.grantRole(nft.getManagerRole(nextNftType), _settings.manager);
|
|
131
134
|
nft.grantRole(nft.getManagerRole(nextNftType), address(pool));
|
|
132
|
-
pool.grantRole(pool.MINTER_ROLE(), _settings.manager);
|
|
133
135
|
|
|
134
136
|
//access control to project is determinted by the first pool access control rules
|
|
135
137
|
if (address(projectIdToControlPool[keccak256(bytes(_projectId))]) == address(0))
|
|
@@ -137,13 +139,16 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
|
|
|
137
139
|
registry[address(pool)].ipfs = _ipfs;
|
|
138
140
|
registry[address(pool)].projectId = _projectId;
|
|
139
141
|
|
|
142
|
+
pool.grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
|
140
143
|
pool.renounceRole(DEFAULT_ADMIN_ROLE, address(this));
|
|
144
|
+
pools.push(address(pool));
|
|
145
|
+
|
|
141
146
|
emit PoolCreated(address(pool), _projectId, _ipfs, nextNftType, _settings, _limits);
|
|
142
147
|
|
|
143
148
|
nextNftType++;
|
|
144
149
|
}
|
|
145
150
|
|
|
146
|
-
function changePoolDetails(DirectPaymentsPool _pool, string memory _ipfs) external
|
|
151
|
+
function changePoolDetails(DirectPaymentsPool _pool, string memory _ipfs) external onlyPoolOwner(_pool) {
|
|
147
152
|
registry[address(_pool)].ipfs = _ipfs;
|
|
148
153
|
emit PoolDetailsChanged(address(_pool), _ipfs);
|
|
149
154
|
}
|
|
@@ -162,4 +167,17 @@ contract DirectPaymentsFactory is AccessControlUpgradeable, UUPSUpgradeable {
|
|
|
162
167
|
feeBps = _feeBps;
|
|
163
168
|
feeRecipient = _feeRecipient;
|
|
164
169
|
}
|
|
170
|
+
|
|
171
|
+
function addMember(address member) external onlyPool {
|
|
172
|
+
memberPools[member].push(msg.sender);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function removeMember(address member) external onlyPool {
|
|
176
|
+
for (uint i = 0; i < memberPools[member].length; i++) {
|
|
177
|
+
if (memberPools[member][i] == msg.sender) {
|
|
178
|
+
memberPools[member][i] = memberPools[member][memberPools[member].length - 1];
|
|
179
|
+
memberPools[member].pop();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
165
183
|
}
|
|
@@ -21,7 +21,7 @@ interface IMembersValidator {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
interface IIdentityV2 {
|
|
24
|
-
function getWhitelistedRoot(address member) external returns (address);
|
|
24
|
+
function getWhitelistedRoot(address member) external view returns (address);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -112,7 +112,7 @@ contract DirectPaymentsPool is
|
|
|
112
112
|
DirectPaymentsFactory public registry;
|
|
113
113
|
|
|
114
114
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
115
|
-
constructor(ISuperfluid _host,
|
|
115
|
+
constructor(ISuperfluid _host, IV3SwapRouter _swapRouter) GoodCollectiveSuperApp(_host, _swapRouter) {}
|
|
116
116
|
|
|
117
117
|
/**
|
|
118
118
|
* @dev Authorizes an upgrade for the implementation contract.
|
|
@@ -120,8 +120,8 @@ contract DirectPaymentsPool is
|
|
|
120
120
|
*/
|
|
121
121
|
function _authorizeUpgrade(address impl) internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
|
|
122
122
|
|
|
123
|
-
function getRegistry() public view override returns (
|
|
124
|
-
return
|
|
123
|
+
function getRegistry() public view override returns (IRegistry) {
|
|
124
|
+
return IRegistry(address(registry));
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
/**
|
|
@@ -140,8 +140,10 @@ contract DirectPaymentsPool is
|
|
|
140
140
|
settings = _settings;
|
|
141
141
|
limits = _limits;
|
|
142
142
|
nft = _nft;
|
|
143
|
-
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
|
|
144
|
-
_setupRole(
|
|
143
|
+
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender); // when using factory this gives factory role which then set role to the real msg.sender
|
|
144
|
+
_setupRole(MANAGER_ROLE, _settings.manager);
|
|
145
|
+
_setupRole(MINTER_ROLE, _settings.manager);
|
|
146
|
+
|
|
145
147
|
setSuperToken(ISuperToken(address(settings.rewardToken)));
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -341,10 +343,24 @@ contract DirectPaymentsPool is
|
|
|
341
343
|
}
|
|
342
344
|
}
|
|
343
345
|
|
|
344
|
-
|
|
346
|
+
_grantRole(MEMBER_ROLE, member);
|
|
345
347
|
return true;
|
|
346
348
|
}
|
|
347
349
|
|
|
350
|
+
function _grantRole(bytes32 role, address account) internal virtual override {
|
|
351
|
+
if (role == MEMBER_ROLE) {
|
|
352
|
+
registry.addMember(account);
|
|
353
|
+
}
|
|
354
|
+
super._grantRole(role, account);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function _revokeRole(bytes32 role, address account) internal virtual override {
|
|
358
|
+
if (role == MEMBER_ROLE) {
|
|
359
|
+
registry.removeMember(account);
|
|
360
|
+
}
|
|
361
|
+
super._revokeRole(role, account);
|
|
362
|
+
}
|
|
363
|
+
|
|
348
364
|
function mintNFT(address _to, ProvableNFT.NFTData memory _nftData, bool withClaim) external onlyRole(MINTER_ROLE) {
|
|
349
365
|
uint nftId = nft.mintPermissioned(_to, _nftData, true, "");
|
|
350
366
|
if (withClaim) {
|
|
@@ -384,7 +400,7 @@ contract DirectPaymentsPool is
|
|
|
384
400
|
* @dev Sets the safety limits for the pool.
|
|
385
401
|
* @param _limits The new safety limits.
|
|
386
402
|
*/
|
|
387
|
-
function setPoolLimits(SafetyLimits memory _limits) public onlyRole(
|
|
403
|
+
function setPoolLimits(SafetyLimits memory _limits) public onlyRole(MANAGER_ROLE) {
|
|
388
404
|
limits = _limits;
|
|
389
405
|
emit PoolLimitsChanged(_limits);
|
|
390
406
|
}
|
|
@@ -393,7 +409,7 @@ contract DirectPaymentsPool is
|
|
|
393
409
|
* @dev Sets the settings for the pool.
|
|
394
410
|
* @param _settings The new pool settings.
|
|
395
411
|
*/
|
|
396
|
-
function setPoolSettings(PoolSettings memory _settings) public onlyRole(
|
|
412
|
+
function setPoolSettings(PoolSettings memory _settings) public onlyRole(MANAGER_ROLE) {
|
|
397
413
|
if (_settings.nftType != settings.nftType) revert NFTTYPE_CHANGED();
|
|
398
414
|
if (_settings.manager == address(0)) revert EMPTY_MANAGER();
|
|
399
415
|
|
|
@@ -9,13 +9,11 @@ import { SuperTokenV1Library } from "@superfluid-finance/ethereum-contracts/cont
|
|
|
9
9
|
import { CFAv1Library, IConstantFlowAgreementV1 } from "@superfluid-finance/ethereum-contracts/contracts/apps/CFAv1Library.sol";
|
|
10
10
|
|
|
11
11
|
import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
|
|
12
|
-
import "@uniswap/
|
|
12
|
+
import "@uniswap/swap-router-contracts/contracts/interfaces/IV3SwapRouter.sol";
|
|
13
13
|
|
|
14
14
|
import "../DirectPayments/DirectPaymentsFactory.sol";
|
|
15
15
|
import "../utils/HelperLibrary.sol";
|
|
16
16
|
|
|
17
|
-
// import "hardhat/console.sol";
|
|
18
|
-
|
|
19
17
|
abstract contract GoodCollectiveSuperApp is SuperAppBaseFlow {
|
|
20
18
|
int96 public constant MIN_FLOW_RATE = 386e9;
|
|
21
19
|
|
|
@@ -51,7 +49,7 @@ abstract contract GoodCollectiveSuperApp is SuperAppBaseFlow {
|
|
|
51
49
|
// ask about "receiver" can it be different then app?
|
|
52
50
|
|
|
53
51
|
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
54
|
-
|
|
52
|
+
IV3SwapRouter public immutable swapRouter;
|
|
55
53
|
|
|
56
54
|
struct SupporterData {
|
|
57
55
|
uint256 contribution;
|
|
@@ -71,12 +69,12 @@ abstract contract GoodCollectiveSuperApp is SuperAppBaseFlow {
|
|
|
71
69
|
uint256[48] private _reserved;
|
|
72
70
|
|
|
73
71
|
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
74
|
-
constructor(ISuperfluid _host,
|
|
72
|
+
constructor(ISuperfluid _host, IV3SwapRouter _swapRouter) SuperAppBaseFlow(_host) {
|
|
75
73
|
if (address(_host) == address(0)) revert ZERO_ADDRESS();
|
|
76
74
|
swapRouter = _swapRouter;
|
|
77
75
|
}
|
|
78
76
|
|
|
79
|
-
function getRegistry() public view virtual returns (
|
|
77
|
+
function getRegistry() public view virtual returns (IRegistry);
|
|
80
78
|
|
|
81
79
|
/**
|
|
82
80
|
* @dev Sets the address of the super token and registers the app with the host
|
|
@@ -160,6 +158,28 @@ abstract contract GoodCollectiveSuperApp is SuperAppBaseFlow {
|
|
|
160
158
|
return _ctx;
|
|
161
159
|
}
|
|
162
160
|
|
|
161
|
+
/**
|
|
162
|
+
* @dev allow single contribution. user needs to approve tokens first. can be used in superfluid batch actions.
|
|
163
|
+
* @param _sender The address of the sender who is contributing tokens.
|
|
164
|
+
* @param _customData The SwapData struct containing information about the swap
|
|
165
|
+
* @param _ctx The context of the transaction for superfluid in case this was used in superfluid batch. otherwise can be empty.
|
|
166
|
+
* @return Returns the context of the transaction.
|
|
167
|
+
*/
|
|
168
|
+
function supportWithSwap(
|
|
169
|
+
address _sender,
|
|
170
|
+
HelperLibrary.SwapData memory _customData,
|
|
171
|
+
bytes memory _ctx
|
|
172
|
+
) external onlyHostOrSender(_sender) returns (bytes memory) {
|
|
173
|
+
uint256 balance = superToken.balanceOf(address(this));
|
|
174
|
+
HelperLibrary.handleSwap(swapRouter, _customData, address(superToken), _sender, address(this));
|
|
175
|
+
uint256 amountReceived = superToken.balanceOf(address(this)) - balance;
|
|
176
|
+
if (amountReceived == 0) revert ZERO_AMOUNT();
|
|
177
|
+
|
|
178
|
+
// Update the contribution amount for the sender in the supporters mapping
|
|
179
|
+
_updateSupporter(_sender, int256(amountReceived), 0, ""); //we pass empty ctx since this is not a flow but a single donation
|
|
180
|
+
return _ctx;
|
|
181
|
+
}
|
|
182
|
+
|
|
163
183
|
/**
|
|
164
184
|
* @dev Handles the swap of tokens using the SwapData struct
|
|
165
185
|
* @param _customData The SwapData struct containing information about the swap
|
|
@@ -247,7 +267,7 @@ abstract contract GoodCollectiveSuperApp is SuperAppBaseFlow {
|
|
|
247
267
|
) internal returns (bytes memory newCtx) {
|
|
248
268
|
newCtx = _ctx;
|
|
249
269
|
bool _isFlow = _ctx.length > 0;
|
|
250
|
-
|
|
270
|
+
HelperLibrary.updateStats(stats, superToken, getRegistry(), _isFlow ? 0 : uint256(_previousFlowRateOrAmount));
|
|
251
271
|
// Get the current flow rate for the supporter
|
|
252
272
|
int96 flowRate = superToken.getFlowRate(_supporter, address(this));
|
|
253
273
|
uint256 prevContribution = supporters[_supporter].contribution;
|
|
@@ -260,7 +280,14 @@ abstract contract GoodCollectiveSuperApp is SuperAppBaseFlow {
|
|
|
260
280
|
supporters[_supporter].contribution +=
|
|
261
281
|
uint96(int96(_previousFlowRateOrAmount)) *
|
|
262
282
|
(block.timestamp - _lastUpdated);
|
|
263
|
-
newCtx =
|
|
283
|
+
newCtx = HelperLibrary.takeFeeFlow(
|
|
284
|
+
cfaV1,
|
|
285
|
+
stats,
|
|
286
|
+
superToken,
|
|
287
|
+
getRegistry(),
|
|
288
|
+
flowRate - int96(_previousFlowRateOrAmount),
|
|
289
|
+
_ctx
|
|
290
|
+
);
|
|
264
291
|
// we update the last rate after we do all changes to our own flows
|
|
265
292
|
stats.lastIncomeRate = superToken.getNetFlowRate(address(this));
|
|
266
293
|
} else {
|
|
@@ -278,51 +305,6 @@ abstract contract GoodCollectiveSuperApp is SuperAppBaseFlow {
|
|
|
278
305
|
);
|
|
279
306
|
}
|
|
280
307
|
|
|
281
|
-
// this should be called before any flow rate changes
|
|
282
|
-
function _updateStats(uint256 _amount) internal {
|
|
283
|
-
//use last rate before the current possible rate update
|
|
284
|
-
stats.netIncome += uint96(stats.lastIncomeRate) * (block.timestamp - stats.lastUpdate);
|
|
285
|
-
uint feeBps;
|
|
286
|
-
if (address(getRegistry()) != address(0)) {
|
|
287
|
-
feeBps = getRegistry().feeBps();
|
|
288
|
-
//fees sent to last recipient, the flowRate to recipient still wasnt updated.
|
|
289
|
-
stats.totalFees +=
|
|
290
|
-
uint96(superToken.getFlowRate(address(this), stats.lastFeeRecipient)) *
|
|
291
|
-
(block.timestamp - stats.lastUpdate);
|
|
292
|
-
}
|
|
293
|
-
if (_amount > 0) {
|
|
294
|
-
stats.netIncome += (_amount * (10000 - feeBps)) / 10000;
|
|
295
|
-
stats.totalFees += (_amount * feeBps) / 10000;
|
|
296
|
-
}
|
|
297
|
-
stats.lastUpdate = block.timestamp;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function _takeFeeFlow(int96 _diffRate, bytes memory _ctx) internal returns (bytes memory newCtx) {
|
|
301
|
-
newCtx = _ctx;
|
|
302
|
-
if (address(getRegistry()) == address(0)) return newCtx;
|
|
303
|
-
address recipient = getRegistry().feeRecipient();
|
|
304
|
-
int96 curFeeRate = superToken.getFlowRate(address(this), stats.lastFeeRecipient);
|
|
305
|
-
bool newRecipient;
|
|
306
|
-
if (recipient != stats.lastFeeRecipient) {
|
|
307
|
-
newRecipient = true;
|
|
308
|
-
if (stats.lastFeeRecipient != address(0)) {
|
|
309
|
-
//delete old recipient flow
|
|
310
|
-
if (curFeeRate > 0)
|
|
311
|
-
newCtx = cfaV1.deleteFlowWithCtx(newCtx, address(this), stats.lastFeeRecipient, superToken); //passing in the ctx which is sent to the callback here
|
|
312
|
-
}
|
|
313
|
-
stats.lastFeeRecipient = recipient;
|
|
314
|
-
}
|
|
315
|
-
if (recipient == address(0)) return newCtx;
|
|
316
|
-
|
|
317
|
-
int96 feeRateChange = (_diffRate * int32(getRegistry().feeBps())) / 10000;
|
|
318
|
-
int96 newFeeRate = curFeeRate + feeRateChange;
|
|
319
|
-
if (newFeeRate <= 0 && newRecipient == false) {
|
|
320
|
-
newCtx = cfaV1.deleteFlowWithCtx(newCtx, address(this), recipient, superToken); //passing in the ctx which is sent to the callback here
|
|
321
|
-
} else if (curFeeRate > 0 && newRecipient == false) {
|
|
322
|
-
newCtx = cfaV1.updateFlowWithCtx(newCtx, recipient, superToken, newFeeRate); //passing in the ctx which is sent to the callback here
|
|
323
|
-
} else if (newFeeRate > 0) newCtx = cfaV1.createFlowWithCtx(newCtx, recipient, superToken, newFeeRate); //passing in the ctx which is sent to the callback here
|
|
324
|
-
}
|
|
325
|
-
|
|
326
308
|
function _takeFeeSingle(uint256 _amount) internal {
|
|
327
309
|
if (address(getRegistry()) == address(0)) return;
|
|
328
310
|
address recipient = getRegistry().feeRecipient();
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
pragma solidity >=0.8.0;
|
|
3
3
|
|
|
4
|
+
interface IRegistry {
|
|
5
|
+
function feeRecipient() external view returns (address);
|
|
6
|
+
|
|
7
|
+
function feeBps() external view returns (uint32);
|
|
8
|
+
}
|
|
9
|
+
|
|
4
10
|
interface IGoodCollectiveSuperApp {
|
|
5
11
|
struct Stats {
|
|
6
12
|
uint256 netIncome; //without fees
|