Skip to main content

Β· 4 min read
Sem
note

The first version of this article was published in the 1hive forum.

Luke once described 1hive as cybernetic superorganism, I didn't realized it was an established term in science to describe such an amazing natural phenomenon.

Together we thrive​

1hive is a decentralized autonomous organization, but that doesn't really mean very much to very many people, and even for people that are familiar with DAOs, the term has been used in so many different context that it has lost much of its meaning.

Superorganism - Wikipedia​

A superorganism or supraorganism is a group of synergetically interacting organisms of the same species. A community of synergetically interacting organisms of different species is called a holobiont. The term superorganism is used most often to describe a social unit of eusocial animals, where division of labour is highly specialised and where individuals are not able to survive by themselves for extended periods. Termite cathedral

A bee hive can be considered a superorganism as well which has a very interesting way to gather information from each individual bee through quorum sensing:

Honey bees (Apis mellifera) also use quorum sensing to make decisions about new nest sites. Large colonies reproduce through a process called swarming, in which the queen leaves the hive with a portion of the workers to form a new nest elsewhere. After leaving the nest, the workers form a swarm that hangs from a branch or overhanging structure. This swarm persists during the decision-making phase until a new nest site is chosen.

The quorum sensing process in honey bees is similar to the method used by Temnothorax ants in several ways. A small portion of the workers leave the swarm to search out new nest sites, and each worker assesses the quality of the cavity it finds. The worker then returns to the swarm and recruits other workers to her cavity using the honey bee waggle dance. However, instead of using a time delay, the number of dance repetitions the worker performs is dependent on the quality of the site. Workers that found poor nests stop dancing sooner, and can, therefore, be recruited to the better sites. Once the visitors to a new site sense that a quorum number (usually 10–20 bees) has been reached, they return to the swarm and begin using a new recruitment method called piping. This vibration signal causes the swarm to take off and fly to the new nest location. In an experimental test, this decision-making process enabled honey bee swarms to choose the best nest site in four out of five trials.

Here are two "primary regulation mechanisms" for regulating bee colony behavior at the group level, and two of four or five observed mechanisms known to be used by honeybees to change the task allocation among worker bees:

Waggle dance​

By performing a waggle dance, successful foragers can share information about the direction and distance to patches of flowers yielding nectar and pollen, to water sources, or to new nest-site locations with other members of the colony.

Tremble dance​

A tremble dance is a dance performed by forager honey bees of the species Apis mellifera to recruit more receiver honey bees to collect nectar from the workers.

Read more about signaling in nature​

I have found it very interesting leaning about this and other biotic interactions, such as how trees communicate with each other using a symbiosis of their roots with the network of fungi that connect them to other trees in order to exchange sugar, water, and minerals or be aware of predatory insects. You can read more on this in:

The Social Life of Forests (Published 2020)​

The Social Life of Forests As a child, Suzanne Simard often roamed Canada's old-growth forests with her siblings, building forts from fallen branches, foraging mushrooms and huckleberries and occasionally eating handfuls of dirt (she liked the taste). Her grandfather and uncles, meanwhile, worked nearby as horse loggers, using low-impact methods to selectively harvest cedar, Douglas fir and white pine.

Β· 5 min read
Sem
note

You can find the first version of this article as a hackmd published during the ETHOnline '21 hackathon.

Osmotic Funding is a protocol built on top of Superfluid Finance and Conviction Voting to create and regulate project funding streams based on the amount of interest a community gives them. Community preference is revealed continuously, since tokenholders are able to update their preferences (change their stake) at any moment.

A community of tokenholders (DAO) can use Osmotic Funding to decide which parts of the DAO should receive funding and how much. Funding proposals need a minimum amount of support to start receiving funds. Once the flow is open, they can grow or shrink over time, depending on the stake with which the token holders are supporting the proposals.

Mechanism​

We have prepared a desmos for displaying the different parameters and calculations the algorithm uses to distribute funds. >> Please go ahead and play along with it <<.

Depending on the distribution of staked tokens and the available funds in the pool, we can calculate which will be the rate of each proposal with:

