Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: version 3.0.2 #188

Merged
merged 16 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .github/workflows/foundry.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Foundry tests

on:
push:
branches:
- master
pull_request:

concurrency:
group: ${{github.workflow}}-${{github.ref}}
cancel-in-progress: true

jobs:
unit:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
architecture:
- "x64"
python-version:
- "3.10"
node_version:
- 16

steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.architecture }}

- name: Install Ape
uses: ApeWorX/github-action@v2.0
with:
python-version: '3.10'

- name: install vyper
run: pip install git+https://github.com/vyperlang/vyper

- name: Compile contracts
# Compile Ape contracts to get dependencies
run: ape compile --force --size

- name: Install Vyper
run: pip install vyper==0.3.7

- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node_version }}

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Foundry tests
run: forge test -vvv
2 changes: 1 addition & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ jobs:
run: pip install -r requirements.txt

- name: Run black
run: black --check --include "(tests|scripts)" .
run: black --check .
2 changes: 0 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ jobs:
- uses: ApeWorX/github-action@v2.0
with:
python-version: '3.10'
ape-version-pin: "==0.6.3"
ape-plugins-list: 'solidity==0.6.0 vyper==0.6.1 hardhat==0.6.0'

- name: install vyper
run: pip install git+https://github.com/vyperlang/vyper
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
pyenv.cfg
vyper_git_commithash.txt
bin/
lib/
cache/
out/
share/
build/
include/
Expand All @@ -17,3 +18,6 @@ venv/
.vscode
yarn.lock
env
cache/
out/
.gas-snapshot
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/erc4626-tests"]
path = lib/erc4626-tests
url = https://github.com/a16z/erc4626-tests
2 changes: 1 addition & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
"not-rely-on-time": "off",
"private-vars-leading-underscore": "warn",
"reason-string": ["warn", { "maxLength": 64 }],
"yearn/underscore-function-args": "error"
"yearn/underscore-function-args": "off"
}
}
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ This repository runs on [ApeWorx](https://www.apeworx.io/). A python based devel

You will need:
- Python 3.8 or later
- Vyper 0.3.7
- [Vyper 0.3.7](https://docs.vyperlang.org/en/stable/installing-vyper.html)
- [Foundry](https://book.getfoundry.sh/getting-started/installation)
- Linux or macOS
- Windows: Install Windows Subsystem Linux (WSL) with Python 3.8 or later
- [Hardhat](https://hardhat.org/) installed globally
Expand All @@ -24,7 +25,7 @@ You will need:
Fork the repository and clone onto your local device

```
git clone https://github.com/user/yearn-vaults-v3
git clone --recursive https://github.com/user/yearn-vaults-v3
cd yearn-vaults-v3
```

Expand Down Expand Up @@ -60,6 +61,24 @@ and test smart contracts with:
ape test
```

To run the Foundry tests

NOTE: You will need to first compile with Ape before running foundry tests.
```
forge test
```

## Deployment

Deployments of the Vault Factory are done using create2 to be at a deterministic address on any EVM chain.

Check the [docs](https://docs.yearn.fi/developers/v3/overview) for the most updated deployment address.

Deployments on new chains can be done permissionlessly by anyone using the included script.
```
ape run scripts/deploy.py --network YOUR_RPC_URL
```

### To make a contribution please follow the [guidelines](https://github.com/yearn/yearn-vaults-v3/bloc/master/CONTRIBUTING.md)

See the ApeWorx [documentation](https://docs.apeworx.io/ape/stable/) and [github](https://github.com/ApeWorX/ape) for more information.
Expand Down
6 changes: 3 additions & 3 deletions TECH_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ This responsibility is taken by callers with DEBT_MANAGER role

This role can increase or decrease strategies specific debt.

The vault sends and receives funds to/from strategies. The function updateDebt(strategy, target_debt) will set the current_debt of the strategy to target_debt (if possible)
The vault sends and receives funds to/from strategies. The function update_debt(strategy, target_debt, max_loss) (max_loss defaults to 100%) will set the current_debt of the strategy to target_debt (if possible)

If the strategy currently has less debt than the target_debt, the vault will send funds to it.

Expand Down Expand Up @@ -224,15 +224,15 @@ Strategies are completely independent smart contracts that can be implemented fo

In any case, to be compatible with the vault, they need to implement the following functions, which are a subset of ERC4626 vaults:
- asset(): view returning underlying asset
- totalAssets(): view returning current amount of assets. It can include rewards valued in `asset` ¡
- maxDeposit(address): view returning the amount max that the strategy can take safely
- deposit(assets, receiver): deposits `assets` amount of tokens into the strategy. it can be restricted to vault only or be open
- maxRedeem(owner): return the max amount of shares that `owner` can redeem.
- redeem(shares, receiver, owner): redeems `shares` of the strategy for the underlying asset.
- balanceOf(address): return the number of shares of the strategy that the address has
- convertToAssets(shares): Converts `shares` into the corresponding amount of asset.
- convertToShares(assets): Converts `assets` into the corresponding amount of shares.
- previewWithdraw(assets): Converts `assets` into the corresponding amount of shares rounding up.
- maxRedeem(owner): return the max amount of shares that `owner` can redeem.


This means that the vault can deposit into any ERC4626 vault but also that a non-compliant strategy can be implemented provided that these functions have been implemented (even in a non ERC4626 compliant way).

Expand Down
9 changes: 3 additions & 6 deletions ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@ name: yearn-v3

plugins:
- name: solidity
version: 0.6.0
- name: vyper
version: 0.6.1
- name: hardhat
version: 0.6.0

default_ecosystem: ethereum
dependencies:
- name: openzeppelin
github: OpenZeppelin/openzeppelin-contracts
version: 4.7.3
ref: 4.9.5
- name: tokenized-strategy
github: yearn/tokenized-strategy
branch: master
ref: master
contracts_folder: src

solidity:
import_remapping:
- "@openzeppelin/contracts=openzeppelin/v4.7.3"
- "@openzeppelin/contracts=openzeppelin/v4.9.5"
- "@tokenized-strategy=tokenized-strategy/master"

ethereum:
Expand Down
62 changes: 36 additions & 26 deletions contracts/VaultFactory.vy
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
This vault Factory can be used by anyone wishing to deploy their own
ERC4626 compliant Yearn V3 Vault of the same API version.

The factory uses the Blueprint (ERC-5202) standard to handle the
deployment of any new vaults off of the immutable address stored
at `VAULT_BLUEPRINT`. This allows the vaults to be deployed and
initialized fully on-chain with their init byte code, thus not
requiring any delegatecall patterns or post deployment initialization.
The factory clones new vaults from its specific `VAULT_ORIGINAL`
immutable address set on creation of the factory.

The deployments are done through create2 with a specific `salt`
that is derived from a combination of the deployer's address,
the underlying asset used, as well as the name and symbol specified.
Expand All @@ -33,6 +31,15 @@

from vyper.interfaces import ERC20

interface IVault:
def initialize(
asset: address,
name: String[64],
symbol: String[32],
role_manager: address,
profit_max_unlock_time: uint256
): nonpayable

event NewVault:
vault_address: indexed(address)
asset: indexed(address)
Expand Down Expand Up @@ -68,13 +75,13 @@ struct PFConfig:
fee_recipient: address

# Identifier for this version of the vault.
API_VERSION: constant(String[28]) = "3.0.1"
API_VERSION: constant(String[28]) = "3.0.2"

# The max amount the protocol fee can be set to.
MAX_FEE_BPS: constant(uint16) = 5_000 # 50%

# The address that all newly deployed vaults are based from.
VAULT_BLUEPRINT: immutable(address)
VAULT_ORIGINAL: immutable(address)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you consider VAULT_IMPLEMENTATION?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i did not.

I guess that would be more accurate.

Went with language more associated with just cloning than proxies

I guess Implementation may be confusing, and seem like its possible to upgrade it.


# State of the Factory. If True no new vaults can be deployed.
shutdown: public(bool)
Expand All @@ -95,21 +102,21 @@ custom_protocol_fee: public(HashMap[address, uint16])
use_custom_protocol_fee: public(HashMap[address, bool])

@external
def __init__(name: String[64], vault_blueprint: address, governance: address):
def __init__(name: String[64], vault_original: address, governance: address):
self.name = name
VAULT_BLUEPRINT = vault_blueprint
VAULT_ORIGINAL = vault_original
self.governance = governance

@external
def deploy_new_vault(
asset: ERC20,
asset: address,
name: String[64],
symbol: String[32],
role_manager: address,
profit_max_unlock_time: uint256
) -> address:
"""
@notice Deploys a new vault base on the bLueprint.
@notice Deploys a new clone of the original vault.
@param asset The asset to be used for the vault.
@param name The name of the new vault.
@param symbol The symbol of the new vault.
Expand All @@ -120,29 +127,32 @@ def deploy_new_vault(
# Make sure the factory is not shutdown.
assert not self.shutdown, "shutdown"

# Deploy the new vault using the blueprint.
vault_address: address = create_from_blueprint(
VAULT_BLUEPRINT,
asset,
name,
symbol,
role_manager,
profit_max_unlock_time,
code_offset=3,
salt=keccak256(_abi_encode(msg.sender, asset.address, name, symbol))
# Clone a new version of the vault using create2.
vault_address: address = create_minimal_proxy_to(
VAULT_ORIGINAL,
value=0,
salt=keccak256(_abi_encode(msg.sender, asset, name, symbol))
)

IVault(vault_address).initialize(
asset,
name,
symbol,
role_manager,
profit_max_unlock_time,
)

log NewVault(vault_address, asset.address)
log NewVault(vault_address, asset)
return vault_address

@view
@external
def vault_blueprint()-> address:
def vault_original()-> address:
"""
@notice Get the address of the vault blueprint
@return The address of the vault blueprint
@notice Get the address of the vault to clone from
@return The address of the original vault.
"""
return VAULT_BLUEPRINT
return VAULT_ORIGINAL

@view
@external
Expand Down
Loading
Loading