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

Aped #102

Merged
merged 4 commits into from
Jan 7, 2025
Merged

Aped #102

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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ jobs:
run: docker build ./ -t velodrome/sugar

- name: Runs code QA and tests
run: docker run --rm --env-file=env.${{ matrix.chain }} -v $(pwd):/app -w /app -t velodrome/sugar sh -c 'flake8 && brownie test --network=${{ matrix.chain }}-main'
run: docker run --rm --env-file=deployments/${{ matrix.chain }}.env -w /app -t velodrome/sugar sh -c 'python -m black . && ape test --network ${{ matrix.chain }}:mainnet:node --disable-isolation'
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ __pycache__
.env
.history
.hypothesis/
build/
.build/
reports/
22 changes: 7 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
FROM python:3.10-alpine
FROM ghcr.io/apeworx/ape:latest-slim

RUN apk add --no-cache \
git npm build-base linux-headers python3-dev tk libc6-compat gcompat cargo

RUN npm install -g ganache
USER root

COPY . /app
WORKDIR /app

RUN pip install "cython<3.0.0" && pip install --no-build-isolation pyyaml==5.4.1
RUN pip install -r requirements.txt

RUN brownie networks modify optimism-test host=https://sepolia.optimism.io
RUN brownie networks modify optimism-main host=https://optimism-mainnet.wallet.coinbase.com

RUN brownie networks modify base-main host=https://mainnet.base.org
# TODO: move this into an ENV or sort of...
RUN python -c 'import vvm; vvm.install_vyper("0.4.0", True)'
RUN ape pm install
RUN ape pm compile

RUN brownie networks add Bob bob-main host=https://rpc.gobob.xyz chainid=60808
RUN brownie networks add Mode mode-main host=https://mainnet.mode.network chainid=34443
RUN brownie networks add Lisk lisk-main host=https://lisk.drpc.org chainid=1135
RUN brownie networks add Fraxtal fraxtal-main host=https://rpc.frax.com chainid=252
RUN brownie networks add MetalL2 metall2-main host=https://rpc.metall2.com chainid=1750
ENTRYPOINT []
36 changes: 36 additions & 0 deletions ape-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Sugar

vyper:
evm_version: cancun

dependencies:
- pypi: snekmate
config_override:
base_path: src
contracts_folder: snekmate

networks:
custom:
- name: mainnet
ecosystem: mode
chain_id: 34443
- name: mainnet
ecosystem: lisk
chain_id: 1135
- name: mainnet
ecosystem: metall2
chain_id: 1750

node:
mode:
mainnet:
uri: https://mode.drpc.org
lisk:
mainnet:
uri: https://lisk.drpc.org
metall2:
mainnet:
uri: https://metall2.drpc.org
optimism:
mainnet:
uri: https://optimism-mainnet.wallet.coinbase.com
13 changes: 0 additions & 13 deletions brownie-config.yaml

This file was deleted.

85 changes: 66 additions & 19 deletions contracts/LpSugar.vy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# @notice Makes it nicer to work with the liquidity pools.

from modules import lp_shared
from snekmate.utils import math

initializes: lp_shared

Expand All @@ -16,6 +17,9 @@ MAX_LPS: public(constant(uint256)) = 500
MAX_POSITIONS: public(constant(uint256)) = 200
MAX_TOKEN_SYMBOL_LEN: public(constant(uint256)) = 32

ALM_SCALE: constant(uint256) = as_wei_value(1000, "ether")
MAX_UINT: constant(uint256) = max_value(uint256)

# Slot0 from CLPool.sol
struct Slot:
sqrtPriceX96: uint160
Expand Down Expand Up @@ -121,7 +125,7 @@ struct Lp:
root: address

# See:
# https://github.com/mellow-finance/mellow-alm-toolkit/blob/main/src/interfaces/ICore.sol#L12-L60
# https://github.com/mellow-finance/mellow-alm-toolkit/blob/main/src/interfaces/ICore.sol#L71-L120
struct AlmManagedPositionInfo:
slippageD9: uint32
property: uint24
Expand Down Expand Up @@ -195,15 +199,15 @@ interface ISlipstreamHelper:
def poolFees(_pool: address, _liquidity: uint128, _current_tick: int24, _lower_tick: int24, _upper_tick: int24) -> Amounts: view