r∞(i)=Bβ‹…(1βˆ’Tmax(T,si))whereΒ T=Ξ³β‹…(s0+s1+...+sn)+T0Β andΒ Β B=bβ‹…Ξ²r_\infty(i) = B Β· \left ( 1 - \sqrt{\frac{T}{max(T, s_i)}} \right ) \\ \textrm{where}\ T = \gamma Β· (s_0 + s_1 + ... + s_n) + T_0\\\textrm{ and }\ B = b Β· \beta

  1. The target rate (r∞r_\infty) of a proposal (ii) is the amount of funds a project should be receiving per second in the future.
  2. The pool balance (bb) is the amount of funding tokens that can be transmitted to grants. It will keep diminishing if there are no inflows that fund the contract at the same rate.
  3. Max spending ratio (Ξ²\beta) is the max percentage of the pool balance that one proposal can spend per second.
  4. Threshold (TT) is the minimum amout of staked tokens a proposal needs to start getting funded depending on amount staked on the rest of the proposals.
    • Threshold ratio (Ξ³\gamma) determines the increse in the threshold for each new token staked on any proposal.
    • Min threshold (T0T_0) is the minimum amount of tokens required to fund a proposal when no other proposal is being funded.
    • Total staked tokens (s0+s1+...+sns_0 + s_1 + ... + s_n) are the amount of tokens that are actively voting in the protocol. It plays against a proposal if new tokens are staked on other proposals.
  5. Staked tokens (sis_i) are how many tokens are staked on the proposal which we calculate the rate for.

When the staked amount on a proposal (sis_i) changes, the rate changes over time following the following formula:

rt(i)=Ξ±tβ‹…r0(i)+(1βˆ’Ξ±t)β‹…r∞(i)r_{t}(i) = \alpha^t Β· r_{0}(i) + (1-\alpha^t) Β· r_{\infty} (i)

  1. The current rate (rtr_t) of a proposal (ii) is the amount of funds per second a proposal receives in a particular instant of time (tt).
  2. The last rate (r0r_0).
  3. The exponential decay base (Ξ±\alpha) is a number from 0 to 1 that determines the speed in which the current rate is going to reach the target rate.

As you can see the formula has two parts. The first part starts with last rate and ends at zero over time. The second part starts at zero and grows up to target ratio over time.

Every time the target ratio changes (due to a change in token staking), we define the current ratio as the last ratio, so the rate over time can still be a continuous formula, and we reset the timer (tt) to zero.

In order to know the amount of funds a proposal has accrued since the last time there was a stake change, we can calculate the definite integral of the current rate (rtr_t) formula over time:

ft(i)=∫0xrt(i)Β dt=∫0x[Ξ±tβ‹…r0(i)+(1βˆ’Ξ±t)β‹…r∞(i)]dtf_{t}(i) = \int_{0}^x r_t(i)\ dt= \int_{0}^x \left[\alpha^t Β· r_{0}(i) + (1-\alpha^t) Β· r_{\infty} (i) \right]dt

ft(i)=(1βˆ’Ξ±x+xln⁑α)β‹…r∞(i)βˆ’(1βˆ’Ξ±x)β‹…r0(i)ln⁑αf_{t}(i) = \frac{\left(1-\alpha^{x}+x\ln\alpha\right) Β· r_\infty(i)-\left(1-\alpha^{x}\right) Β· r_0(i)}{\ln\alpha}

Because the target rate formula (r∞r_\infty) does not depend on the time, we can treat it as a constant in the integral, which makes it not-so-difficult to calculate.

It calculates is the area below the curve defined by the current rate formula over time, which correspond to the amout of funds, or what is the same, the average rate (of all variations of rt(i)r_t(i) over the period of time) multiplied by time (tt).

Appendix

Some research on botany​

We have done some research in botany in order to understand how plants distribute their resources. We hope you can

  • Vascular tissue - plants have different types of conducting tissues:
    • Xylem - transports water and minerals from the roots upwards. Types:
      • Tracheid - primitive tissue, produces softwood.
      • Xylem vessel - present in most flowering plants, produces hardwood.
    • Phloem - transports products of photosynthesis to various parts of the plant.
  • Vascular bundle - Joins many tissues, including xylem and phloem.
  • Stele - central part of the root or stem of a plant, which contains vascular tissue.
    • Most seed plant stems primary vascular tissue are vascular bundles.
    • Photo gallery.
  • Osmosis - why water moves from the root to the leaves.

