@superfluid-finance/ethereum-contracts 1.7.2-dev.09f3be3.0 → 1.7.2-dev.1ef77a5.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.
Files changed (188) hide show
  1. package/README.md +2 -2
  2. package/artifacts/contracts/apps/SuperAppBaseFlow.sol/SuperAppBaseFlow.json +13 -13
  3. package/artifacts/contracts/apps/SuperfluidLoaderLibrary.sol/SuperfluidLoaderLibrary.json +2 -2
  4. package/artifacts/contracts/mocks/SuperAppBaseFlowTester.sol/SuperAppBaseFlowTester.json +15 -15
  5. package/build/contracts/AccessControl.json +1 -1
  6. package/build/contracts/AccessControlEnumerable.json +1 -1
  7. package/build/contracts/Address.json +1 -1
  8. package/build/contracts/AgreementBase.json +18 -18
  9. package/build/contracts/AgreementLibrary.json +165 -165
  10. package/build/contracts/BaseRelayRecipient.json +57 -57
  11. package/build/contracts/BatchLiquidator.json +382 -382
  12. package/build/contracts/BatchOperation.json +614 -614
  13. package/build/contracts/CFAv1Forwarder.json +1250 -1250
  14. package/build/contracts/CFAv1ForwarderDeployerLibrary.json +2384 -2384
  15. package/build/contracts/CFAv1Library.json +389 -389
  16. package/build/contracts/CallUtils.json +198 -198
  17. package/build/contracts/ClosingOnUpdateFlowTestApp.json +1525 -1525
  18. package/build/contracts/ConstantFlowAgreementV1.json +1087 -1087
  19. package/build/contracts/ConstantInflowNFT.json +402 -402
  20. package/build/contracts/ConstantOutflowNFT.json +661 -661
  21. package/build/contracts/Context.json +1 -1
  22. package/build/contracts/ContextDefinitions.json +614 -614
  23. package/build/contracts/CustomSuperTokenBase.json +19 -19
  24. package/build/contracts/ERC165.json +1 -1
  25. package/build/contracts/ERC1820Implementer.json +1 -1
  26. package/build/contracts/ERC1820RegistryCompiled.json +22 -22
  27. package/build/contracts/ERC20.json +1 -1
  28. package/build/contracts/ERC20WithTokenInfo.json +23 -23
  29. package/build/contracts/ERC777Helper.json +384 -384
  30. package/build/contracts/ERC777RecipientDrainingGas.json +863 -863
  31. package/build/contracts/ERC777RecipientReverting.json +863 -863
  32. package/build/contracts/EnumerableSet.json +1 -1
  33. package/build/contracts/EventsEmitter.json +43 -43
  34. package/build/contracts/ExclusiveInflowTestApp.json +1525 -1525
  35. package/build/contracts/FixedSizeData.json +200 -200
  36. package/build/contracts/FlowExchangeTestApp.json +1526 -1526
  37. package/build/contracts/FlowNFTBase.json +1280 -1280
  38. package/build/contracts/FlowOperatorDefinitions.json +614 -614
  39. package/build/contracts/ForwarderBase.json +190 -190
  40. package/build/contracts/FullUpgradableSuperTokenProxy.json +116 -116
  41. package/build/contracts/IAccessControl.json +1 -1
  42. package/build/contracts/IAccessControlEnumerable.json +1 -1
  43. package/build/contracts/IConstantFlowAgreementV1.json +677 -677
  44. package/build/contracts/IConstantInflowNFT.json +54 -54
  45. package/build/contracts/IConstantOutflowNFT.json +107 -107
  46. package/build/contracts/IDAv1Forwarder.json +912 -912
  47. package/build/contracts/IDAv1ForwarderDeployerLibrary.json +2384 -2384
  48. package/build/contracts/IDAv1Library.json +430 -430
  49. package/build/contracts/IERC165.json +1 -1
  50. package/build/contracts/IERC1820Implementer.json +1 -1
  51. package/build/contracts/IERC1820Registry.json +1 -1
  52. package/build/contracts/IERC20.json +1 -1
  53. package/build/contracts/IERC20Metadata.json +1 -1
  54. package/build/contracts/IERC20Permit.json +1 -1
  55. package/build/contracts/IERC721.json +1 -1
  56. package/build/contracts/IERC721Metadata.json +1 -1
  57. package/build/contracts/IERC777.json +1 -1
  58. package/build/contracts/IERC777Recipient.json +1 -1
  59. package/build/contracts/IERC777Sender.json +1 -1
  60. package/build/contracts/IFlowNFTBase.json +115 -115
  61. package/build/contracts/IInstantDistributionAgreementV1.json +667 -667
  62. package/build/contracts/IMultiSigWallet.json +31 -31
  63. package/build/contracts/IPoolAdminNFT.json +7 -7
  64. package/build/contracts/IPoolMemberNFT.json +7 -7
  65. package/build/contracts/IPureSuperToken.json +62 -62
  66. package/build/contracts/IPureSuperTokenCustom.json +62 -62
  67. package/build/contracts/IRelayRecipient.json +27 -27
  68. package/build/contracts/IResolver.json +38 -38
  69. package/build/contracts/ISETH.json +67 -67
  70. package/build/contracts/ISETHCustom.json +67 -67
  71. package/build/contracts/ISuperAgreement.json +50 -50
  72. package/build/contracts/ISuperApp.json +191 -191
  73. package/build/contracts/ISuperToken.json +695 -695
  74. package/build/contracts/ISuperTokenFactory.json +225 -225
  75. package/build/contracts/ISuperfluid.json +904 -904
  76. package/build/contracts/ISuperfluidGovernance.json +251 -251
  77. package/build/contracts/ISuperfluidToken.json +407 -407
  78. package/build/contracts/ITOGAv1.json +1346 -1346
  79. package/build/contracts/ITOGAv2.json +1346 -1346
  80. package/build/contracts/ITOGAv3.json +1346 -1346
  81. package/build/contracts/Initializable.json +1 -1
  82. package/build/contracts/InstantDistributionAgreementV1.json +594 -594
  83. package/build/contracts/Math.json +1 -1
  84. package/build/contracts/NonClosableOutflowTestApp.json +1526 -1526
  85. package/build/contracts/Ownable.json +1 -1
  86. package/build/contracts/Proxy.json +1 -1
  87. package/build/contracts/ProxyDeployerLibrary.json +2382 -2382
  88. package/build/contracts/PureSuperToken.json +106 -106
  89. package/build/contracts/Resolver.json +98 -98
  90. package/build/contracts/SETHProxy.json +224 -224
  91. package/build/contracts/SafeCast.json +1 -1
  92. package/build/contracts/SafeERC20.json +1 -1
  93. package/build/contracts/SafeGasLibrary.json +51 -51
  94. package/build/contracts/SafeMath.json +1 -1
  95. package/build/contracts/SelfDeletingFlowTestApp.json +1525 -1525
  96. package/build/contracts/SlotsBitmapLibrary.json +457 -457
  97. package/build/contracts/StreamRedirector.json +704 -704
  98. package/build/contracts/Strings.json +1 -1
  99. package/build/contracts/SuperAppBase.json +42 -42
  100. package/build/contracts/SuperAppBaseFlow.json +800 -800
  101. package/build/contracts/SuperAppDefinitions.json +614 -614
  102. package/build/contracts/SuperToken.json +2714 -2714
  103. package/build/contracts/SuperTokenDeployerLibrary.json +2383 -2383
  104. package/build/contracts/SuperTokenFactory.json +1347 -1347
  105. package/build/contracts/SuperTokenFactoryBase.json +1329 -1329
  106. package/build/contracts/SuperTokenV1Library.json +1483 -1483
  107. package/build/contracts/SuperUpgrader.json +439 -439
  108. package/build/contracts/Superfluid.json +5196 -5196
  109. package/build/contracts/SuperfluidCFAv1DeployerLibrary.json +2383 -2383
  110. package/build/contracts/SuperfluidFrameworkDeployer.json +1260 -1260
  111. package/build/contracts/SuperfluidFrameworkDeploymentSteps.json +2382 -2382
  112. package/build/contracts/SuperfluidGovDeployerLibrary.json +2383 -2383
  113. package/build/contracts/SuperfluidGovernanceBase.json +2449 -2449
  114. package/build/contracts/SuperfluidGovernanceConfigs.json +614 -614
  115. package/build/contracts/SuperfluidGovernanceII.json +155 -155
  116. package/build/contracts/SuperfluidGovernanceIIProxy.json +135 -135
  117. package/build/contracts/SuperfluidHostDeployerLibrary.json +2382 -2382
  118. package/build/contracts/SuperfluidIDAv1DeployerLibrary.json +2383 -2383
  119. package/build/contracts/SuperfluidLoader.json +207 -207
  120. package/build/contracts/SuperfluidLoaderDeployerLibrary.json +2384 -2384
  121. package/build/contracts/SuperfluidLoaderLibrary.json +552 -417
  122. package/build/contracts/SuperfluidNFTLogicDeployerLibrary.json +2387 -2387
  123. package/build/contracts/SuperfluidPeripheryDeployerLibrary.json +2385 -2385
  124. package/build/contracts/SuperfluidToken.json +1423 -1423
  125. package/build/contracts/TOGA.json +1360 -1360
  126. package/build/contracts/TestGovernance.json +250 -250
  127. package/build/contracts/TestResolver.json +47 -47
  128. package/build/contracts/TestToken.json +102 -102
  129. package/build/contracts/TokenDeployerLibrary.json +2384 -2384
  130. package/build/contracts/TokenInfo.json +32 -32
  131. package/build/contracts/UUPSProxiable.json +139 -139
  132. package/build/contracts/UUPSProxy.json +81 -81
  133. package/build/contracts/UUPSUtils.json +37 -37
  134. package/build/contracts-sizes.txt +15 -15
  135. package/build/typechain/contracts/apps/SuperAppBaseFlow.d.ts +9 -9
  136. package/build/typechain/contracts/apps/SuperAppBaseFlow.d.ts.map +1 -1
  137. package/build/typechain/contracts/mocks/SuperAppBaseFlowTester.d.ts +9 -9
  138. package/build/typechain/contracts/mocks/SuperAppBaseFlowTester.d.ts.map +1 -1
  139. package/build/typechain/factories/contracts/apps/SuperAppBaseFlow__factory.d.ts +10 -10
  140. package/build/typechain/factories/contracts/apps/SuperAppBaseFlow__factory.js +13 -13
  141. package/build/typechain/factories/contracts/apps/SuperAppBaseFlow__factory.js.map +1 -1
  142. package/build/typechain/factories/contracts/apps/SuperfluidLoaderLibrary__factory.d.ts +1 -1
  143. package/build/typechain/factories/contracts/apps/SuperfluidLoaderLibrary__factory.d.ts.map +1 -1
  144. package/build/typechain/factories/contracts/apps/SuperfluidLoaderLibrary__factory.js +1 -1
  145. package/build/typechain/factories/contracts/apps/SuperfluidLoaderLibrary__factory.js.map +1 -1
  146. package/build/typechain/factories/contracts/mocks/SuperAppBaseFlowTester__factory.d.ts +11 -11
  147. package/build/typechain/factories/contracts/mocks/SuperAppBaseFlowTester__factory.d.ts.map +1 -1
  148. package/build/typechain/factories/contracts/mocks/SuperAppBaseFlowTester__factory.js +14 -14
  149. package/build/typechain/factories/contracts/mocks/SuperAppBaseFlowTester__factory.js.map +1 -1
  150. package/contracts/apps/SuperAppBaseFlow.sol +8 -8
  151. package/contracts/apps/SuperfluidLoaderLibrary.sol +5 -2
  152. package/package.json +5 -5
  153. package/ops-scripts/.eslintrc.js +0 -15
  154. package/ops-scripts/artifacts/ERC1820Registry.json +0 -5
  155. package/ops-scripts/deploy-aux-contracts.js +0 -99
  156. package/ops-scripts/deploy-deterministically.js +0 -169
  157. package/ops-scripts/deploy-erc1820.js +0 -83
  158. package/ops-scripts/deploy-framework.js +0 -895
  159. package/ops-scripts/deploy-mfa.ts +0 -27
  160. package/ops-scripts/deploy-super-token.js +0 -206
  161. package/ops-scripts/deploy-test-environment.js +0 -98
  162. package/ops-scripts/deploy-test-token.js +0 -86
  163. package/ops-scripts/deploy-unlisted-pure-super-token.js +0 -69
  164. package/ops-scripts/deploy-unlisted-super-token.js +0 -68
  165. package/ops-scripts/gov-create-new-app-registration-key.js +0 -75
  166. package/ops-scripts/gov-create-new-factory-registration.js +0 -49
  167. package/ops-scripts/gov-set-3Ps-config.js +0 -67
  168. package/ops-scripts/gov-set-reward-address.js +0 -60
  169. package/ops-scripts/gov-set-token-min-deposit.js +0 -53
  170. package/ops-scripts/gov-set-trusted-forwarder.js +0 -80
  171. package/ops-scripts/gov-transfer-framework-ownership.js +0 -90
  172. package/ops-scripts/gov-upgrade-governance.js +0 -87
  173. package/ops-scripts/gov-upgrade-super-token-logic.js +0 -193
  174. package/ops-scripts/info-inspect-account.js +0 -118
  175. package/ops-scripts/info-list-apps.js +0 -55
  176. package/ops-scripts/info-print-contract-addresses.js +0 -136
  177. package/ops-scripts/info-scan-deployments.js +0 -63
  178. package/ops-scripts/info-show-protocol.js +0 -400
  179. package/ops-scripts/libs/common.js +0 -436
  180. package/ops-scripts/libs/getConfig.js +0 -289
  181. package/ops-scripts/libs/truffleScriptRunnerFactory.js +0 -97
  182. package/ops-scripts/resolver-list-super-token.js +0 -73
  183. package/ops-scripts/resolver-register-token.js +0 -72
  184. package/ops-scripts/resolver-reset-deployment.js +0 -54
  185. package/ops-scripts/resolver-set-key-value.js +0 -69
  186. package/ops-scripts/resolver-unlist-super-token.js +0 -61
  187. package/ops-scripts/tmp-trigger-token-transfer.js +0 -33
  188. package/ops-scripts/validate-nft-addresses.ts +0 -49