interface IAlmFactory:
def poolToAddresses(pool: address) -> address[2]: view
def getImmutableParams() -> address[5]: view
def poolToWrapper(pool: address) -> address: view
def core() -> address: view

interface IAlmCore:
def managedPositionAt(_id: uint256) -> AlmManagedPositionInfo: view

interface IAlmLpWrapper:
def positionId() -> uint256: view
def totalSupply() -> uint256: view
def previewMint(scale: uint256) -> uint256[2]: view

# Vars
cl_helper: public(ISlipstreamHelper)
Expand Down Expand Up @@ -557,7 +561,7 @@ def _positions(

alm_core: IAlmCore = empty(IAlmCore)
if self.alm_factory != empty(IAlmFactory):
alm_core = IAlmCore((staticcall self.alm_factory.getImmutableParams())[0])
alm_core = IAlmCore(staticcall self.alm_factory.core())

for index: uint256 in range(0, lp_shared.MAX_FACTORIES):
if index >= factories_count:
Expand Down Expand Up @@ -669,11 +673,11 @@ def _positions(
if self.alm_factory == empty(IAlmFactory):
continue

alm_addresses: address[2] = staticcall self.alm_factory.poolToAddresses(pool_addr)
alm_staking: IGauge = IGauge(alm_addresses[0])
alm_vault: IAlmLpWrapper = IAlmLpWrapper(alm_addresses[1])
alm_staking: IGauge = IGauge(
staticcall self.alm_factory.poolToWrapper(pool_addr)
)

if alm_vault.address == empty(address):
if alm_staking.address == empty(address):
continue

alm_user_liq: uint256 = staticcall alm_staking.balanceOf(_account)
Expand All @@ -682,7 +686,7 @@ def _positions(
continue

alm_pos: AlmManagedPositionInfo = staticcall alm_core.managedPositionAt(
staticcall alm_vault.positionId()
staticcall IAlmLpWrapper(alm_staking.address).positionId()
)

if gauge.address != empty(address) and len(alm_pos.ammPositionIds) > 0:
Expand All @@ -700,22 +704,38 @@ def _positions(
nfpm.address
)

alm_liq: uint256 = staticcall alm_vault.totalSupply()
# For the Temper strategy we might have a second position to add up
if len(alm_pos.ammPositionIds) > 1:
pos2: Position = self._cl_position(
alm_pos.ammPositionIds[1],
# Account is the ALM Core contract here...
alm_core.address,
pool_addr,
gauge.address if staked else empty(address),
factory.address,
nfpm.address
)
pos.amount0 += pos2.amount0
pos.amount1 += pos2.amount1
pos.staked0 += pos2.staked0
pos.staked1 += pos2.staked1

alm_liq: uint256 = staticcall alm_staking.totalSupply()
# adjust user share of the vault...
pos.amount0 = (alm_user_liq * pos.amount0) // alm_liq
pos.amount1 = (alm_user_liq * pos.amount1) // alm_liq
pos.staked0 = (alm_user_liq * pos.staked0) // alm_liq
pos.staked1 = (alm_user_liq * pos.staked1) // alm_liq

pos.emissions_earned = staticcall alm_staking.earned(_account)
# ignore dust as the rebalancing might report "fees"
pos.unstaked_earned0 = 0
pos.unstaked_earned1 = 0

pos.liquidity = (alm_user_liq * pos.liquidity) // alm_liq
pos.staked = (alm_user_liq * pos.staked) // alm_liq

pos.alm = alm_vault.address
pos.emissions_earned = staticcall alm_staking.earned(_account)
# ALM liquidity is fully staked
pos.liquidity = 0
pos.staked = alm_user_liq
pos.alm = alm_staking.address

if len(positions) < MAX_POSITIONS:
positions.append(pos)
Expand Down Expand Up @@ -980,9 +1000,9 @@ def _cl_lp(_data: address[4], _token0: address, _token1: address) -> Lp:
if gauge_alive and staticcall gauge.periodFinish() > block.timestamp:
emissions = staticcall gauge.rewardRate()

alm_addresses: address[2] = [empty(address), empty(address)]
alm_wrapper: address = empty(address)
if self.alm_factory != empty(IAlmFactory):
alm_addresses = staticcall self.alm_factory.poolToAddresses(pool.address)
alm_wrapper = staticcall self.alm_factory.poolToWrapper(pool.address)

return Lp({
lp: pool.address,
Expand Down Expand Up @@ -1019,7 +1039,7 @@ def _cl_lp(_data: address[4], _token0: address, _token1: address) -> Lp:
token1_fees: token1_fees,

nfpm: _data[3],
alm: alm_addresses[1],
alm: alm_wrapper,

root: lp_shared._root_lp_address(_data[0], _token0, _token1, tick_spacing),
})
Expand Down Expand Up @@ -1121,3 +1141,30 @@ def _has_userPositions(_nfpm: address) -> bool:
)[1]

return len(response) > 0


@external
@view
def almEstimateAmounts(
_wrapper: address,
_amount0: uint256,
_amount1: uint256
) -> uint256[3]:
"""
@notice Estimates the ALM amounts and LP tokens for a deposit
@param _wrapper The LP Wrapper contract
@param _amount0 First token amount
@param _amount1 Second token amount
@return Returns an array of tokens and LP amounts
"""
targets: uint256[2] = staticcall IAlmLpWrapper(_wrapper).previewMint(ALM_SCALE)

lp_amount: uint256 = min(
MAX_UINT if (targets[0] == 0) else math._mul_div(_amount0, ALM_SCALE, targets[0], False),
MAX_UINT if (targets[1] == 0) else math._mul_div(_amount1, ALM_SCALE, targets[1], False)
)

max0: uint256 = 0 if (targets[0] == 0) else math._mul_div(targets[0], lp_amount, ALM_SCALE, True)
max1: uint256 = 0 if (targets[1] == 0) else math._mul_div(targets[1], lp_amount, ALM_SCALE, True)

return [max0, max1, lp_amount]
17 changes: 3 additions & 14 deletions contracts/modules/lp_shared.vy
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# @title Velodrome Finance LP Module
# @author Velodrome Finance

from snekmate.utils import create2_address

MAX_FACTORIES: constant(uint256) = 10
MAX_POOLS: constant(uint256) = 2000
MAX_ITERATIONS: constant(uint256) = 8000
Expand Down Expand Up @@ -202,17 +204,4 @@ def _root_lp_address(
)
)


data: bytes32 = keccak256(
concat(
0xFF,
convert(_factory, bytes20),
salt,
init_hash
)
)

return convert(
convert(data, uint256) & convert(max_value(uint160), uint256),
address
)
return create2_address._compute_address(salt, init_hash, _factory)
24 changes: 0 additions & 24 deletions contracts/test.vy

This file was deleted.

4 changes: 2 additions & 2 deletions env.base → deployments/base.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VOTER_8453=0x16613524e02ad97eDfeF371bC883F2F5d6C480A5
REGISTRY_8453=0x5C3F18F06CC09CA1910767A34a20F771039E37C0
CONVERTOR_8453=0x1111111111111111111111111111111111111111
SLIPSTREAM_HELPER_8453=0x9c62ab10577fB3C20A22E231b7703Ed6D456CC7a
ALM_FACTORY_8453=0x5B1b1aaC71bDca9Ed1dCb2AA357f678584db4029
ALM_FACTORY_8453=0xb4eA34bDD77D75b97dF6b07DA0b2A3021B6D2227
DIST_8453=0x227f65131A261548b057215bB1D5Ab2997964C7d
RELAY_REGISTRY_ADDRESSES_8453=0x05e41604B9463e2224227053980dfF3f57fb6dB5,0xD308aBCe663302d3b86b36d332CEFd8A4F62C5Ed
GOVERNOR_8453=0x94C012A23A8A65A6f40608dA30534a46a433F410
Expand All @@ -14,7 +14,7 @@ TEST_FACTORY_ADDRESS_8453=0x5e7BB104d84c7CB9B682AaC2F3d509f5F406809A
TEST_ADDRESS_8453=0x892Ff98a46e5bd141E2D12618f4B2Fe6284debac
TEST_ALM_ADDRESS_8453=0x892Ff98a46e5bd141E2D12618f4B2Fe6284debac

LP_SUGAR_ADDRESS_8453=0xF117AFbE285f867c67960F4bfEDe3121Cf6d8F76
LP_SUGAR_ADDRESS_8453=0x8D1eaAFe47D6b2d560d69Ff44A7e0D48980ab69b
REWARDS_SUGAR_ADDRESS_8453=0xA44600F4DBA6683d8BD99270B1A6a143fB9F1C3B
VE_SUGAR_ADDRESS_8453=0x4c5d3925fe65DFeB5A079485136e4De09cb664A5
RELAY_SUGAR_ADDRESS_8453=0x8932B5FE23C07Df06533F8f09E43e7cca6a24143
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion env.mode → deployments/mode.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CONVERTOR_34443=0x1111111111111111111111111111111111111111
SLIPSTREAM_HELPER_34443=0xD24a61656AB0d70994Ef5F42fE11AA95c0a1d329
ALM_FACTORY_34443=0x0000000000000000000000000000000000000000

LP_SUGAR_ADDRESS_34443=0x8A5e97184E8850064805fAc2427ce7728689De5B
LP_SUGAR_ADDRESS_34443=0x7f23Fa4D139CCD5b7a4e4EFfFe1d2e61b33BCD21
REWARDS_SUGAR_ADDRESS_34443=0xD5d3ABAcB8CF075636792658EE0be8B03AF517B8

TEST_ADDRESS_34443=0x892ff98a46e5bd141e2d12618f4b2fe6284debac
Expand Down
4 changes: 2 additions & 2 deletions env.optimism → deployments/optimism.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ VOTER_10=0x41C914ee0c7E1A5edCD0295623e6dC557B5aBf3C
REGISTRY_10=0xF4c67CdEAaB8360370F41514d06e32CcD8aA1d7B
CONVERTOR_10=0x585Af0b397AC42dbeF7f18395426BF878634f18D
SLIPSTREAM_HELPER_10=0xD45624bf2CB9f65ecbdF3067d21992b099b56202
ALM_FACTORY_10=0xeD8b81E3fF6c54951621715F5992CA52007D88bA
ALM_FACTORY_10=0xb4eA34bDD77D75b97dF6b07DA0b2A3021B6D2227
DIST_10=0x9D4736EC60715e71aFe72973f7885DCBC21EA99b
RELAY_REGISTRY_ADDRESSES_10=0xe9F00f2e61CB0c6fb00A2e457546aCbF0fC303C2,0x6b1253B116B5919932399295C75116d33F8EfF96
GOVERNOR_10=0x1F82e10D58aEf03DeA2e478029fB0387A1cbE989

TEST_ADDRESS_10=0x892ff98a46e5bd141e2d12618f4b2fe6284debac
TEST_ALM_ADDRESS_10=0x892ff98a46e5bd141e2d12618f4b2fe6284debac

LP_SUGAR_ADDRESS_10=0x191FF5F5EAC07b082ff877236E8e7537c2d9D2A7
LP_SUGAR_ADDRESS_10=0x7F6D3A4c8a1111DDbFe282794f4D608aB7Cb23A2
REWARDS_SUGAR_ADDRESS_10=0x62CCFB2496f49A80B0184AD720379B529E9152fB
VE_SUGAR_ADDRESS_10=0x94f913362b232e31daB49a1aFB775cfd25DaA6a1
RELAY_SUGAR_ADDRESS_10=0xb8307e5842B9aeE75C704183F0355076aa74b4e2
8 changes: 4 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,21 +236,21 @@ docker build ./ -t velodrome/sugar

Next start the container with existing environment variables:
```sh
docker run --env-file=env.{{chain}} --rm -v $(pwd):/app -w /app -it velodrome/sugar sh
docker run --env-file=deployments/{{chain}}.env --rm -v $(pwd):/app -w /app -it velodrome/sugar sh
```
The environment has Brownie and Vyper already installed.

To run the tests inside the container, use:
```sh
brownie test --network={{chain}}-test
ape test --network={{chain}}:mainnet:node
```

## Releases

This repository is used to manage the releases for multiple chains.

The latest deployed contracts can be found in the `env.{{chain}}` files in the
root of the repository.
The latest deployed contracts can be found in the `deployments/{{chain}}.env`
files in the root of the repository.

## Why the contracts are not verified?

Expand Down
Loading
Loading