Skip to content

Commit dd08f57

Browse files
committed
Initial commit
0 parents  commit dd08f57

File tree

5 files changed

+602
-0
lines changed

5 files changed

+602
-0
lines changed

.gitignore

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
node_modules/
2+
client/build/*
3+
.DS_Store
4+
.env
5+
.env.local
6+
.env.development.local
7+
.env.test.local
8+
.env.production.local
9+
npm-debug.log*
10+
yarn-debug.log*
11+
yarn-error.log*

contracts/index.md

+293
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
# Balancer Protocol Specification
2+
3+
## Note about releases
4+
5+
The **🍂Bronze Release🍂** is the first of 3 planned releases of the Balancer Protocol. Bronze emphasizes code clarity for audit and verification, and does not go to great lengths to optimize for gas.
6+
7+
The **❄️Silver Release❄️** will bring many gas optimizations and architecture changes that will reduce transaction overhead and enable more flexibile usage patterns.
8+
9+
The **☀️Golden Release☀️** will introduce a few final features that will tie the whole system together.
10+
11+
Unless noted otherwise, this document describes the contract architecture for the **🍂Bronze Release🍂**.
12+
We have attempted to make note of the functionality that will change for future releases,
13+
but it is possible for *any aspect* of the design to change in both very large and also very subtle ways.
14+
15+
Please take care to when interacting with a Balancer pool to ensure you know which release it is associated with.
16+
Objects in the Balancer system provide `getColor() returns (bytes32)`, which returns a left-padded ASCII representation of the all-caps color word, ie, `bytes32("BRONZE")`.
17+
18+
## Contents
19+
* [Note about releases](#note-about-releases)
20+
* [Contents](#contents)
21+
* [Terminology](#terminology)
22+
* * [Access Control](#access-control)
23+
* * [Pool Status](#pool-status)
24+
* [Events](#events)
25+
* [API Index](#api-index)
26+
* [Functions](#functions)
27+
28+
## Terminology
29+
30+
* Pool: A `BPool` contract object
31+
* Balance: The total token balance of a pool. Does not refer to any user balance.
32+
* Denorm: Denormalized weight. Weights on a BPool are configured and stored in their **denormalized** form.
33+
* Controller: The pool's "owner"; an address that can call `CONTROL` capabilities.
34+
* Factory: The official BPool factory. Pools deployed from this factory appear in tools and explorers for Balancer.
35+
36+
### Access Control
37+
38+
The access control state of a pool can be modeled with a rudimentary role-based access control system.
39+
40+
##### Conceptual Roles:
41+
42+
* factory
43+
* controller
44+
* public
45+
46+
##### Conceptual Capabilities:
47+
48+
* `SWAP` (`swap_*`, `joinswap_*`, `exitswap_*`)
49+
* `JOIN` (`joinPool`, `joinswap_*`)
50+
* `EXIT` (`exitPool`, `exitswap_*`) <-- always public
51+
* `CONTROL` (`bind`, `unbind`, `rebind`, `setFees`, `finalize`)
52+
* `FACTORY` (`collect`)
53+
54+
Notice that e.g. `joinswap` requires both `JOIN` and `SWAP`.
55+
56+
##### Token-specific state:
57+
58+
* A token can be "bound" or not -- if it's bound, it is funded, has a valid denorm, and can be interacted with, assuming your address has a role with the right capabilities
59+
60+
With this mental model in mind, you can proceed to the status functions for Bronze pools.
61+
62+
### Pool Status
63+
64+
* `isPublicSwap()`
65+
* `isPublicJoin()`
66+
* `isPublicExit()` (always true in Bronze release)
67+
* `isBound(address T)`
68+
* `isFinalized()`
69+
* `getController() returns (address C)`
70+
71+
72+
| capability | when finalized is FALSE | when finalized is TRUE |
73+
|-|-|-|
74+
| `SWAP` | controller OR public | public |
75+
| `JOIN` | controller OR public | public |
76+
| `EXIT` | public | public |
77+
| `CONTROL` | controller only | none |
78+
| `FACTORY` | factory only | factory only |
79+
|-|-|-|
80+
81+
In other words, `setPublicSwap` and `setPublicJoin` can be used to configured `SWAP` and `JOIN` functions.
82+
`setPublicExit(false)` will throw `ERR_EXIT_ALWAYS_PUBLIC`.
83+
`finalize` is used to make a public pool with immutable parameters.
84+
85+
86+
### Events
87+
88+
89+
`LOG_CALL` is an anonymous event which uses the function signature as the event signature.
90+
It is fired by all stateful functions.
91+
92+
`LOG_SWAP` is fired (along with `LOG_CALL`) for all [swap variants]().
93+
94+
```
95+
event LOG_SWAP( address indexed caller
96+
, address indexed tokenIn
97+
, address indexed tokenOut
98+
, uint256 amountIn
99+
, uint256 amountOut
100+
);
101+
102+
event LOG_CALL( bytes4 indexed sig
103+
, address indexed caller
104+
, bytes data
105+
) anonymous; // LOG_CALL is `anonymous` to replace default signature
106+
```
107+
108+
109+
110+
### API Index
111+
112+
| Function |
113+
|-
114+
|[`swap_ExactAmountIn(TI,AI,TO,MO,MP)->(AO,NP)`](#swap_exactamountin)
115+
|[`swap_ExactAmountOut(TI,MI,TO,AO,MP)->(AI,NP)`](#swap_exactamountout) |
116+
|[`swap_ExactMarginalPrice(TI,MI,TO,MO,MP)->(AI,AO)`](#swap_exactmarginalprice) |
117+
|[`joinPool(PO)`](#joinpool) |
118+
|[`exitPool(PO)`](#exitpool) |
119+
|[`joinswap_ExternAmountIn(TI, AI)->(PO)`](#joinswap_externamountin) |
120+
|[`exitswap_ExternAmountOut(TO, AO)->(PI)`](#joinswap_externamountout) |
121+
|[`joinswap_PoolAmountOut(PO,TI)->(AI)`](#joinswap_poolamountout) |
122+
|[`exitswap_PoolAmountIn(PI,TO)->(AO)`](#joinswap_poolamountin) |
123+
|-
124+
|[`getSpotPrice(TI,TO)->(P)`](#getspotprice)
125+
|[`getSpotRate(TI,TO)->(R)`](#getspotprice)
126+
|[`getSpotPriceSansFee(TI,TO)->(P)`](#getspotprice)
127+
|[`getSpotRateSansFee(TI,TO)->(R)`](#getspotprice)
128+
|[`getFees()->(swapFee,exitFee)`](#getfees) |
129+
|-
130+
|[`bind(T, balance, denorm)`](#bind) |
131+
|[`rebind(T, balance, denorm)`](#rebind) |
132+
|[`unbind(T)`](#unbind) |
133+
|[`setPublicSwap(bool)`](#setPublicSwap) |
134+
|[`setPublicJoin(bool)`](#setPublicJoin) |
135+
|[`setPublicExit(bool)`](#setPublicExit) |
136+
|[`setFees(swapFee, exitFee)`](#setfees) |
137+
|[`collect()`](#collect) |
138+
|[`finalize()`](#finalize) |
139+
|[`gulp(T)`](#gulp) |
140+
|-
141+
|[`isFinalized()->bool`](#isfinalized) |
142+
|[`isBound()->bool`](#isbound) |
143+
|[`getBalance()->bool`](#getbalance) |
144+
|[`getNormalizedWeight(T)->(NW)`](#getnormalizedweight) |
145+
|[`getDenormalizedWeight(T)->(DW)`](#getdenormalizedweight) |
146+
|[`getTotalDenormalizedWeight()->(TDW)`](#gettotaldenormalizedweight) |
147+
|[`getNumTokens()->(N)`](#getnumtokens) |
148+
|[`getCurrentTokens()->[Ts]`](#getnumtokens) |
149+
|[`getFinalTokens->[Ts]`](#getnumtokens) |
150+
|[`getController()->address`](#getcontroller) |
151+
|-
152+
153+
154+
## Functions
155+
156+
## `swap_ExactAmountIn`
157+
```
158+
swap_ExactAmountIn( address tokenIn, uint amountIn
159+
, address tokenOut, uint minOut
160+
, uint maxPrice)
161+
returns (uint amountOut, uint newPrice);
162+
```
163+
164+
Trades an exact `amountIn` of `tokenIn` taken from the caller by the pool, in exchange for at least `minOut` of `tokenOut` given to the caller from the pool, with a maximum marginal price of `maxPrice`.
165+
166+
Returns `(amountOut, newPrice)`, where `amountOut` is the amount of token that came out of the pool, and MP is the new marginal spot price, ie, the result of `getSpotPrice` after the call. (These values are what are limited by the arguments; you are guaranteed `amountOut >= minOut` and `newPrice <= maxPrice`).
167+
168+
## `swap_ExactAmountOut`
169+
```
170+
swap_ExactAmountOut( address tokenIn, uint maxIn
171+
, address tokenOut, uint amountOut
172+
, uint maxPrice)
173+
returns (uint amountIn, uint newPrice)
174+
```
175+
176+
## `swap_ExactMarginalPrice`
177+
```
178+
swap_ExactMarginalPrice( address tokenIn, uint maxIn
179+
, address tokenOut, uint maxOut
180+
, uint newPrice)
181+
return (uint amountIn, uint amountOut)`
182+
```
183+
184+
## `joinPool`
185+
`joinPool(uint shares_out)`
186+
187+
Join the pool, getting `shares_out` pool tokens. This will pull some of each of the currently trading tokens in the pool, meaning you must have called `approve` for each token for this pool.
188+
189+
## `exitPool`
190+
`exitPool(uint shares_in)`
191+
192+
Exit the pool, paying `shares_in` pool tokens and getting some of each of the currently trading tokens in return.
193+
194+
## `joinswap_ExternAmountIn`
195+
`joinswap_ExternAmountIn(address T, uint tAi) -> (uint pAo)`
196+
197+
Pay `tAi` of token `T` to join the pool, getting `pAo` of the pool shares.
198+
199+
200+
## `exitswap_ExternAmountOut`
201+
`exitswap_ExternAmountOut(address T, uint tAo) -> (uint pAi)`
202+
203+
Specify `tAo` of token `T` that you want to get out of the pool. This costs `pAi` pool shares (these went into the pool).
204+
205+
## `joinswap_PoolAmountOut`
206+
`joinswap_PoolAmountOut(uint pAo, address T) -> (uint tAi)`
207+
208+
Specify `pAo` pool shares that you want to get, and a token `T` to pay with. This costs `tAi` tokens (these went into the pool).
209+
210+
## `exitswap_PoolAmountIn`
211+
`exitswap_PoolAmountIn(uint pAi, address T) -> (uint tAo)`
212+
213+
Pay `pAi` pool shares into the pool, getting `tAo` of the given token `T` out of the pool.
214+
215+
## `isFinalized`
216+
`isFinalized() -> (bool)`
217+
218+
The `finalized` state lets users know that the weights, balances, and fees of this pool are immutable.
219+
In the `finalized` state, `SWAP`, `JOIN`, and `EXIT` are public. [`CONTROL` capabilities](#access-control) are disabled.
220+
221+
## `isBound`
222+
`isBound(address T) -> (bool)`
223+
224+
A bound token has a valid balance and weight. A token cannot be bound without valid parameters which will enable e.g. `getSpotPrice` in terms of other tokens. However, disabling `isSwapPublic` and `isJoinPublic` will disable any interaction with this token in practice (assuming there are no existing tokens in the pool, which can always `exitPool`). This is one of many factors that could lead to `getSpotPrice` being an unreliable price sensor.
225+
226+
## `getNumTokens`
227+
`getNumTokens() -> (uint)`
228+
229+
How many tokens are bound to this pool.
230+
231+
## `getController`
232+
`getController() -> (address)`
233+
234+
Get the "controller" address, which can call `CONTROL` functions like `rebind`, `setFees`, or `finalize`.
235+
236+
237+
238+
## `bind`
239+
`bind(address T, uint B, uint W)`
240+
241+
Binds the token with address `T`. Tokens will be pushed/pulled from caller to adjust match new balance.
242+
Token must not already be bound.
243+
`B` must be a valid balance and `W` must be a valid *denormalized* weight.
244+
245+
Possible errors:
246+
* `ERR_NOT_CONTROLLER` -- caller is not the controller
247+
* `ERR_IS_BOUND` -- `T` is already bound
248+
* `ERR_IS_FINALIZED` -- `isFinalized()` is true
249+
* `ERR_ERC20_FALSE` -- `ERC20` token returned false
250+
* unspecified error thrown by token
251+
252+
### `rebind`
253+
`rebind(address T, uint B, uint W)`
254+
255+
Changes the parameters of an already-bound token. Performs the same validation on the parameters.
256+
257+
### `unbind`
258+
`rebind(address T)`
259+
260+
Unbinds a token, clearing all of its parameters and pushing the entire balance to caller.
261+
262+
### `setPublicSwap`
263+
`setPublicSwap(bool isPublic)`
264+
265+
Makes `isPublicSwap` return `isPublic`
266+
Requires caller to be controller and pool not to be finalized.
267+
Finalized pools always have public swap.
268+
269+
### `setPublicJoin`
270+
`setPublicJoin(bool p)`
271+
272+
Makes `isPublicJoin` return `isPublic`.
273+
Requires caller to be controller and pool not to be finalized.
274+
Finalized pools always have public join.
275+
276+
### `setPublicExit`
277+
278+
Throws `ERR_EXIT_ALWAYS_PUBLIC` if called with `p == false`.
279+
`EXIT` functions are always public on Bronze pools.
280+
281+
### `finalize`
282+
`finalize()`
283+
284+
This makes the pool **finalized**.
285+
This is a one-way transition.
286+
`bind`, `rebind`, `unbind`, `setFees` and `setPublic<Swap/Join/Exit>` will all throw `ERR_IS_FINALIZED` after pool is finalized.
287+
This also switches `isSwapPublic` and `isJoinPublic` to true. `isExitPublic` is always true.
288+
289+
### `setFees`
290+
`setFees(uint swapFee, uint exitFee)`
291+
292+
Caller must be controller.
293+
Pool must NOT be finalized.

index.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<p align=center>
2+
<img width="128px" src="https://balancer-labs.github.io/pebbles/images/pebbles-pad.256w.png" alt="balancer pebbles logo"/>
3+
</p>
4+
5+
<h1 align=center><code>balancer</code></h1>
6+
7+
**Balancer** is an automated **portfolio manager**, **liquidity provider**, and **price sensor**.
8+
9+
Balancer turns the concept of an index fund on its head: instead of a paying fees
10+
to portfolio managers to rebalance your portfolio, you collect fees from traders, who rebalance
11+
your portfolio by following arbitrage opportunities.
12+
13+
Balancer is based on an N-dimensional invariant surface which is a generalization of the constant product formula described by Vitalik Buterin and proven viable by the popular Uniswap dapp.

0 commit comments

Comments
 (0)