Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Commit

Permalink
Deposit quote token WIP. Add brownie scripts + README
Browse files Browse the repository at this point in the history
  • Loading branch information
grandizzy committed Feb 4, 2022
1 parent eb4ae5d commit 5019fa0
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 71 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ node_modules
.env
.env.prod
.vscode/*.log
scripts/
brownie*
__pycache__/
98 changes: 38 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,23 @@
# foundry-starter • [![tests](https://github.com/abigger87/foundry-starter/actions/workflows/tests.yml/badge.svg)](https://github.com/abigger87/foundry-starter/actions/workflows/tests.yml) [![lints](https://github.com/abigger87/foundry-starter/actions/workflows/lints.yml/badge.svg)](https://github.com/abigger87/foundry-starter/actions/workflows/lints.yml) ![GitHub](https://img.shields.io/github/license/abigger87/foundry-starter) ![GitHub package.json version](https://img.shields.io/github/package-json/v/abigger87/foundry-starter)
# ajna contracts

Backwards Compatible Template for Foundry and DappTools Projects

## Blueprint

```ml
lib
├─ ds-test — https://github.com/dapphub/ds-test
├─ forge-std — https://github.com/brockelmore/forge-std
├─ solmate — https://github.com/Rari-Capital/solmate
├─ clones-with-immutable-args — https://github.com/wighawag/clones-with-immutable-args
src
├─ tests
│ └─ Greeter.t — "Greeter Tests"
└─ Greeter — "A Minimal Greeter Contract"
```
Ajna contracts

## Development

[foundry-starter](https://github.com/abigger87/foundry-starter) is intended to be minimal while also providing backwards compatibility. Thus, both [DappTools](https://dapp.tools/) and [Foundry](https://github.com/gaskonst/foundry) are supported. Installation instructions for both are included below.
#### Install DappTools

Install DappTools using their [installation guide](https://github.com/dapphub/dapptools#installation).

#### First time with Forge/Foundry?

See the official Foundry installation [instructions](https://github.com/gakonst/foundry/blob/master/README.md#installation).

Don't have [rust](https://www.rust-lang.org/tools/install) installed?
Run
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

Then, install the [foundry](https://github.com/gakonst/foundry) toolchain installer (`foundryup`) with:
Install Foundry [instructions](https://github.com/gakonst/foundry/blob/master/README.md#installation) then, install the [foundry](https://github.com/gakonst/foundry) toolchain installer (`foundryup`) with:
```bash
curl -L https://foundry.paradigm.xyz | bash
```

Now that you've installed the `foundryup` binary,
anytime you need to get the latest `forge` or `cast` binaries,
you can run `foundryup`.

So, simply execute:
To get the latest `forge` or `cast` binaries, tun
```bash
foundryup
```

🎉 Foundry is installed! 🎉

#### Setup
#### Project Setup

```bash
make
# OR #
make setup
make all
```

#### Build
Expand All @@ -69,24 +32,39 @@ make build
make test
```

#### Configure Foundry
## Brownie integration
- Install Brownie [instructions](https://eth-brownie.readthedocs.io/en/stable/install.html)
- Make a copy of .env.example and name it .env. Add the values for ETHERSCAN_TOKEN and WEB3_INFURA_PROJECT_ID
- Run `brownie console`

Using [foundry.toml](./foundry.toml), Foundry is easily configurable.
### ERC20 pool test

## License
- Deploy ERC20 Perp pool for DAI/MKR, swap ETH to DAI for `alice` and ETH to MKR for `bob` and check balances:

[AGPL-3.0-only](https://github.com/abigger87/foundry-starter/blob/master/LICENSE)

# Acknowledgements

- [foundry](https://github.com/gakonst/foundry)
- [solmate](https://github.com/Rari-Capital/solmate)
- [forge-std](https://github.com/brockelmore/forge-std)
- [clones-with-immutable-args](https://github.com/wighawag/clones-with-immutable-args).
- [foundry-toolchain](https://github.com/onbjerg/foundry-toolchain) by [onbjerg](https://github.com/onbjerg).
- [forge-template](https://github.com/FrankieIsLost/forge-template) by [FrankieIsLost](https://github.com/FrankieIsLost).
- [Georgios Konstantopoulos](https://github.com/gakonst) for [forge-template](https://github.com/gakonst/forge-template) resource.

## Disclaimer
```bash
>>> deployer, alice, bob, dai, mkr, daiPool = run('erc20setup')
>>> dai.balanceOf(alice)
157571811476835406723764
```
- Deposit and withdraw collateral from pool:

_These smart contracts are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions, loss of transmitted information or loss of funds. The creators are not liable for any of the foregoing. Users should proceed with caution and use at their own risk._
```bash
>>> daiPool.deposit(1111111111, {"from": alice})
>>> dai.balanceOf(daiPool)
1111111111
>>> daiPool.withdraw(1111111111, {"from": alice})
0
```
- Deposit quote token into the pool:
```
>>> daiPool.depositQuoteToken(125454, 307000000000000000000, {"from": alice})
>>> daiPool.quoteBalances(alice)
125454
```
- Query buckets
```
>>> daiPool.indexToPrice(3)
307000000000000000000
>>> daiPool.priceToIndex(307000000000000000000)
3
```
23 changes: 23 additions & 0 deletions brownie-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
project_structure:
build: out
contracts: src
tests: src/tests

# use Ganache's forked mainnet mode as the default network
# NOTE: You don't *have* to do this, but it is often helpful for testing
networks:
default: mainnet-fork

# automatically fetch contract sources from Etherscan
autofetch_sources: True

# path remapping to support imports from GitHub/NPM
compiler:
solc:
version: 0.8.10
remappings:
- "@ds-test=lib/ds-test/src/"
- "@ds-math=lib/ds-math/src/"
- "@openzeppelin/contracts=lib/openzeppelin-contracts/contracts"
- "@std=lib/forge-std/src/"

3 changes: 3 additions & 0 deletions brownie_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from dotenv import load_dotenv

load_dotenv()
16 changes: 16 additions & 0 deletions scripts/erc20setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from brownie import *
import itertools

def main():
deployer = accounts[0];
alice = accounts[1];
bob = accounts[2];
uniswap =Contract("0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667");
uniswap.ethToTokenSwapInput(1, 9999999999, {"from": alice, "value": "100 ether"});
uniswap.ethToTokenSwapInput(1, 9999999999, {"from": bob, "value": "55 ether"});
dai = Contract('0x6b175474e89094c44da98b954eedeac495271d0f');
mkr = Contract('0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2')
daiPool = ERC20PerpPool.deploy(dai, mkr, {"from" : deployer});
dai.approve(daiPool, 111111111111, {"from" : alice});
dai.approve(daiPool, 111111111111, {"from" : bob});
return deployer, alice, bob, dai, mkr, daiPool;
63 changes: 54 additions & 9 deletions src/ERC20PerpPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ interface IPerpPool {
function depositCollateral(uint256 _amount) external;
function withdrawCollateral(uint256 _amount) external;
function depositQuoteToken(uint256 _amount, uint256 _price) external;
function withdrawQuoteToken(uint256 _amount) external;
function borrow(uint256 _amount) external;
function actualUtilization() external view returns (uint256);
function targetUtilization() external view returns (uint256);
Expand All @@ -29,11 +30,6 @@ contract ERC20PerpPool is IPerpPool {
uint256 inflatorSnapshot;
}

enum PricePointer {
HighestUtilizable,
LowestUtilized
}

// --- Math ---
uint private constant WAD = 10 ** 18;

Expand All @@ -52,19 +48,36 @@ contract ERC20PerpPool is IPerpPool {
function wdiv(uint x, uint y) internal pure returns (uint z) {
z = add(mul(x, WAD), y / 2) / y;
}
function max(uint x, uint y) internal pure returns (uint z) {
z = x >= y ? x : y;
}

event CollateralDeposited(address depositor, uint256 amount, uint256 collateralAccumulator);
event CollateralWithdrawn(address depositor, uint256 amount, uint256 collateralAccumulator);

uint public constant HIGHEST_UTILIZABLE_PRICE = 1;
uint public constant LOWEST_UTILIZABLE_PRICE = 2;

uint public constant SECONDS_PER_YEAR = 3600 * 24 * 365;
uint public constant MAX_PRICE = 1000 * WAD;
uint public constant MIN_PRICE = 10 * WAD;
uint public constant PRICE_COUNT = 10;
uint public constant PRICE_STEP = (MAX_PRICE - MIN_PRICE) / PRICE_COUNT;

IERC20 public immutable collateralToken;
IERC20 public immutable quoteToken;

mapping(address => uint256) public collateralBalances;
uint256 public collateralAccumulator;

IERC20 public immutable quoteToken;
mapping(address => uint256) public quoteBalances;
uint256 public quoteTokenAccumulator;

mapping(uint256 => uint256) public priceToIndex;
mapping(uint256 => uint256) public indexToPrice;
mapping(uint256 => uint256) public pointerToIndex;

mapping(uint256 => PriceBucket) public buckets;

uint256 public collateralAccumulator;
uint256 public borrowerInflator;
uint256 public lastBorrowerInflatorUpdate;
uint256 public previousRate;
Expand All @@ -80,6 +93,12 @@ contract ERC20PerpPool is IPerpPool {

previousRate = wdiv(5, 100);
previousRateUpdate = block.timestamp;

for (uint256 i = 0; i < PRICE_COUNT; i++) {
uint256 price = MIN_PRICE + (PRICE_STEP * i);
priceToIndex[price] = i;
indexToPrice[i] = price;
}
}

modifier updateBorrowerInflator(address account) {
Expand All @@ -102,7 +121,7 @@ contract ERC20PerpPool is IPerpPool {
}

function withdrawCollateral(uint256 _amount) external updateBorrowerInflator(msg.sender) {
require(_amount <= collateralBalances[msg.sender], "Not enough collateral");
require(_amount <= collateralBalances[msg.sender], "Not enough collateral to withdraw");

collateralBalances[msg.sender] -= _amount;
collateralAccumulator -= _amount;
Expand All @@ -112,6 +131,32 @@ contract ERC20PerpPool is IPerpPool {
}

function depositQuoteToken(uint256 _amount, uint256 _price) external {

uint256 depositBucketId = priceToIndex[_price];
require(depositBucketId > 0, "Price bucket not found");

PriceBucket storage bucket = buckets[depositBucketId];
bucket.lpTokenBalance[msg.sender] += _amount;
bucket.onDeposit += _amount;

quoteBalances[msg.sender] += _amount;
quoteTokenAccumulator += _amount;

uint256 lupIndex = pointerToIndex[LOWEST_UTILIZABLE_PRICE];
if (depositBucketId > lupIndex) {
for (uint256 i = lupIndex; i < depositBucketId; i++) {
// TODO reallocate debt here!
}
}

if (bucket.onDeposit == 0) {
return;
}
pointerToIndex[HIGHEST_UTILIZABLE_PRICE] = max(pointerToIndex[HIGHEST_UTILIZABLE_PRICE], depositBucketId);

}

function withdrawQuoteToken(uint256 _amount) external {
}

function borrow(uint256 _amount) external {
Expand Down
1 change: 1 addition & 0 deletions src/test/ERC20PerpPool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,5 @@ contract ERC20PerpPoolTest is DSTest, stdCheats {
// borrower inflator updated with new deposit tx
assertGt(pool.borrowerInflator(), 1 ether);
}

}

0 comments on commit 5019fa0

Please sign in to comment.