# QACC User Flow Tutorials The following tutorial covers the deployment and initial setup of an Inverter workflow that includes a (restricted) *Bonding Curve*, a *Role Authorizer*, a *Streaming Payment Processor* and a *Payment Router*. It also includes step by step--by-step instructions for selected user flows. ## 0. Q/ACC specific ### 0.1. Relevant functions | ***Action*** | Contract | Method | Params | | -------- | -------- | - | -------- | | | ***Deploying*** | | | | *deploying a new workflow* | OrchestratrorFactory | `createWorkflow` | check deploy section | | | ***Bonding Curve Interactions*** | | | | *enabling permissioned buying* | FM_BC_Restricted_Bancor_Redeeming_VirtualSupply_v1 | `openBuy` |none| | *disabling permissioned buying* | FM_BC_Restricted_Bancor_Redeeming_VirtualSupply_v1 | `closeBuy` |none| | *ychanging buy fees on BC* | FM_BC_Restricted_Bancor_Redeeming_VirtualSupply_v1 | `setBuyFee` |`fee`: number without decimals| | *granting buy permissions* | FM_BC_Restricted_Bancor_Redeeming_VirtualSupply_v1 | `grantModuleRole` |`role`: the bytes32 representations for roles can be retrieved from the module <br> `target`: the address that should get the role| | *getting "amount out" for a given BC purchase* | FM_BC_Restricted_Bancor_Redeeming_VirtualSupply_v1 | `calculatePurchaseReturn` | `role`: the bytes32 representations for roles can be retrieved from the module `target`: the address that should get the role| | | ***Vesting*** | || | *buying from BC* | FM_BC_Restricted_Bancor_Redeeming_VirtualSupply_v1 | `buyFor` or `buy` |`_receiver`: address that receives tokens, `_depositAmount`: amount of reserve token to be deposited, uint `_minAmountOut`: minimum amount that buyer is expecting to receive| | *setting up vesting* | LM_PC_PaymentRouter_v1 | `pushPayment` |`recipient`: receiver address of vested tokens <br> `paymentToken`: token to be vested <br> `amount`: vesting amount <br> `start`: unix timestamp of vesting start <br> `end`: unix timestamp of vesting end <br> `cliff`: unix timestamp of vesting cliff| | *granting the right to set up vesting* | LM_PC_PaymentRouter_v1 | `grantModuleRole` |`role`: the bytes32 representations for roles can be retrieved from the module <br> `target`: the address that should get the role| | *claiming a vest* | PP_Streaming_v1 | `claimAll` |`client`: address of `LM_PC_PaymentRouter_v1` module | | *cancelling a vest* | LM_PC_PaymentRouter_v1 | `removeAllPaymentReceiverPayments` |`client`: address of `LM_PC_PaymentRouter_v1` module| ## 1. Deploying the workflow ### 1.1. Deployment Parameters | Module | Parameter Name | Description | Additional Notes | | -------- | -------- | -------- | -------- | | Restricted Bonding Curve (=Funding Manager) | | | | | |issuanceToken > `name`|Name of the token issued through the bonding curve|-| | |issuanceToken > `symbol`|Symbol of the token issued through the bonding curve| | | |issuanceToken > `decimals`|Number of decimals of the token issued through the bonding curve|typically `decimals = 18`;<br> has to be larger than `decimals` of the collateral token| | |issuance token > `maxSupply`|Maximum possible supply of the token issued through the bonding curve|-| | |`tokenAdmin`|Can mint/burn and manage minters on the issuance token contract|-| | |bondinCurveParams > `formula`|Bonding curve math implementation address|Multiple curve modules can use the same math implementation| | |bondinCurveParams > `reserveRatioForBuying`|The reserve ratio that is applied when calculating how many tokens a buyer receives| Expressed in parts per million, e.g. `333333` corresponds to 33.3333%| | |bondinCurveParams > `reserveRatioForSelling`|The reserve ratio that is applied when calculating how many tokens a seller receives| Expressed in parts per million, e.g. `333333` corresponds to 33.3333%| | |bondinCurveParams > `buyFee`|The fee that is applied to a token purchase in basis points|Expressed in basis points, e.g. `100` corresponds to 1%| | |bondinCurveParams > `sellFee`|The fee that is applied to a token sale in basis points|Expressed in basis points, e.g. `100` corresponds to 1%| | |bondinCurveParams > `buyIsOpen`|Whether buying from the curve is generally possible|A restricted bonding curve still requires the buyer to hold an appropriate role to be able to buy| | |bondinCurveParams > `sellIsOpen`|Whether selling to the curve is generally possible|A restricted bonding curve still requires the seller to hold an appropriate role to be able to buy| | |bondinCurveParams > `initialTokenSupply`|Initial supply of the issuance token|Passing this value is mostly a technical necessity. Check annotation below table.| | |bondinCurveParams > `initialCollateralSupply`|Initial supply of the collateral token|Passing this value is mostly a technical necessity. Check annotation below table.| | |`tokenAdmin`|Powerful admin role over issuance token|Can mint/burn tokens and set new minters| | |`collateralToken`|Represents the token used as collateral token (e.g. USDC)| | Roles Authorizer (= Authorizer) | | | | | |`initialAdmin`| Defines who holds powerful admin capabilities for the workflow.| Admin can eg assign permissions to buy/sell on bonding curve | | Orchestrator | | | | | |`independentUpdates`| Determines whether workflows can be upgraded and paused by the Inverter Team | | | |`independentUpdateAdmin`| If `independentUpdates = false` this address determines who can manually upgrade workflows | Don't fill if `independentUpdates = true` | > [color=#00FF00] **NOTE** on setting `initialTokenSupply` and `initialCollateralSupply` > The bonding curve math implementation requires these parameters to be set. Which values to use for these parameters depends on the `reserveRatioForBuying`. > > `initialCollateralSupply` and `initialTokenSupply` should be chosen such that their ratio `initialCollateralSupply / initialTokenSupply` corresponds to the [simplest form](https://www.ixl.com/math/lessons/simplest-form) that approximates the `reserveRatioForBuying`. > > *Example: if `reserveRatioForBuying = 333333`, the simplest form that approximates 33.3333% is `1/3`, therefore `initialCollateralSupply = 1` and `initialTokenSupply = 3`* ### 1.2. With the SDK Specify the modules that need to be deployed: Tip: use typescript with a `satisfies` constraint to make sure your `requestedModules` are valid. ```ts= import { RequestedModules } from "@inverter-network/sdk" const requestedModules = { fundingManager: "FM_BC_Restricted_Bancor_Redeeming_VirtualSupply_v1", authorizer: "AUT_Roles_v1", paymentProcessor: "PP_Streaming_v1", optionalModules: ["LM_PC_PaymentRouter_v1"] } satisfies RequestedModules ``` Get the deployment function for your desired workflow: ```ts= import { Inverter } from "@inverter-network/sdk" const sdk = new Inverter(publicClient, walletClient) // the clients correspond to viem's clients const { run } = sdk.getDeploy(requestedModules) ``` Invoke the deployment runner with your deployment arguments: ```ts= const args = { fundingManager: { issuanceToken: { name: 'My Issuance Token', symbol: 'MIT', decimals: '18', maxSupply: '115792', // don't add decimals }, tokenAdmin: '0x823F6AC80759F2e037eaF706d45CB4B47b80926c', bondingCurveParams: { formula: '0x823F6AC80759F2e037eaF706d45CB4B47b80926c', // you need this address for your network from us or our docs reserveRatioForBuying: '333333', // (= 33.33%) unit: PPM reserveRatioForSelling: '333333', // (= 33.33%) unit: PPM buyFee: '0', // unit: basis points sellFee: '100', // (= 1%) unit: basis points buyIsOpen: false, sellIsOpen: false, initialTokenSupply: '100', // don't add decimals initialCollateralSupply: '33', // don't add decimals }, collateralToken: '0xf08a50178dfcde18524640ea6618a1f965821715', // collateral token }, authorizer: { initialAdmin: '0x7AcaF5360474b8E40f619770c7e8803cf3ED1053', // should correspond to your deployer EOA for ease of configuration initially and represents the orchestrator admin }, } const txHash = await run(args) ``` ### 1.3. With the Control Room 1. Connect your wallet with the correct network ___ 2. Choose the corret modules: ![1](https://hackmd.io/_uploads/HkBdcqtHR.png) ___ 3. Choose if you want to turn off upgradeability and pausability through Inverter Governance. Just move to the next page, if you want Inverter to be able tu upgrade and pause modules. ![2](https://hackmd.io/_uploads/HJCuc9tHA.png) ___ 4. Fill in the initial managing address for the authorizer: ![4](https://hackmd.io/_uploads/rkr0cqFHR.png) ___ 5. Fill in the configuration parameters for the bonding curve: a) Define the Issuance Token (= the token that will be issued by the curve) **NOTE**: **You don't have to add decimals to the Max Supply.** The 18 `decimals` specified in the screenshot example will be added to the specified `Max Supply` of 1 Mio automatically through the SDK. ![5a](https://hackmd.io/_uploads/SkAJn9trR.png) b) Define the token administrator and the accepted token that serves as reserve token of the bonding curve ![5b](https://hackmd.io/_uploads/SJbeaqFrR.png) c) Define the Bonding Curve parameters **check section 1.1. for details on deployment parameters** ![5c](https://hackmd.io/_uploads/HJN0eoKB0.png) --- 6. Click deploy and confirm transaction in your wallet Note: you didn't have to provide inputs for the Streaming Payment Provider module, because it doesn't require any deployment parameters. --- ## 2. Selected User Flows All sdk instructions assume that you have instantiated the workflow like so: ```ts= const workflow = await sdk.getWorkflow(orchestratorAddress) // address of previously deployed workflow ``` ### 2.1. Enabling/disabling permissioned buying from the curve The curve has been deployed with buying disabled (check the deployment args in the previous section). In this case, buying needs to be enabled specifically. This can only be done as the *orchestrator admin* (= `initialAdmin` of `authorizer`). Because this example is using a restricted bonding curve module, even with enabled buying, a buyer needs permission to do so. #### 2.1.1. SDK Enabling buying: ```ts= await workflow.fundingManager.write.openBuy.run() ``` Disabling buying: ```ts= await workflow.fundingManager.write.closeBuy.run() ``` #### 2.1.2. Control Room > [color=#FF0000] **NOTE**: requires orchestrator admin role The curve has been deployed with buying disabled (check the deployment args in the previous section). In this case, buying needs to be enabled specifically. This can only be done as the *orchestrator admin* (= `initialAdmin` of `authorizer`). Because this example is using a restricted bonding curve module, even with enabled buying, a buyer needs a specific permission to be able to buy from the curve. * go to `operate` > `Funding Manager` > `write` > `Open Buy` ![open:closeBuy](https://hackmd.io/_uploads/HkCtiSWIA.png) ### 2.2. Changing buy fees Can only be done as the orchestrator admin #### 2.2.1. SDK ```ts= await workflow.fundingManager.write.setBuyFee.run("0") // sets fees to zero await workflow.fundingManager.write.setBuyFee.run("200000") // sets fees to 20% ``` #### 2.2.2. Control Room > [color=#FF0000] **NOTE**: requires orchestrator admin role * go to `operate` > `Funding Manager` > `write` > `Set Buy Fee` * `Fee`: the new buy fee in basis points (e.g. `100` corresponds to 1%) ![setBuyFee](https://hackmd.io/_uploads/H1MIhBWUR.png) ### 2.3. Granting buy rights Can only be done as the orchestrator admin #### 2.3.1. SDK ```ts= // get role identifier for minting from bonding curve const buyerRole = await fundingManager.read.CURVE_INTERACTION_ROLE.run() // buyer: address which should get buy rights // function needs to be called by deployer address await workflow.fundingManager.write.grantModuleRole.run(bcMinterRole, buyer) ``` #### 2.3.2. Control Room > [color=#FF0000] **NOTE**: requires permission to interact with curve #### 2.3.2.1. Buying from curve * go to `operate` > `Funding Manager` > `read` > `Calculate Purchase Return` * `Depositamount`: the amount of collateral tokens used to buy issuance tokens (don't add decimals) * returns the amount of issuance tokens you'll get in return for the deposit amount of collateral tokens * copy that amount (if applicable add slippage) ![calculatePurchaseReturn](https://hackmd.io/_uploads/r1nEAr-UC.png) * go to `operate` > `Funding Manager` > `write` > `Buy For` * `Receiver`: who should receive the issuance tokens * `Depositamount`: how much collateral tokens will be inserted into the curve module (don't add decimals) * `Minamountout`: how much issuance tokens at least are expected to be issued by the curve (can be copied from prev step; don't add decimals) ![buyFor](https://hackmd.io/_uploads/Skg6ENlPR.png) #### 2.3.2.2. Selling to curve * go to `operate` > `Funding Manager` > `read` > `Calculate Sale Return` * `Depositamount`: the amount of issuance tokens sold for collateral tokens (don't add decimals) * returns the amount of collateral tokens you'll get in return for the deposit amount of issuance tokens * copy that amount (if applicable add slippage) ![calculateSaleReturn](https://hackmd.io/_uploads/r1py_VlPA.png) * go to `operate` > `Funding Manager` > `write` > ` * `Receiver`: who should receive the collateral tokens * `Depositamount`: how many issuance tokens will be sold back into the curve module (don't add decimals) * `Minamountout`: how many collateral tokens are at least expected to be returned by the curve (can be copied from prev step; don't add decimals) ![sellFor](https://hackmd.io/_uploads/SkgDONlvR.png) ### 2.4. Buying from the curve Requires role ("CURVE_INTERACTION_ROLE") #### 2.4.1. SDK ```ts= const minAmountOut = await workflow.fundingManager.read.calculatePurchaseReturn.run(depositAmount) // don't add decimals, await workflow.fundingManager.write.buyFor.run([receiverAddress, depositAmount, minAmountOut]) ``` #### 2.4.2. Control Room go to `operate` > `Funding Manager` > `read` * copy amount ![calculatePurchaseReturn](https://hackmd.io/_uploads/r1nEAr-UC.png) go to `operate` > `Funding Manager` > `write` * paste it as Minamountout ![buyFor](https://hackmd.io/_uploads/H1yr0HWUR.png) ### 2.5. Setting up vesting Requires role ("PAYMENT_PUSHER") #### 2.5.1. SDK ```ts= await workflow.optionalModule.LM_PC_PaymentRouter_v1.write.pushPayment.run(recipient, paymentToken, amount, start, cliff, end) // don't bother about adding decimals ``` #### 2.5.2. Control Room go to `operate` > `Optional Module` > `LM_PC_PaymentRouter_v1` > `write` ![pushPayment](https://hackmd.io/_uploads/By6sy8WI0.png) ### 2.6. Granting rights to set up vestings Can only be done as the orchestrator admin #### 2.6.1. SDK Granting rights: ```ts= const vestingCreatorRole = await workflow.optionalModule.LM_PC_PaymentRouter_v1.read.PAYMENT_PUSHER_ROLE.run() await workflow.optionalModule.LM_PC_PaymentRouter_v1.write.grantModuleRole.run(vestingCreatorRole, userAddress) ``` Revoking rights: ```ts= await workflow.optionalModule.LM_PC_PaymentRouter_v1.write.revokeModuleRole.run(vestingCreatorRole, userAddress) ``` #### 2.6.2. Control Room go to `operate` > `Optional Module` > `LM_PC_PaymentRouter_v1` > `read` ![paymentPusher](https://hackmd.io/_uploads/S1MygLWUA.png) go to `operate` > `Optional Module` > `LM_PC_PaymentRouter_v1` > `write` ![grantPaymentPusher](https://hackmd.io/_uploads/S1i1x8W80.png) ### 2.7. Claiming a vest #### 2.7.1. SDK ```ts= await workflow.paymentProcessor.write.claimAll.run() ``` #### 2.7.2. Control Room go to `operate` > `Optional Module` > `LM_PC_PaymentRouter_v1` * copy address of module ![paymentRouterAddress](https://hackmd.io/_uploads/S1G6gLWI0.png) go to `operate` > `PaymentProcessor` >`write` * paste address from previously ![claimAll](https://hackmd.io/_uploads/HJx_gU-LA.png) ### 2.8. Cancelling an ongoing vest Can only be done as the orchestrator admin #### 2.8.1. SDK ```ts= await workflow.optionalModule.LM_PC_PaymentRouter_v1.write.removeAllPaymentReceiverPayments.run(paymentProcessorAddress, paymentReceiver) ``` #### 2.8.2. Control Room go to `operate` > `Optional Module` > `LM_PC_PaymentRouter_v1` * copy address of module ![paymentRouterAddress](https://hackmd.io/_uploads/S1G6gLWI0.png) go to `operate` > `Payment Processor` > `write` * pase address from before * cancels all running vests ![cancelRunningPayments](https://hackmd.io/_uploads/S1xYb8-UA.png)