The presence of vessels in xylem has been considered to be one of the key innovations that led to the success of the flowering plants.

Screenshot​

Β· 9 min read
Sem
note

The first version of this article was published in the 1hive forum.

Some days ago I pointed out some inconsistencies I found in the issuance policy 1hive is using at the moment. After some days of thinking about it, I'd like to share with the community my work until now. This post has two purposes:

  • Propose a new issuance policy for 1hive and the rest of gardens
  • Educate about the process I've followed to obtain a result like this.

Our new Dynamic Issuance Policy?​

As the old policy, the proposed Dynamic Issuance v2 tends over time towards a particular ratio between the token balance of the common pool and the total supply (or circulating supply) of the token.

We call this ratio towards the issuance mints or burns tokens the target ratio, a number between 0 and 1.

The new issuance policy is configured using two parameters, target ratio, already used in the previous version, and recovery time, a new parameter that sets the maximum time that it cost for the ratio to recover the target percent.

The formulas that determine the ratio over time when there are no inflows or outflows on the common pool are as follow:

  • When we start with a ratio below the target ratio (we mint tokens into the common pool): f(x)=βˆ’tr2(xβˆ’r)2+tf(x)=\frac{-t}{r^{2}}\left(x-r\right)^{2}+t
  • When we start with a ratio above the target ratio (we burn tokens from the common pool): f(x)=1βˆ’tr2(xβˆ’r)2+tf(x)=\frac{1-t}{r^{2}}\left(x-r\right)^{2}+t

Note that both of these formulas only apply within the recovery time, after this period, the new ratio is target ratio.

You can observe how these formulas work in this desmos. You can use target ratio to move the ratio vertically and recovery time to move the point in which curves touch each other.

Screenshot from 2021-07-31 21-02-00|690x442

It's very unlikely that our common pool is totally full or totally empty at any point, but those equations determine the path that the ratio will travel during time starting from any point. So if we start with a ratio of 20% (current ratio), we see how the curve travels a shorter path (blue lines in the chart above).

The "blue line" formula is a bit more complex as we have to translate the equation horizontally until it matches the current ratio in the Y-axis. It is the following piecewise formula:

Screenshot from 2021-07-31 22-09-16|679x222

This can be gracefully translated to Solidity code, as we can see here (or in remix):

pragma solidity ^0.4.24;

import "@aragon/os/contracts/lib/math/SafeMath.sol";


contract DynamicIssuance {
using SafeMath for uint256;

uint256 constant public RATIO_PRECISION = 1e10;

uint256 public targetRatio;
uint256 public recoveryTime;

constructor(uint256 _targetRatio, uint256 _recoveryTime) public {
targetRatio = _targetRatio;
recoveryTime = _recoveryTime;
}

function calculateRatio(uint256 _lastRatio, uint256 _time) public view returns (uint256 _ratio) {
uint256 shared;
_ratio = _lastRatio;
if (_ratio < targetRatio) {
// _time < recoveryTime * sqrt(targetRatio * (targetRatio - _ratio))
shared = recoveryTime.mul(_sqrt(targetRatio.mul(targetRatio.sub(_ratio))));
if (_time < shared.div(targetRatio)) {
// (_ratio * recoveryTime ** 2 + 2 * _time * shared - targetRatio * _time ** 2) / (recoveryTime ** 2)
_ratio = _ratio.mul(recoveryTime.mul(recoveryTime)).add(_time.mul(shared).mul(2)).sub(targetRatio.mul(_time.mul(_time))).div(recoveryTime.mul(recoveryTime));
} else {
_ratio = targetRatio;
}
} else if (_ratio > targetRatio) {
// recoveryTime * sqrt((1 - targetRatio) * (_ratio - targetRatio))
shared = recoveryTime.mul(_sqrt(RATIO_PRECISION.sub(targetRatio).mul(_ratio.sub(targetRatio))));
if (_time < shared.div(RATIO_PRECISION.sub(targetRatio))) {
// (_ratio * recoveryTime ** 2 - 2 * _time * shared + (RATIO_PRECISION - targetRatio) * _time ** 2) / (recoveryTime ** 2)
_ratio = _ratio.mul(recoveryTime).mul(recoveryTime).sub(_time.mul(shared).mul(2)).add(RATIO_PRECISION.sub(targetRatio).mul(_time).mul(_time)).div(recoveryTime.mul(recoveryTime));
} else {
_ratio = targetRatio;
}
} else {
_ratio = targetRatio;
}
}

function _sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}

