-
Notifications
You must be signed in to change notification settings - Fork 6
Issuance Factory
In the last episodes of the guide we issued a currency with the CurrencyFactory, and learned the benefits of autonomous liquidity providers, especially for Community Currencies. We walked through the features of ElliplseMarketMaker, and dived into the math behind (gosh, we even realised what that 'ellipse-thingy' means).
We have got through a lot together, but be sure that I left the good parts to the end. In this chapter, I will explain the crowdfunding issuance of Community Currencies with the IssuanceFactory contract. Without further ado, let's give the Power to the People and rock on.
As you might have noticed, the currency's life cycle is divided into two stages.
- The first stage is the currency issuance. We reviewed this in chapter one, where I have inserted CLN into
CurrencyFactoryand received CC back. WithCurrencyFactorycontract, only the issuer can exchange the CLN/CC at this stage. When the issuer acquires enough CC, he finishes this stage callingopenMarketfunction. - At the second stage every participant can perform the CLN/CC exchange, interacting directly with the dedicated
MarketMaker. So this stage is the same for all currencies, no matter how they were issued. We did this in chapter two.
There can be multiple contract for the issuance stage, you learned before about CurrencyFactory and in this chapter you'll learn about IssuanceFactory. Moreover, additional contracts may be introduced later, presenting new issuance models. These factories are kind of a "home" for each currency, and each factory holds a list of currencies that were issued with it. This means that currency issued with CurrencyFactory cannot be used with IssuanceFactory and vice versa.
It's important to note that in both stages the exchange rate is calculated by the the same MarketMaker formula. At the second stage, when the issuance is over, every CLN stakeholder can interact freely with the currency's MarkerMaker to exchange CLN to CC. The contract that created the currency doesn't matter anymore. For example, CurrencyFactory was build in a way that only the currency issuer can exchange CLN/CC at the first stage. He has the precedence advantage, he's the only one that can use the formula and he decides when everybody else can use it by opening the market. So because of the properties of the formula the issuer has a better exchange rate.
But IssuanceFactory suggest a different model for currency issuance. First of all, and I want to say it one more time, everyone can participate in the issuance! Second, everyone get's the same exchange rate. How's that possible ๐ฎ ? Especially after all that stuff I told about the mechanical market making and all that math? Well, there's two points:
- That price doesn't hold for ever
- The amount of tokens that can be bought for this stable price is limited.
So you better catch the train. But, why should the issuer create Community Currency in such way? After all, he is giving up his precedence advantage. First, he doesn't have to gather all CLN funds himself. Secondly, well, I'll reveal this later. But there's a bonus ๐, remember there's an ellipse equation that must hold and just think about the math..
As usual, we start with loading the contract's ABI into MyEtherWallet to get a quick look into its methods. If you don't remember how this is done, you can review this section. Notice that the IssuanceFactory contract has all the functions of CurrencyFactory:

it's because IssuanceFactory extends CurrencyFactory. This means that IssuanceFactory and CurrencyFactory are similar in many ways, and the former is using internally the functions of the latter. Also an important consequence is that both of them have a dedicated MarketMaker for every issued CC. On the other hand, some functionality is just blocked, for example you can't call insertCLNtoMarketMaker or extractCLNfromMarketMaker on IssuanceFactory (the transaction will simply fail).
You can call createCurrency on IssuanceFactory but it will make no sense, instead you should call createIssuance. I want to explain the practical difference between the two factories. With CurrencyFactory, after the execution of createCurrency the issuer is able to make the currency tradable anytime by calling openMarket. The caller of createIssuance doesn't have such freedom, instead he installs a conditions that determines whether the issuance will be successful. If the issuance turned to be insufficient, the currency can't become tradable and it's practically useless.
So let's see the createIssuance arguments to see what this condition is:

I already explained the name, symbol, decimals and totalSupply. Let's explain the new ones:
-
startTime- the date when the issuance opens. The date represented at Unix time, converting 1521363600 to "Human time" gives Sunday, March 18, 2018 9:00:00 AM (GMT). This is soon! I used EpochConverter to covert dates to Unix time and backwards. Just be aware of the difference between your local time and GMT. -
durationTime- number of seconds afterstartTimewhen the issuance would close. I set this to 900000, it's 10 days and 10 hours.
Till now we looked into the time constraint for the issuance, but as I said the number of tokens is limited also. This is defined by:
-
hardCap- the maximum amount of CLN that can be inserted to the CC's dedicatedMarketMakerduring the issuance. When this hard cap is reached the issuance is over, even if the closing time has not reached yet. -
reverseAmount- this is the CLN soft cap for the issuance. This soft cap must be reached for the issuance to become successful. As you guessed this value represents the CLN reservoir (R1) in the market making formula.reverseAmountmust be lesser or equal thanhardCap.
Viewing the createIssuance transaction you can see that it's not much different from createCurrency. Let's open the IssuanceFactory contract in Etherscan. As I did before, I can query read-only functions in Etherscan without a wallet. Querying the created CC in the currencyMap I see the usual data about the currency. But there's another map I want to check, it's called issueMap. Cool, let's query that:

Under the "[ issueMap method Response ]" you see the response. This map holds additional data that describes the currency issuance. I filled most of them with the createIssuance transaction, the other are derived from this data.
-
endTimeis calculated asstartTime+duration. -
targetPriceis the exchange rate of CLN to CC. 254764970653110149 is a big number, but 18 digits are actually used for precision (Solidity can store only integers). So the exchange rate is 254764970653110149 / 1e18 = ~0.254. This means for the issuance 1 CLN = ~0.254 CC. -
clnRaisedis the amount of CLN raised for the issuance.
Before proceeding you should approve IssuanceFactory as the spender of your CLN. If you are not sure about that, here's the particular section from part one about ERC20 tokens. I approved 3000 CLN.
Now I call the participate function of IssuanceFactory. There are multiple implementations for this function, and I take the one which takes two parameters - token and clnAmount. Maybe someday I'll have the time to talk about those functions with less arguments. They are intended for further smart contract development, so as users we can ignore them. Back to business, I participate with 1000 CLN.

The transaction looks pretty familiar as it is similar to the insertCLNtoMarketMaker transaction we did in part one. As before, 1000 CLN have been transferred from my account to the IssuanceFactory and then to the dedicated MarketMaker. In return ~ 1139 CC was released from the MarketMaker to IssuanceFactory, but then just ~254 CC was sent to back to me. Interesting ๐ค.. I think I was hoping for more seeing that bunch of CLN got released. But this aligns with the promised exchange rate, 1000 CLN * ~0.254 = ~254 CC.
Should I regret this rate? As an issuer, it depends, I could create the currency by myself with CurrencyFactory, grabbing all the excessive CLN tokens. But I'll lose having the community as the initial currency stakeholders, this is important. Also remember the bonus I promised? we're getting to it. But as a participant there's nothing to regret cause this functionality was allowed to the issuer only. By the way, notice that the exchange rate of 1000 CLN to ~1139 CC is exactly the same as the one of insertCLNtoMarketMaker from chapter one. This is because the supplies and reservoirs of the CommunityCurrency and the CrowdCoin were the same at the moment of exchange.
Now I'll participate with another account to show that: a) the exchange rate is stable, b) everyone can participate ๐. After approving 1000 CLN for my other wallet, I'm participating in the same issuance. So here 1000 CLN were exchanged to ~471 CC by the MarkerMaker, but I still got the same ~254 CC that were promised. You can see how fast the exchange rate drops, but that should not surprise you after we dived into the math behind in chapter two. I can assume that even if the exchange rate will be less than 0.254 CC for 1 CLN, the participant still get the promised exchange rate. This CLN "refund" will come from the first transactions that were conducted with better exchange rates.
Let's find out if someone but me participated in the issuance. Querying issueMap of IssuanceFactory to find out how much CLN is raised, I see that 3000 CLN is already raised. So another 1000 CLN was raised, looking into all tranfers of the CC token here it's not hard to find the participation transaction.
Now I want to reach the soft cap, so I participate with another 2000 CLN. Looking at the transaction I see that the MarkerMaker has sent ~574 CC to the IssuanceFactory and it sent ~509 (~254 * 2) tokens back to me. While the promised exchange rate doesn't change - it's still ~0.254 CC for 1 CLN, the MarkerMaker's exchange rate is diminishing (CC becomes more valuable). We see that the numbers are getting closer. Now, that exactly 5000 CLN have been raised, long live the CrowdCoin:

The IssuanceFactory withholds some of the CC, let's find out how much. Usually, this is done by reading the balanceOf method of the CC's contract. But opening the BadCoin, I find out that its contract is unverified, so it doesn't contain the a "Read Smart Contract" section or the ABI. We had a similar problem in chapter two while interacting with the dedicated MarketMaker, and we will use a similar solution now. Looking into the reference docs of ColuLocalCurrency (the CC's contract) and ColuLocalNetwork (the CLN contract) I see that their specifications are very alike. Both of them comply to the ERC20 token standard, so both of them have got the same functions as approve, allowance, transfer, transferFrom and etc. I wrote a little about these methods in chapter one. In short it means that I can take the ABI of the CLN contract for the CC contract. So doing this, I query the balanceOf with the adddress of IssuanceFactory:

That number is ~1273 CC which the IssuanceFactory has withheld from participate transactions.
The soft cap is a turning point, so it seems like the right time to sum up. As we saw before, the IssuanceFactory holds ~1273 CC. Does it also have CLN? Checking the balanceOf of the CLN contract I see that it also has 5000 CLN in it, although this could be CLN that belongs to other issuances. So it's hard to determine how much CLN has been raised by my issuance using this method. Until now the IssuanceFactory didn't withhold any CLN, it just sent in the MarkerMaker. So this 5000 CLN got there as a result of some other transactions I'm not aware of, there's other currencies issued with the IssuanceFactory. We'll get to this, let's just keep this number in mind.
Now, I want to participate with another 1000 CLN. Can you see what's weird about that transaction? It doesn't use the MarkerMaker at all! the ~254 CC have got transferred from the IssuanceFactory to the sender account, that's all. So how much CC does the IssuanceFactory hold now?

It's ~1019 CC, so as expected the IssuanceFactory CC surplus has decreased by ~254 CC. On the other hand, the IssuanceFactory CLN surplus has increased, it's now 6000 CLN:

That explains that 5000 CLN we saw before. That must be some other issuance that bypassed the soft cap. Furthermore, if I participate once again, more CC will leave the IssuanceFactory and more CLN will be added. It's clear that this exchange cannot hold forever, at some point the CC surplus of the IssuanceFactory will drain away. Then the promised price cannot be provided anymore. Actually, "that point when CC ends" is exactly the hard cap. Just do the rough math: ~1019 CC in the surplus reserve, ~254 CC for 1000 CLN is the exchange rate, when the amount of CLN raised reaches 10000 the CC reserve will be 0.
The MarketMaker provides a variable exchange rate that is especially steep when the currency is created. This is good for an open market, but during the issuance we can benefit more from something different. I think that the model we introduced with the IssuanceFactory is suitable for the issuance of community currencies with a big number of participants.
The IssuanceFactory is acting like a custodian during the issuance: it holds the CLN surplus at first, and completes the CLN shortage later. This smooths the exchange rate, and, graphically speaking, turns the rate curve into a horizontal line without a slope.
Overall, the issuance of the CrowdCoin went pretty well. It passed the soft cap, reaching eventually 6000 CLN. Now I need to open the market, like we did in part one. This is done calling the finalize method. This method can be called only once by the currency issuer, also the issuance has to be over and be successful. So I'm calling this method, giving CrowdCoin's address as an argument. The transaction is pretty suprising ๐. Remember the remainder of ~1019 CC and 1000 CLN? Since the issuance was successful, all this surplus have got transferred to the issuer! The purpose of these funds is to develop the community, generate value to the new community currency, and pay variable expenses. For example, the issur can distribute the tokens to the early adopters, thus expanding the community with new businesses and users.
There's a possibility that the soft cap will not be reached during the issuance, in that case the invested CLN can be refunded. For example I created another coin. I called it BadCoin to give a hint that this currency is not going to be a great success ๐
. So I was the only one who participated in the issuance, and the soft cap of 5000 CLN wasn't hit. It's obvious that nobody will use my coin, and I cannot call finalize to open the market because the issuance was unsuccessful. Clearly, I want my CLN back.
That's what refund function is meant for. After the unsuccessful issuance is over, every CC holder can execute the refund function to exchange back CC to CLN. To use refund, first you need to approve the IssuanceFactory to use your CC, just like with the CLN tokens. We showed how this is done in [Interacting the CC contract](#Interacting the CC contract) section, now we just use approve function istead of balanceOf. I signing the transaction and approve 10000 BadCoin tokens for IssuanceFactory (I can approve more than I have), that's how it looks like:

If you don't sure how much CC tokens you have, you can call the read-only balanceOf method on the same CC contract:

Another way is to check the participate transaction, here you can see that I've got ~254 BC tokens, multiplying it by 1e18 gives the same number. Now we can proceed to the refund:

Investigating the transaction we can see that:
- I transferred ~254 BC tokens to
IssuanceFactory - The
IssuanceFactorytransferred back ~1,139 BC tokens to theMarkerMaker. So with mine tokens, it transferred back the surplus also. - In the opposite direction, 1000 CLN transferred from the
MarketMakertoIssuanceFactory. - then
IssuanceFactorytransferred that 1000 CLN back to me.
Sweet, I've got my CLN back. No money lost ๐. But what's the future of my BadCoin? There's no way to acquire more coins - the issuance is over so no once can participate anymore, and the MarketMaker can't be open. Though the IssuanceFactory will continue to hold the token's data forever, the BadCoin have become a part of history.