Skip to content

Commit

Permalink
Merge branch 'cw-abc' into improvements/cw-abc
Browse files Browse the repository at this point in the history
  • Loading branch information
ismellike committed Sep 17, 2024
2 parents 85654cf + 455880f commit 848cecd
Show file tree
Hide file tree
Showing 65 changed files with 9,125 additions and 135 deletions.
600 changes: 510 additions & 90 deletions Cargo.lock

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ cosm-tome = "0.2"
cosmos-sdk-proto = "0.19"
cosmwasm-schema = { version = "1.5.4" }
cosmwasm-std = { version = "1.5.4", features = ["ibc3", "cosmwasm_1_1"] }
cw-address-like = "1.0.4"
cw-controllers = "1.1"
cw-multi-test = { version = "0.20.1", features = ["cosmwasm_1_1"] }
cw-storage-plus = { version = "1.1" }
Expand All @@ -55,15 +56,19 @@ cw4-group = "1.1"
cw721 = "0.18"
cw721-base = "0.18"
env_logger = "0.10"
getrandom = "0.2"
integer-sqrt = "0.1.5"
integer-cbrt = "0.1.2"
once_cell = "1.18"
omniflix-std = "0.1.8"
osmosis-std = "0.20.1"
osmosis-std-derive = "0.20.1"
osmosis-test-tube = "20.1.1"
osmosis-test-tube = "20.1.2"
proc-macro2 = "1.0"
prost = { version = "=0.12.3", features = ["prost-derive"] }
prost-types = { version = "=0.12.3", default-features = false }
prost-derive = "=0.12.3"
rust_decimal = "1.14.3"
quote = "1.0"
rand = "0.8"
schemars = "0.8"
Expand All @@ -76,6 +81,7 @@ sg-multi-test = "3.1.0"
sg-std = "3.1.0"
sg721 = "3.1.0"
sg721-base = "3.1.0"
speculoos = "0.11.0"
syn = { version = "1.0", features = ["derive"] }
test-context = "0.1"
thiserror = { version = "1.0" }
Expand All @@ -88,7 +94,9 @@ tokio = "=1.38.1"
cw-ownable = "0.5"