This is just a proof-of-concept code, the real smart contract has to actually mint or burn tokens to/from the common pool, in a similar way we were doing with the old policy (calling executeAdjustment()).

For this particular policy, we will also need to do adjustments every time that the token supply changes (some tokens are minted or burnt), or there are inflows or outflows in the common pool. This means that we will need to register the Dynamic Issuance app as a hook for the Hooked Token Manager in order to be able to act when these events occur.

How did I arrived to this result​

Obtaining the "pristine" formulas​

I think this can be a great opportunity to explain how we can design token policies using simple math models. I recommend using desmos when you do this kind of explorations during the first stage.

We know that we would like a curve, so we start with the formula y=xΒ² because powers and square roots are easy to calculate in Solidity. If we divide the formula by r, we will find that the formula then passes by the points (r,r) and (-r, r).

y=1rx2y = \frac{1}{r}x^2

When r=8 the point (8,8) is touched by the curve|690x375

If we want it to pass by the point (r, t), which is when the recovery time (r) ends and the ratio (x) is target ratio (t), we have to divide by r again in order to obtain the point (r, 1), and by t to obtain (r, t):

y=tr2x2y = \frac{t}{r^2}x^2

When t=0.2 the point (8,0.2) is touched by the curve|690x311

We now have a formula that passes by the points (0,0) and (r, t), but it doesn't have the shape that we want, as it should decrease it's speed of emission of tokens as it reaches the target goal instead of increasing it.

In order to solve that issue we are going to apply some geometrical transformations. We will first flip the chart upside down and then we will move the entire chart from point (0, 0) to point (r, t). To flip the chart we just have to multiply the formula by -1:

y=βˆ’tr2x2y = -\frac{t}{r^2}x^2

It is the same curve but flipped|690x306

And to move the maximum of the formula, currently at point (0, 0), into the point in which recovery time has passed and we reach the target ratio (r, t), we can do a simple translation, substracting r from x and t from y:

y=βˆ’tr2(xβˆ’r)2+ty=-\frac{t}{r^2}(x-r)^2+t

It is the same curve but translated to the top right|690x299

The "deflationary" formula can be obtained by replacing the -t factor by 1-t. It inverts the shape of the formula again because 1-t is positive (knowing that t≀1), and we want the formula go from 1 to t so its height must be 1-t:

y=1βˆ’tr2(xβˆ’r)2+ty=\frac{1-t}{r^2}(x-r)^2+t

Inverted curve coming from (0,1) point|690x399

Obtaining the "left-shifted" formulas​

In order to shift the formulas to the left until they touch the point (0,c) so we start at time 0 with a specific ratio (c). When you need to work with equations, Wolfram Alpha is your friend.

We isolate x from the "inflationary" formula and we obtain the following result:

x=rtβˆ’rt2βˆ’tβ‹…f(x)tx=\frac{rt-r\sqrt{t^2-t\cdot f(x)}}{t}

We then add on the left side a shift to the point in which f(0)=c, and then solve f(x-c):

x+rtβˆ’rt2βˆ’tct=rtβˆ’rt2βˆ’tβ‹…f(xβˆ’c)tβ†’f(xβˆ’c)=cr2+2rxt(tβˆ’c)βˆ’tx2r2x+\frac{rt-r\sqrt{t^2-tc}}{t}=\frac{rt-r\sqrt{t^2-t\cdot f(x-c)}}{t}\rightarrow f(x-c)=\frac{cr^{2}+2rx\sqrt{t(t-c)}-tx^{2}}{r^{2}}