@@ -1,895 +0,0 @@
1
- const fs = require("fs");
2
- const util = require("util");
3
- const getConfig = require("./libs/getConfig");
4
- const SuperfluidSDK = require("@superfluid-finance/js-sdk");
5
- const {web3tx} = require("@decentral.ee/web3-helpers");
6
- const deployERC1820 = require("../ops-scripts/deploy-erc1820");
7
-
8
- const {
9
- getScriptRunnerFactory: S,
10
- ZERO_ADDRESS,
11
- hasCode,
12
- codeChanged,
13
- isProxiable,
14
- extractWeb3Options,
15
- builtTruffleContractLoader,
16
- sendGovernanceAction,
17
- } = require("./libs/common");
18
-
19
- let resetSuperfluidFramework;
20
- let resolver;
21
-
22
- /// @param deployFunc must return a contract object
23
- /// @returns the newly deployed or existing loaded contract
24
- async function deployAndRegisterContractIf(
25
- Contract,
26
- resolverKey,
27
- cond,
28
- deployFunc
29
- ) {
30
- let contractDeployed;
31
- const contractName = Contract.contractName;
32
- const contractAddress = await resolver.get.call(resolverKey);
33
- console.log(`${resolverKey} address`, contractAddress);
34
- if (resetSuperfluidFramework || (await cond(contractAddress))) {
35
- console.log(`${contractName} needs new deployment.`);
36
- contractDeployed = await deployFunc();
37
- console.log(`${resolverKey} deployed to`, contractDeployed.address);
38
- await web3tx(resolver.set, `Resolver set ${resolverKey}`)(
39
- resolverKey,
40
- contractDeployed.address
41
- );
42
- } else {
43
- console.log(`${contractName} does not need new deployment.`);
44
- contractDeployed = await Contract.at(contractAddress);
45
- }
46
- return contractDeployed;
47
- }
48
-
49
- /// @param deployFunc must return a contract address
50
- /// @returns the address of the newly deployed contract or ZERO_ADDRESS if not deployed
51
- async function deployContractIf(web3, Contract, cond, deployFunc) {
52
- const contractName = Contract.contractName;
53
- if (await cond()) {
54
- console.log(`${contractName} logic code has changed`);
55
- const newCodeAddress = await deployFunc();
56
- console.log(`${contractName} new logic code address ${newCodeAddress}`);
57
- return newCodeAddress;
58
- } else {
59
- console.log(
60
- `${contractName} has the same logic code, no deployment needed.`
61
- );
62
- return ZERO_ADDRESS;
63
- }
64
- }
65
-
66
- /// @param deployFunc must return a contract address
67
- /// @returns the address of the newly deployed contract or ZERO_ADDRESS if not deployed
68
- async function deployContractIfCodeChanged(
69
- web3,
70
- Contract,
71
- codeAddress,
72
- deployFunc,
73
- codeReplacements
74
- ) {
75
- return deployContractIf(
76
- web3,
77
- Contract,
78
- async () =>
79
- await codeChanged(web3, Contract, codeAddress, codeReplacements),
80
- deployFunc
81
- );
82
- }
83
-
84
- /**
85
- * @dev Deploy the superfluid framework
86
- * @param {boolean} options.isTruffle Whether the script is used within native truffle framework
87
- * @param {Web3} options.web3 Injected web3 instance
88
- * @param {Address} options.from Address to deploy contracts from
89
- * @param {boolean} options.newTestResolver Force to create a new resolver (overriding env: CREATE_NEW_RESOLVER)
90
- * @param {boolean} options.useMocks Use mock contracts instead (overriding env: USE_MOCKS)
91
- * @param {boolean} options.nonUpgradable Deploy contracts configured to be non-upgradable
92
- * (overriding env: NON_UPGRADABLE)
93
- * @param {boolean} options.appWhiteListing Deploy contracts configured to require app white listing
94
- * (overriding env: ENABLE_APP_WHITELISTING)
95
- * @param {boolean} options.resetSuperfluidFramework Reset the superfluid framework deployment
96
- * (overriding env: RESET_SUPERFLUID_FRAMEWORK)
97
- * @param {string} options.protocolReleaseVersion Specify the protocol release version to be used
98
- * (overriding env: RELEASE_VERSION)
99
- * @param {string} options.outputFile Name of file where to log addresses of newly deployed contracts
100
- * (overriding env: OUTPUT_FILE)
101
- *
102
- * Usage: npx truffle exec ops-scripts/deploy-framework.js
103
- */
104
-
105
- module.exports = eval(`(${S.toString()})({skipArgv: true})`)(async function (
106
- args,
107
- options = {}
108
- ) {
109
- console.log("======== Deploying superfluid framework ========");
110
- let {
111
- newTestResolver,
112
- useMocks,
113
- nonUpgradable,
114
- appWhiteListing,
115
- protocolReleaseVersion,
116
- outputFile,
117
- } = options;
118
- resetSuperfluidFramework = options.resetSuperfluidFramework;
119
-
120
- resetSuperfluidFramework =
121
- resetSuperfluidFramework || !!process.env.RESET_SUPERFLUID_FRAMEWORK;
122
- console.log("reset superfluid framework: ", resetSuperfluidFramework);
123
-
124
- outputFile = outputFile || process.env.OUTPUT_FILE;
125
- if (outputFile !== undefined) {
126
- console.log("output file: ", outputFile);
127
- }
128
-
129
- // string to build a list of newly deployed contracts, written to a file if "outputFile" option set
130
- let output = "";
131
-
132
- const networkType = await web3.eth.net.getNetworkType();
133
- const networkId = await web3.eth.net.getId();
134
- const chainId = await web3.eth.getChainId();
135
- const deployerAddr = (await web3.eth.getAccounts())[0];
136
- console.log("network Type: ", networkType);
137
- console.log("network ID: ", networkId);
138
- console.log("chain ID: ", chainId);
139
- console.log("deployer: ", deployerAddr);
140
- const config = getConfig(chainId);
141
- output += `NETWORK_ID=${networkId}\n`;
142
-
143
- const deployerInitialBalance = await web3.eth.getBalance(deployerAddr);
144
-
145
- const CFAv1_TYPE = web3.utils.sha3(
146
- "org.superfluid-finance.agreements.ConstantFlowAgreement.v1"
147
- );
148
- const IDAv1_TYPE = web3.utils.sha3(
149
- "org.superfluid-finance.agreements.InstantDistributionAgreement.v1"
150
- );
151
-
152
- newTestResolver = newTestResolver || !!process.env.CREATE_NEW_RESOLVER;
153
- useMocks = useMocks || !!process.env.USE_MOCKS;
154
- nonUpgradable = nonUpgradable || !!process.env.NON_UPGRADABLE;
155
- appWhiteListing =
156
- appWhiteListing ||
157
- config.gov_enableAppWhiteListing ||
158
- !!process.env.ENABLE_APP_WHITELISTING;
159
- if (newTestResolver) {
160
- console.log("**** !ATTN! CREATING NEW RESOLVER ****");
161
- }
162
- if (useMocks) {
163
- console.log("**** !ATTN! USING MOCKS CONTRACTS ****");
164
- }
165
- if (nonUpgradable) {
166
- console.log("**** !ATTN! DISABLED UPGRADABILITY ****");
167
- }
168
- if (appWhiteListing) {
169
- console.log("**** !ATTN! ENABLING APP WHITELISTING ****");
170
- }
171
-
172
- await deployERC1820((err) => {
173
- if (err) throw err;
174
- }, options);
175
-
176
- const contracts = [
177
- "Ownable",
178
- "CFAv1Forwarder",
179
- "IMultiSigWallet",
180
- "SuperfluidGovernanceBase",
181
- "Resolver",
182
- "SuperfluidLoader",
183
- "Superfluid",
184
- "SuperTokenFactory",
185
- "SuperToken",
186
- "TestGovernance",
187
- "ISuperfluidGovernance",
188
- "UUPSProxy",
189
- "UUPSProxiable",
190
- "SlotsBitmapLibrary",
191
- "ConstantFlowAgreementV1",
192
- "InstantDistributionAgreementV1",
193
- "ConstantOutflowNFT",
194
- "ConstantInflowNFT",
195
- ];
196
- const mockContracts = [
197
- "SuperfluidMock",
198
- "SuperTokenFactoryMock",
199
- "SuperTokenMock",
200
- ];
201
- const {
202
- Ownable,
203
- IMultiSigWallet,
204
- CFAv1Forwarder,
205
- SuperfluidGovernanceBase,
206
- Resolver,
207
- SuperfluidLoader,
208
- Superfluid,
209
- SuperfluidMock,
210
- SuperTokenFactory,
211
- SuperTokenFactoryMock,
212
- SuperToken,
213
- SuperTokenMock,
214
- TestGovernance,
215
- ISuperfluidGovernance,
216
- UUPSProxy,
217
- UUPSProxiable,
218
- SlotsBitmapLibrary,
219
- ConstantFlowAgreementV1,
220
- InstantDistributionAgreementV1,
221
- ConstantOutflowNFT,
222
- ConstantInflowNFT,
223
- } = await SuperfluidSDK.loadContracts({
224
- ...extractWeb3Options(options),
225
- additionalContracts: contracts.concat(useMocks ? mockContracts : []),
226
- contractLoader: builtTruffleContractLoader,
227
- networkId,
228
- });
229
-
230
- if (!newTestResolver && config.resolverAddress) {
231
- resolver = await Resolver.at(config.resolverAddress);
232
- } else {
233
- resolver = await web3tx(Resolver.new, "Resolver.new")();
234
- // make it available for the sdk for testing purpose
235
- process.env.RESOLVER_ADDRESS = resolver.address;
236
- }
237
- console.log("Resolver address", resolver.address);
238
-
239
- // deploy new governance contract
240
- let governanceInitializationRequired = false;
241
- let governance;
242
- if (!config.disableTestGovernance && !process.env.NO_NEW_GOVERNANCE) {
243
- governance = await deployAndRegisterContractIf(
244
- TestGovernance,
245
- `TestGovernance.${protocolReleaseVersion}`,
246
- async (contractAddress) =>
247
- await codeChanged(web3, TestGovernance, contractAddress),
248
- async () => {
249
- governanceInitializationRequired = true;
250
- const c = await web3tx(
251
- TestGovernance.new,
252
- "TestGovernance.new"
253
- )();
254
- output += `SUPERFLUID_GOVERNANCE=${c.address}\n`;
255
- return c;
256
- }
257
- );
258
- }
259
-
260
- // deploy superfluid loader
261
- await deployAndRegisterContractIf(
262
- SuperfluidLoader,
263
- "SuperfluidLoader-v1",
264
- async (contractAddress) => contractAddress === ZERO_ADDRESS,
265
- async () => {
266
- const c = await web3tx(
267
- SuperfluidLoader.new,
268
- "SuperfluidLoader.new"
269
- )(resolver.address);
270
- output += `SUPERFLUID_LOADER=${c.address}\n`;
271
- return c;
272
- }
273
- );
274
-
275
- // deploy new superfluid host contract
276
- const SuperfluidLogic = useMocks ? SuperfluidMock : Superfluid;
277
- const superfluid = await deployAndRegisterContractIf(
278
- SuperfluidLogic,
279
- `Superfluid.${protocolReleaseVersion}`,
280
- async (contractAddress) => !(await hasCode(web3, contractAddress)),
281
- async () => {
282
- governanceInitializationRequired = true;
283
- let superfluidAddress;
284
- const superfluidLogic = await web3tx(
285
- SuperfluidLogic.new,
286
- "SuperfluidLogic.new"
287
- )(nonUpgradable, appWhiteListing);
288
- console.log(
289
- `Superfluid new code address ${superfluidLogic.address}`
290
- );
291
- output += `SUPERFLUID_HOST_LOGIC=${superfluidLogic.address}\n`;
292
- if (!nonUpgradable) {
293
- const proxy = await web3tx(
294
- UUPSProxy.new,
295
- "Create Superfluid proxy"
296
- )();
297
- output += `SUPERFLUID_HOST_PROXY=${proxy.address}\n`;
298
- await web3tx(
299
- proxy.initializeProxy,
300
- "proxy.initializeProxy"
301
- )(superfluidLogic.address);
302
- superfluidAddress = proxy.address;
303
- } else {
304
- superfluidAddress = superfluidLogic.address;
305
- }
306
- const superfluid = await Superfluid.at(superfluidAddress);
307
- await web3tx(
308
- superfluid.initialize,
309
- "Superfluid.initialize"
310
- )(governance.address);
311
- if (!nonUpgradable) {
312
- if (
313
- await codeChanged(
314
- web3,
315
- SuperfluidLogic,
316
- await superfluid.getCodeAddress()
317
- )
318
- ) {
319
- throw new Error(
320
- "Unexpected code change from fresh deployment"
321
- );
322
- }
323
- }
324
- return superfluid;
325
- }
326
- );
327
- // this is needed later on
328
- const superfluidConstructorParam = superfluid.address
329
- .toLowerCase().slice(2).padStart(64, "0");
330
-
331
- // load existing governance if needed
332
- if (!governance) {
333
- governance = await ISuperfluidGovernance.at(
334
- await superfluid.getGovernance.call()
335
- );
336
- console.log("Governance address", governance.address);
337
- }
338
-
339
- // initialize the new governance
340
- if (governanceInitializationRequired) {
341
- const accounts = await web3.eth.getAccounts();
342
- console.log(`initializing governance with config: ${JSON.stringify(config, null, 2)}`);
343
- await web3tx(governance.initialize, "governance.initialize")(
344
- superfluid.address,
345
- // let rewardAddress the first account
346
- accounts[0],
347
- // liquidationPeriod
348
- config.liquidationPeriod,
349
- // patricianPeriod
350
- config.patricianPeriod,
351
- // trustedForwarders
352
- config.biconomyForwarder ? [config.biconomyForwarder] : []
353
- );
354
- if (config.cfaFwd !== undefined) {
355
- await web3tx(governance.enableTrustedForwarder, "governance.enableTrustedForwarder")(
356
- superfluid.address,
357
- ZERO_ADDRESS,
358
- config.cfaFwd
359
- )
360
- };
361
- }
362
-
363
- // replace with new governance
364
- if ((await superfluid.getGovernance.call()) !== governance.address) {
365
- const currentGovernance = await ISuperfluidGovernance.at(
366
- await superfluid.getGovernance.call()
367
- );
368
- await web3tx(
369
- currentGovernance.replaceGovernance,
370
- "governance.replaceGovernance"
371
- )(superfluid.address, governance.address);
372
- }
373
-
374
- // list CFA v1
375
- const deployCFAv1 = async () => {
376
- const agreement = await web3tx(
377
- ConstantFlowAgreementV1.new,
378
- "ConstantFlowAgreementV1.new"
379
- )(superfluid.address);
380
-
381
- console.log("New ConstantFlowAgreementV1 address", agreement.address);
382
- output += `CFA_LOGIC=${agreement.address}\n`;
383
- return agreement;
384
- };
385
-
386
- if (!(await superfluid.isAgreementTypeListed.call(CFAv1_TYPE))) {
387
- const cfa = await deployCFAv1();
388
- await web3tx(
389
- governance.registerAgreementClass,
390
- "Governance registers CFA"
391
- )(superfluid.address, cfa.address);
392
- }
393
-
394
- /**
395
- * This function:
396
- * deploys an external library
397
- * links a contract artifact to the deployed external library (in two ways depending on if hardhat or truffle env)
398
- * returns the deployed external library
399
- * @param {*} externalLibraryArtifact artifact of the external library
400
- * @param {*} externalLibraryName name of the external library
401
- * @param {*} outputName the output name
402
- * @param {*} contract the contract artifact to link to the external library
403
- * @returns
404
- */
405
- const deployExternalLibraryAndLink = async (
406
- externalLibraryArtifact,
407
- externalLibraryName,
408
- outputName,
409
- contract
410
- ) => {
411
- const externalLibrary = await web3tx(
412
- externalLibraryArtifact.new,
413
- `${externalLibraryName}.new`
414
- )();
415
- output += `${outputName}=${externalLibrary.address}\n`;
416
- if (process.env.IS_HARDHAT) {
417
- contract.link(externalLibrary);
418
- } else {
419
- contract.link(externalLibraryName, externalLibrary.address);
420
- }
421
- console.log(externalLibraryName, "address", externalLibrary.address);
422
- return externalLibrary;
423
- };
424
-
425
- // list IDA v1
426
- const deployIDAv1 = async () => {
427
- // small inefficiency: this may be re-deployed even if not changed
428
- // deploySlotsBitmapLibrary
429
- await deployExternalLibraryAndLink(
430
- SlotsBitmapLibrary,
431
- "SlotsBitmapLibrary",
432
- "SLOTS_BITMAP_LIBRARY_ADDRESS",
433
- InstantDistributionAgreementV1
434
- );
435
- const agreement = await web3tx(
436
- InstantDistributionAgreementV1.new,
437
- "InstantDistributionAgreementV1.new"
438
- )(superfluid.address);
439
- console.log(
440
- "New InstantDistributionAgreementV1 address",
441
- agreement.address
442
- );
443
- output += `IDA_LOGIC=${agreement.address}\n`;
444
- return agreement;
445
- };
446
-
447
- if (!(await superfluid.isAgreementTypeListed.call(IDAv1_TYPE))) {
448
- const ida = await deployIDAv1();
449
- await web3tx(
450
- governance.registerAgreementClass,
451
- "Governance registers IDA"
452
- )(superfluid.address, ida.address);
453
- } else {
454
- // NOTE that we are reusing the existing deployed external library
455
- // here as an optimization, this assumes that we do not change the
456
- // library code.
457
- // link library in order to avoid spurious code change detections
458
- let slotsBitmapLibraryAddress = ZERO_ADDRESS;
459
- try {
460
- const IDAv1 = await InstantDistributionAgreementV1.at(
461
- await superfluid.getAgreementClass.call(IDAv1_TYPE)
462
- );
463
- slotsBitmapLibraryAddress =
464
- await IDAv1.SLOTS_BITMAP_LIBRARY_ADDRESS.call();
465
- if (process.env.IS_HARDHAT) {
466
- if (slotsBitmapLibraryAddress !== ZERO_ADDRESS) {
467
- const lib = await SlotsBitmapLibrary.at(
468
- slotsBitmapLibraryAddress
469
- );
470
- InstantDistributionAgreementV1.link(lib);
471
- }
472
- } else {
473
- InstantDistributionAgreementV1.link(
474
- "SlotsBitmapLibrary",
475
- slotsBitmapLibraryAddress
476
- );
477
- }
478
- } catch (e) {
479
- console.warn("Cannot get slotsBitmapLibrary address", e.toString());
480
- }
481
- }
482
-
483
- if (protocolReleaseVersion === "test") {
484
- // deploy CFAv1Forwarder for test deployments
485
- // for other (permanent) deployments, it's not handled by this script
486
- await deployAndRegisterContractIf(
487
- CFAv1Forwarder,
488
- "CFAv1Forwarder",
489
- async (contractAddress) => contractAddress === ZERO_ADDRESS,
490
- async () => {
491
- const forwarder = await CFAv1Forwarder.new(superfluid.address);
492
- output += `CFA_V1_FORWARDER=${forwarder.address}\n`;
493
- await web3tx(
494
- governance.enableTrustedForwarder,
495
- "Governance set CFAv1Forwarder"
496
- )(superfluid.address, ZERO_ADDRESS, forwarder.address);
497
- return forwarder;
498
- }
499
- );
500
- }
501
-
502
- let superfluidNewLogicAddress = ZERO_ADDRESS;
503
- const agreementsToUpdate = [];
504
- if (!nonUpgradable) {
505
- if (await superfluid.NON_UPGRADABLE_DEPLOYMENT.call()) {
506
- throw new Error("Superfluid is not upgradable");
507
- }
508
-
509
- // deploy new superfluid host logic
510
- superfluidNewLogicAddress = await deployContractIfCodeChanged(
511
- web3,
512
- SuperfluidLogic,
513
- await superfluid.getCodeAddress(),
514
- async () => {
515
- if (!(await isProxiable(UUPSProxiable, superfluid.address))) {
516
- throw new Error("Superfluid is non-upgradable");
517
- }
518
- const superfluidLogic = await web3tx(
519
- SuperfluidLogic.new,
520
- "SuperfluidLogic.new"
521
- )(nonUpgradable, appWhiteListing);
522
- output += `SUPERFLUID_HOST_LOGIC=${superfluidLogic.address}\n`;
523
- return superfluidLogic.address;
524
- }
525
- );
526
-
527
- // deploy new CFA logic
528
- const cfaNewLogicAddress = await deployContractIfCodeChanged(
529
- web3,
530
- ConstantFlowAgreementV1,
531
- await (
532
- await UUPSProxiable.at(
533
- await superfluid.getAgreementClass.call(CFAv1_TYPE)
534
- )
535
- ).getCodeAddress(),
536
- async () => (await deployCFAv1()).address,
537
- [
538
- // See SuperToken constructor parameter
539
- superfluidConstructorParam,
540
- ZERO_ADDRESS.toLowerCase().slice(2).padStart(64, "0"),
541
- ]
542
- );
543
- if (cfaNewLogicAddress !== ZERO_ADDRESS)
544
- agreementsToUpdate.push(cfaNewLogicAddress);
545
-
546
- // deploy new IDA logic
547
- const idaNewLogicAddress = await deployContractIfCodeChanged(
548
- web3,
549
- InstantDistributionAgreementV1,
550
- await (
551
- await UUPSProxiable.at(
552
- await superfluid.getAgreementClass.call(IDAv1_TYPE)
553
- )
554
- ).getCodeAddress(),
555
- async () => (await deployIDAv1()).address,
556
- [
557
- // See SuperToken constructor parameter
558
- superfluidConstructorParam,
559
- ]
560
- );
561
- if (idaNewLogicAddress !== ZERO_ADDRESS)
562
- agreementsToUpdate.push(idaNewLogicAddress);
563
- }
564
-
565
- // deploy new super token factory logic (depends on SuperToken logic, which links to nft deployer library)
566
- const SuperTokenFactoryLogic = useMocks
567
- ? SuperTokenFactoryMock
568
- : SuperTokenFactory;
569
-
570
- const SuperTokenLogic = useMocks ? SuperTokenMock : SuperToken;
571
-
572
- const factoryAddress = await superfluid.getSuperTokenFactory.call();
573
-
574
- let constantOutflowNFTLogicChanged = false;
575
- let constantInflowNFTLogicChanged = false;
576
-
577
- const deployNFTContract = async (isOutflow, args) => {
578
- const artifact = isOutflow ? ConstantOutflowNFT : ConstantInflowNFT;
579
- const nftType = isOutflow ? "ConstantOutflowNFT" : "ConstantInflowNFT";
580
- const nftTypeCaps = isOutflow
581
- ? "CONSTANT_OUTFLOW_NFT"
582
- : "CONSTANT_INFLOW_NFT";
583
- const flowNFTLogic = await web3tx(
584
- artifact.new,
585
- `${nftType}.new`
586
- )(...args);
587
- console.log(`${nftType} Logic address`, flowNFTLogic.address);
588
- output += `${nftTypeCaps}=${flowNFTLogic.address}\n`;
589
-
590
- await flowNFTLogic.castrate();
591
-
592
- return flowNFTLogic;
593
- };
594
-
595
- const superTokenFactoryNewLogicAddress = await deployContractIf(
596
- web3,
597
- SuperTokenFactoryLogic,
598
- async () => {
599
- console.log(
600
- "checking if SuperTokenFactory needs to be redeployed..."
601
- );
602
- // check if super token factory or super token logic changed
603
- try {
604
- if (factoryAddress === ZERO_ADDRESS) return true;
605
- const factory = await SuperTokenFactoryLogic.at(factoryAddress);
606
- const superTokenLogicAddress =
607
- await factory.getSuperTokenLogic.call();
608
- const superTokenLogic = await SuperTokenLogic.at(
609
- superTokenLogicAddress
610
- );
611
- const constantOutflowNFTAddress =
612
- await superTokenLogic.CONSTANT_OUTFLOW_NFT();
613
- const constantInflowNFTAddress =
614
- await superTokenLogic.CONSTANT_INFLOW_NFT();
615
-
616
- const constantOutflowNFTContract = ConstantOutflowNFT.at(
617
- constantOutflowNFTAddress
618
- );
619
- const constantInflowNFTContract = ConstantInflowNFT.at(
620
- constantInflowNFTAddress
621
- );
622
-
623
- const constantInflowNFTParam = constantInflowNFTAddress
624
- .toLowerCase().slice(2).padStart(64, "0");
625
- const constantOutflowNFTParam = constantOutflowNFTAddress
626
- .toLowerCase().slice(2).padStart(64, "0");
627
- const cfaParam = (await superfluid.getAgreementClass.call(CFAv1_TYPE))
628
- .toLowerCase().slice(2).padStart(64, "0");
629
-
630
- constantOutflowNFTLogicChanged = await codeChanged(
631
- web3,
632
- ConstantOutflowNFT,
633
- await (
634
- await UUPSProxiable.at(constantOutflowNFTAddress)
635
- ).getCodeAddress(),
636
- [superfluidConstructorParam, constantInflowNFTParam, cfaParam]
637
- );
638
- console.log(" constantOutflowNFTLogicChanged:", constantOutflowNFTLogicChanged);
639
-
640
- constantInflowNFTLogicChanged = await codeChanged(
641
- web3,
642
- ConstantInflowNFT,
643
- await (
644
- await UUPSProxiable.at(constantInflowNFTAddress)
645
- ).getCodeAddress(),
646
- [superfluidConstructorParam, constantOutflowNFTParam, cfaParam]
647
- );
648
- console.log(" constantInflowNFTLogicChanged:", constantInflowNFTLogicChanged);
649
-
650
- const superTokenFactoryCodeChanged = await codeChanged(
651
- web3,
652
- SuperTokenFactoryLogic,
653
- await superfluid.getSuperTokenFactoryLogic.call(),
654
- [superfluidConstructorParam]
655
- );
656
- console.log(" superTokenFactoryCodeChanged:", superTokenFactoryCodeChanged);
657
-
658
- const superTokenLogicCodeChanged = await codeChanged(
659
- web3,
660
- SuperTokenLogic,
661
- await factory.getSuperTokenLogic.call(),
662
- // this replacement does not support SuperTokenMock
663
- [
664
- // See SuperToken constructor parameter
665
- superfluidConstructorParam,
666
- constantOutflowNFTParam,
667
- constantInflowNFTParam,
668
- ]
669
- );
670
- console.log(" superTokenLogicCodeChanged:", superTokenLogicCodeChanged);
671
- return (
672
- // check if super token factory logic has changed
673
- // or super token logic has changed
674
- // or constant outflow nft logic has changed
675
- // or constant inflow nft logic has changed
676
- superTokenFactoryCodeChanged ||
677
- superTokenLogicCodeChanged ||
678
- constantOutflowNFTLogicChanged ||
679
- constantInflowNFTLogicChanged
680
- );
681
- } catch (e) {
682
- console.log(
683
- ` re-deploying SuperTokenFactory because checks didn't pass ${e.toString()}`
684
- );
685
- // recreate contract on any errors
686
- return true;
687
- }
688
- },
689
- async () => {
690
- let superTokenFactoryLogic;
691
-
692
- // @note this will either be freshly created proxies on the very first bootstrapping per network
693
- // OR it will be the canonical proxy set on the SuperToken
694
- let cofNFTProxyAddress = ZERO_ADDRESS;
695
- let cifNFTProxyAddress = ZERO_ADDRESS;
696
- let cofNFTLogicAddress = ZERO_ADDRESS;
697
- let cifNFTLogicAddress = ZERO_ADDRESS;
698
-
699
- // try to get NFT proxy addresses from canonical Super Token logic
700
- if (factoryAddress !== ZERO_ADDRESS) {
701
- try {
702
- const factory = await SuperTokenFactoryLogic.at(
703
- factoryAddress
704
- );
705
- console.log(" factory.getSuperTokenLogic.call()");
706
- const superTokenLogicAddress =
707
- await factory.getSuperTokenLogic.call();
708
- const superTokenLogic = await SuperTokenLogic.at(
709
- superTokenLogicAddress
710
- );
711
- cofNFTProxyAddress =
712
- await superTokenLogic.CONSTANT_OUTFLOW_NFT.call();
713
- cifNFTProxyAddress =
714
- await superTokenLogic.CONSTANT_INFLOW_NFT.call();
715
- cofNFTLogicAddress = await (
716
- await UUPSProxiable.at(cofNFTProxyAddress)
717
- ).getCodeAddress();
718
- cifNFTLogicAddress = await (
719
- await UUPSProxiable.at(cifNFTProxyAddress)
720
- ).getCodeAddress();
721
- } catch (err) {
722
- console.error("Unable to get nft proxy addresses");
723
- }
724
- }
725
-
726
- // if the super token logic does not have the proxies, we must deploy
727
- // new nft logic and proxies.
728
- if (
729
- cofNFTProxyAddress === ZERO_ADDRESS &&
730
- cifNFTProxyAddress === ZERO_ADDRESS
731
- ) {
732
- const constantOutflowNFTProxy = await web3tx(
733
- UUPSProxy.new,
734
- `Create ConstantOutflowNFT proxy`
735
- )();
736
- console.log("ConstantOutflowNFT Proxy address", constantOutflowNFTProxy.address);
737
- output += `CONSTANT_OUTFLOW_NFT_PROXY=${constantOutflowNFTProxy.address}\n`;
738
-
739
- const constantInflowNFTProxy = await web3tx(
740
- UUPSProxy.new,
741
- `Create ConstantInflowNFT proxy`
742
- )();
743
- console.log("ConstantInflowNFT Proxy address", constantInflowNFTProxy.address);
744
- output += `CONSTANT_INFLOW_NFT_PROXY=${constantInflowNFTProxy.address}\n`;
745
-
746
- const constantOutflowNFTLogic = await deployNFTContract(true, [
747
- superfluid.address,
748
- constantInflowNFTProxy.address,
749
- ]);
750
- const constantInflowNFTLogic = await deployNFTContract(false, [
751
- superfluid.address,
752
- constantOutflowNFTProxy.address,
753
- ]);
754
-
755
- // set the nft logic addresses (to be consumed by the super token factory logic constructor)
756
- cofNFTLogicAddress = constantOutflowNFTLogic.address;
757
- cifNFTLogicAddress = constantInflowNFTLogic.address;
758
-
759
- // initialize the nft proxy with the nft logic
760
- await constantOutflowNFTProxy.initializeProxy(
761
- constantOutflowNFTLogic.address
762
- );
763
- await constantInflowNFTProxy.initializeProxy(
764
- constantInflowNFTLogic.address
765
- );
766
- const constantOutflowNFT = await ConstantOutflowNFT.at(
767
- constantOutflowNFTProxy.address
768
- );
769
- const constantInflowNFT = await ConstantInflowNFT.at(
770
- constantInflowNFTProxy.address
771
- );
772
-
773
- // initialize the proxy contracts with the nft names
774
- await constantOutflowNFT.initialize("Constant Outflow NFT", "COF");
775
- await constantInflowNFT.initialize("Constant Inflow NFT", "CIF");
776
-
777
- // set the nft proxy addresses (to be consumed by the super token logic constructor)
778
- cofNFTProxyAddress = constantOutflowNFTProxy.address;
779
- cifNFTProxyAddress = constantInflowNFTProxy.address;
780
- } else {
781
- // nft proxies already exist
782
- await deployContractIf(
783
- web3,
784
- ConstantOutflowNFT,
785
- async () => {
786
- return constantOutflowNFTLogicChanged;
787
- },
788
- async () => {
789
- const cofNFTLogic = await deployNFTContract(true, [
790
- superfluid.address,
791
- cifNFTProxyAddress,
792
- ]);
793
- // @note we set the cofNFTLogicAddress to be passed to SuperTokenFactoryLogic here
794
- cofNFTLogicAddress = cofNFTLogic.address;
795
-
796
- return cofNFTLogic.address;
797
- }
798
- );
799
- await deployContractIf(
800
- web3,
801
- ConstantInflowNFT,
802
- async () => {
803
- return constantInflowNFTLogicChanged;
804
- },
805
- async () => {
806
- const cifNFTLogic = await deployNFTContract(false, [
807
- superfluid.address,
808
- cofNFTProxyAddress,
809
- ]);
810
- // @note we set the cifNFTLogicAddress to be passed to SuperTokenFactoryLogic here
811
- cifNFTLogicAddress = cifNFTLogic.address;
812
- return cifNFTLogic.address;
813
- }
814
- );
815
- }
816
-
817
- // deploy super token logic contract
818
- // it now takes the nft logic contracts as parameters
819
- const superTokenLogic = useMocks
820
- ? await web3tx(SuperTokenLogic.new, "SuperTokenLogic.new")(
821
- superfluid.address,
822
- 0,
823
- cofNFTProxyAddress,
824
- cifNFTProxyAddress
825
- )
826
- : await web3tx(SuperTokenLogic.new, "SuperTokenLogic.new")(
827
- superfluid.address,
828
- cofNFTProxyAddress,
829
- cifNFTProxyAddress
830
- );
831
-
832
- console.log(
833
- `SuperToken new logic code address ${superTokenLogic.address}`
834
- );
835
- output += `SUPERFLUID_SUPER_TOKEN_LOGIC=${superTokenLogic.address}\n`;
836
-
837
- superTokenFactoryLogic = await web3tx(
838
- SuperTokenFactoryLogic.new,
839
- "SuperTokenFactoryLogic.new"
840
- )(
841
- superfluid.address,
842
- superTokenLogic.address,
843
- cofNFTLogicAddress,
844
- cifNFTLogicAddress
845
- );
846
- output += `SUPERFLUID_SUPER_TOKEN_FACTORY_LOGIC=${superTokenFactoryLogic.address}\n`;
847
- return superTokenFactoryLogic.address;
848
- }
849
- );
850
-
851
- if (
852
- superfluidNewLogicAddress !== ZERO_ADDRESS ||
853
- agreementsToUpdate.length > 0 ||
854
- superTokenFactoryNewLogicAddress !== ZERO_ADDRESS
855
- ) {
856
- await sendGovernanceAction(
857
- {
858
- host: superfluid,
859
- contracts: {
860
- Ownable,
861
- IMultiSigWallet,
862
- SuperfluidGovernanceBase,
863
- },
864
- },
865
- (gov) =>
866
- gov.updateContracts(
867
- superfluid.address,
868
- superfluidNewLogicAddress,
869
- agreementsToUpdate,
870
- superTokenFactoryNewLogicAddress
871
- )
872
- );
873
- }
874
-
875
- console.log("======== Superfluid framework deployed ========");
876
-
877
- if (process.env.RESOLVER_ADDRESS) {
878
- console.log(
879
- "=============== TEST ENVIRONMENT RESOLVER ======================"
880
- );
881
- console.log(`export RESOLVER_ADDRESS=${process.env.RESOLVER_ADDRESS}`);
882
- }
883
-
884
- if (outputFile !== undefined) {
885
- await util.promisify(fs.writeFile)(outputFile, output);
886
- console.log(
887
- `List of newly deployed contracts written to ${outputFile}`
888
- );
889
- }
890
-
891
- const deployerFinalBalance = await web3.eth.getBalance(deployerAddr);
892
- const consumed = web3.utils.fromWei(
893
- (new web3.utils.BN(deployerInitialBalance)).sub(new web3.utils.BN(deployerFinalBalance)));
894
- console.log(`consumed native coins: ${consumed}`);
895
- });