btsg-ft-factory = { path = "./contracts/external/btsg-ft-factory", version = "2.5.0" }
cw-abc = { path = "./contracts/external/cw-abc", version = "2.5.0" }
cw-admin-factory = { path = "./contracts/external/cw-admin-factory", version = "2.5.0" }
cw-curves = { path = "./packages/cw-curves", version = "2.5.0" }
cw-denom = { path = "./packages/cw-denom", version = "2.5.0" }
cw-fund-distributor = { path = "./contracts/distribution/cw-fund-distributor", version = "2.5.0" }
cw-hooks = { path = "./packages/cw-hooks", version = "2.5.0" }
Expand All @@ -103,6 +111,7 @@ cw-wormhole = { path = "./packages/cw-wormhole", version = "2.5.0" }
cw20-stake = { path = "./contracts/staking/cw20-stake", version = "2.5.0" }
cw721-controllers = { path = "./packages/cw721-controllers", version = "2.5.0" }
cw721-roles = { path = "./contracts/external/cw721-roles", version = "2.5.0" }
dao-abc-factory = { path = "./contracts/external/dao-abc-factory", version = "2.5.0" }
dao-cw721-extensions = { path = "./packages/dao-cw721-extensions", version = "2.5.0" }
dao-dao-core = { path = "./contracts/dao-dao-core", version = "2.5.0" }
dao-dao-macros = { path = "./packages/dao-dao-macros", version = "2.5.0" }
Expand Down
2 changes: 1 addition & 1 deletion contracts/dao-dao-core/schema/dao-dao-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -1851,7 +1851,7 @@
"additionalProperties": false
},
{
"description": "Lists all of the items associted with the contract. For example, given the items `{ \"group\": \"foo\", \"subdao\": \"bar\"}` this query would return `[(\"group\", \"foo\"), (\"subdao\", \"bar\")]`.",
"description": "Lists all of the items associated with the contract. For example, given the items `{ \"group\": \"foo\", \"subdao\": \"bar\"}` this query would return `[(\"group\", \"foo\"), (\"subdao\", \"bar\")]`.",
"type": "object",
"required": [
"list_items"
Expand Down
6 changes: 6 additions & 0 deletions contracts/external/cw-abc/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
wasm-debug = "build --target wasm32-unknown-unknown"
unit-test = "test --lib"
integration-test = "test --test integration"
schema = "run --example schema"
56 changes: 56 additions & 0 deletions contracts/external/cw-abc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[package]
name = "cw-abc"
authors = [
"Ethan Frey <ethanfrey@users.noreply.github.com>",
"Jake Hartnell",
"Adair <adairrr@users.noreply.github.com>",
"Gabe Lopez <ismellike@users.noreply.github.com>",
]
description = "Implements an Augmented Bonding Curve"
# Inherits license from previous work
license = "Apache-2.0"
edition = { workspace = true }
repository = { workspace = true }
version = { workspace = true }

[lib]
crate-type = ["cdylib", "rlib"]

[features]
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []
# use test tube feature to enable test-tube integration tests, for example
# cargo test --features "test-tube"
test-tube = []
# when writing tests you may wish to enable test-tube as a default feature
# default = ["test-tube"]

[dependencies]
cw-utils = { workspace = true }
cw2 = { workspace = true }
cw-storage-plus = { workspace = true }
cosmwasm-std = { workspace = true }
cosmwasm-schema = { workspace = true }
cw-address-like = { workspace = true }
cw-ownable = { workspace = true }
cw-paginate-storage = { workspace = true }
cw-tokenfactory-issuer = { workspace = true, features = ["library"] }
dao-interface = { workspace = true }
getrandom = { workspace = true, features = ["js"] }
thiserror = { workspace = true }
cw-curves = { workspace = true }

[dev-dependencies]
speculoos = { workspace = true }
anyhow = { workspace = true }
cw-multi-test = { workspace = true }
dao-testing = { workspace = true, features = ["test-tube"] }
osmosis-std = { workspace = true }
osmosis-test-tube = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
cw-tokenfactory-issuer = { workspace = true }
dao-voting-token-staked = { workspace = true }
dao-proposal-single = { workspace = true }
dao-voting = { workspace = true }
15 changes: 15 additions & 0 deletions contracts/external/cw-abc/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CW20-Bonding: Bonding Curve to release CW20 token
Copyright 2020-21 Ethan Frey <ethanfrey@users.noreply.github.com>
Copyright 2021-22 Confio GmbH

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
150 changes: 150 additions & 0 deletions contracts/external/cw-abc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# cw-abc

Implements an [Augmented Bonding Curve](https://medium.com/commonsstack/deep-dive-augmented-bonding-curves-b5ca4fad4436).

Forked from and heavily inspired by the work on [cw20-bonding](https://github.com/cosmwasm/cw-tokens/tree/main/contracts/cw20-bonding). This contract uses native and token factory tokens instead.

NOTE: this contract is NOT AUDITED and experimental. NOT RECOMMENDED FOR PRODUCTION USE. Use at your own risk.

## What are Augmented Bonding Curves?
Before we get to the *Augmented* part, we must first describe bonding curves themselves.

### Token Bonding Curves

"A token bonding curve (TBC) is a mathematical curve that defines a relationship between price and token supply." ~[Aavegotchi Wiki](https://wiki.aavegotchi.com/en/curve)

Each bonding curve has a pricing function, also known as the price curve (or `curve_fn` in our implementation). The `curve_fn` is used to determine the price of the asset.

With bonding curves, we will always know what the price of an asset will be based on supply! More on benefits later.

This contract implements two methods:
- `Buy {}` is called with sending along some reserve currency (such as $USDC, or whatever the bonding curve is backed by). The reserve currency is stored by the bonding curve contract, and new tokens are minted and sent to the user.
- `Sell {}` is called along with sending some supply currency (the token minted by the bonding curve). The supply tokens are burned, and reserve currency is returned.

It is possible to use this contact as a basic bonding curve, without any of the augmented features.

#### Math

Given a price curve `f(x)` = price of the `x`th token, we want to figure out how to buy into and sell from the bonding curve. In fact we can look at the total supply issued. let `F(x)` be the integral of `f(x)`. We have issued `x` tokens for `F(x)` sent to the contract. Or, in reverse, if we send `x` tokens to the contract, it will mint `F^-1(x)` tokens.

From this we can create some formulas. Assume we currently have issued `S` tokens in exchange for `N = F(S)` input tokens. If someone sends us `x` tokens, how much will we issue?

`F^-1(N+x) - F^-1(N)` = `F^-1(N+x) - S`

And if we sell `x` tokens, how much we will get out:

`F(S) - F(S-x)` = `N - F(S-x)`

Just one calculation each side. To be safe, make sure to round down and always check against `F(S)` when using `F^-1(S)` to estimate how much should be issued. This will also safely give us how many tokens to return.

There is built in support for safely [raising i128 to an integer power](https://doc.rust-lang.org/std/primitive.i128.html#method.checked_pow). There is also a crate to [provide nth-root of for all integers](https://docs.rs/num-integer/0.1.43/num_integer/trait.Roots.html). With these two, we can handle most math except for logs/exponents.

Compare this to [writing it all in solidity](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7b7ff729b82ea73ea168e495d9c94cb901ae95ce/contracts/math/Power.sol)

Examples:

Price Constant: `f(x) = k` and `F(x) = kx` and `F^-1(x) = x/k`

Price Linear: `f(x) = kx` and `F(x) = kx^2/2` and `F^-1(x) = (2x/k)^(0.5)`

Price Square Root: `f(x) = x^0.5` and `F(x) = x^1.5/1.5` and `F^-1(x) = (1.5*x)^(2/3)`

[You can read more about bonding curve math here](https://yos.io/2018/11/10/bonding-curves/).

#### Benefits

There are a number of benefits to bonding curves:
- There is enough liquidity to back the entire supply without having to list tokens on DEXs
- Easier to wind down projects (there is no going to zero)
- Transparent pricing: looking at the curve will tell you a lot about what kind of project it is.

### Augmented Bonding Curves

Augmented Bonding Curves are nothing new, some articles that inspired this implementation:
- https://medium.com/commonsstack/deep-dive-augmented-bonding-curves-b5ca4fad4436
- https://tokeneconomy.co/token-bonding-curves-in-practice-3eb904720cb8

At a high level, augmented bonding curves extend bonding curves with new functionality:
- Entry and exit fees
- Different phases representing the life cycles of projects

## Features

Example Instantiation message:

``` json
{
"fees_recipient": "address that receives fees",
"token_issuer_code_id": 0,
"supply": {
"subdenom": "utokenname",
"metadata": {
"name": "tokenname",
"description": "Token description.",
"symbol": "TOKEN",
"display": "Token",
},
"decimals": 6,
"max_supply": "100000000000000"
},
"reserve": {
"denom": "ujuno",
"decimals": 6,
},
"curve_type": {
"linear": {
"slope": "2",
"scale": 1
}
},
"phase_config": {
"hatch": {
"contribution_limits": {
"min": "10000000",
"max": "100000000000"
},
"initial_raise": {
"min": "10000000",
"max": "100000000000"
},
"entry_fee": "0.25"
},
"open": {
"exit_fee": "0.01",
"entry_fee": "0.01"
},
"closed": {}
},
"hatcher_allowlist": [
{
"addr": "dao_address",
"config": {
"config_type": { "dao": { "priority": 1 } },
"contribution_limits_override": {
"min": "100000000",
"max": "99999999999999"
}
}
},
{
"addr": "address",
"config": {
"config_type": { "address": {} }
}
}
],
}
```

- `fees_recipient`: the address that will receive fees (usually a DAO).
- `token_issuer_code_id`: the CosmWasm code ID for a `cw-tokenfactory_issuer` contract.
- `supply`: info about the token that will be minted by the curve. This is the token that is created by the bonding curve.
- `reserve`: this is the token that is used to mint the supply token.
- `curve_type`: information about the pricing curve.
- `phase_config`: configuration for the different phase of the augmented bonding curve.
- `hatcher_allowlist`: the list of address allowed to participate in a hatch.

## Future Work
- [ ] Optionally vest tokens during the hatch phase
- [ ] Implement an expanded set of pricing curves to choose from

11 changes: 11 additions & 0 deletions contracts/external/cw-abc/examples/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use cosmwasm_schema::write_api;

use cw_abc::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};

fn main() {
write_api! {
instantiate: InstantiateMsg,
query: QueryMsg,
execute: ExecuteMsg,
}
}
Loading

0 comments on commit 848cecd

Please sign in to comment.