We do the same for the "deflationary" formula, first isolate x:

x=r(tβˆ’1)(tβˆ’y)tβˆ’1+tx=\frac{r\sqrt{(t-1)(t-y)}}{t-1}+t

And then obtain the "left-shifted" formula:

x+r(tβˆ’1)(tβˆ’c)tβˆ’1+t=r(tβˆ’1)(tβˆ’f(xβˆ’c))tβˆ’1tβ†’f(xβˆ’c)=cr2βˆ’2rx(1βˆ’t)(cβˆ’t)+(1βˆ’t)x2Β r2x+\frac{r\sqrt{(t-1)(t-c)}}{t-1}+t=\frac{r\sqrt{(t-1)(t-f(x-c))}}{t-1}t\rightarrow f(x-c)=\frac{cr^{2}-2rx\sqrt{(1-t)(c-t)}+\left(1-t\right)x^{2}\ }{r^{2}}

&quot;Left-shifted&quot; &quot;deflationary&quot; formula with c=0.4|690x392

We also have to take into account that recovery time is going to be less, since we are not starting from 0% or 100%. We have to calculate where the global maximum and minimum of the formulas are in order to avoid going backwards.

The maximum of the pristine "inflationary" formula is r, as it is how we defined it from the beginning. The maximum of the "left-shifted" "inflationary" formula can be found equating it's first derivative to 0.

ddxcr2+2rxt(βˆ’(cβˆ’t))βˆ’tx2r2=2(rt(tβˆ’c)βˆ’tx)r2=0β†’x=rt(tβˆ’c)t\frac{d}{dx}\frac{c r^2 + 2 r x \sqrt{t (-(c - t))} - t x^2}{r^2} = \frac{2\left(r\sqrt{t(t-c)}-tx\right)}{r^2}=0\rightarrow x=\frac{r\sqrt{t(t-c)}}{t}

So we know now the point in which we should stop applying the formula and return target ratio instead (used in the piecewise formula above).

We can do the same for the "left-shifted" "deflationary" formula, obtaining the x in which:

ddx(cr2βˆ’2rx(tβˆ’1)(βˆ’(cβˆ’t))βˆ’tx2+x2r2=βˆ’2(r(tβˆ’1)(tβˆ’c)+(tβˆ’1)x)r2=0β†’x=r(1βˆ’t)(cβˆ’t)1βˆ’t\frac{d}{dx}\frac{(c r^2 - 2 r x \sqrt{(t - 1) (-(c - t))} - t x^2 + x^2}{r^2} = -\frac{2\left(r\sqrt{(t-1)(t-c)}+(t-1)x\right)}{r^2}=0\rightarrow x=\frac{r\sqrt{(1-t)(c-t)}}{1-t}

Which is the check that we do in the piecewise formula when the current ratio (c) is greater than target ratio (t).

In this formula, we find the minimum at x=4, for any x&gt;=4 the piecewise formula should return the target ratio|690x397

Coding the formula​

After defining the formula, it was straightforward to write the Solidity code for it. The only think I had to take into account is that ratios are scaled with a factor of 10^10 in order to be able to operate with Solidity (the language has no native support for decimals).

So when I was dealing with the ratios in the code you have to remember that, and use RATIO_PRECISION constant instead of 1 to do the calculations.

Also the use of fixed point arithmetic could interfere with the function _sqrt(uint256 y) but we have been lucky and all the square roots we needed to do where already multiplications of two ratio-scaled factors, so the result was also ratio-scaled.

Conclusion​

This post has presented a piecewise formula to model the proposed Dynamic Issuance Policy v2, alongside with a proof-of-concept Solidity smart contract. I think it is a considerable improvement in respect to the previous version, but I would love to hear the comments of the community members 🐝 in order to go forward with the proposal.

This post has also been useful to explain in a detailed way the process of obtaining the formula. Hopefully this method can be replicated in the future by other token engineers to create similar policies, not only for token issuance but also for other endeavours. I hope it becomes a helpful resource in the process of designing and implementing of a token policy from its inception to the functional code.


Edited 3rd August, 2021: @divine_comedian helped me clarify some terms that were a bit opaque in the first version.