Skip to content

Commit

Permalink
Merge pull request curvefi#30 from curvefi/fix/audit
Browse files Browse the repository at this point in the history
fixes from auditor comments
  • Loading branch information
bout3fiddy authored Nov 1, 2023
2 parents 96e8ca4 + 48bfbbb commit 4902993
Show file tree
Hide file tree
Showing 49 changed files with 4,527 additions and 2,299 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
run: |
pip install poetry==1.5.1
poetry config virtualenvs.in-project true
poetry install --no-interaction
poetry install --no-interaction --without dev
- name: Run Tests Basic
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
run: |
pip install poetry==1.5.1
poetry config virtualenvs.in-project true
poetry install --no-interaction
poetry install --no-interaction --without dev
- name: Run Tests
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
run: |
pip install poetry==1.5.1
poetry config virtualenvs.in-project true
poetry install --no-interaction
poetry install --no-interaction --without dev
- name: Run All Token Tests 18,18
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
pip install poetry==1.5.1
poetry config virtualenvs.in-project true
poetry install --no-interaction
poetry install --no-interaction --without dev
- name: Run Tests
run: |
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,6 @@ node_modules
docs/
scripts/experiments/get_p.py
.python-version
todo.txt
AuditorComments.md
set_env.py
8 changes: 5 additions & 3 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Stableswap NG

Permissionless deployment of Curve metapools.
Permissionless deployment of Curve Stableswap plain and metapools. Supports up to 8 coins for plain pools and 2 coins for metapools. Supports: rate-oraclised tokens (e.g. wstETH), ERC4626 (sDAI), rebasing (stETH), and plain (WETH:stETH) pools. Does not support native tokens.

# Wen?
For integrators: check exchange_received. That should improve your pathing significantly. Be aware that if a pool contains rebasing tokens, this method is intentionally disabled.

![STOP THE WEN!](./you_shall_not_wen.jpeg)
# Deployments

For a full list of deployments, please check: [The deployment script](scripts/deploy_infra.py)

## Overview

Expand Down
4 changes: 1 addition & 3 deletions ape-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ plugins:
default_ecosystem: ethereum

# vyper:
# default_version: paris # enable for non PUSH0 evm networks
# ethereum:
# evm_version: shanghai
# evm_version: shanghai

hardhat:
port: auto
Expand Down
156 changes: 156 additions & 0 deletions contracts/ProxyAdmin.vy
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# pragma version 0.3.10
# pragma evm-version paris
"""
@title ProxyAdmin
@notice Thin proxy allowing shared ownership of contracts
@author Ben Hauser
@license MIT
"""


event TransactionExecuted:
admin: indexed(address)
target: indexed(address)
calldata: Bytes[100000]
value: uint256

event RequestAdminChange:
current_admin: address
future_admin: address

event RevokeAdminChange:
current_admin: address
future_admin: address
calling_admin: address

event ApproveAdminChange:
current_admin: address
future_admin: address
calling_admin: address

event AcceptAdminChange:
previous_admin: address
current_admin: address


admins: public(address[2])

pending_current_admin: uint256
pending_new_admin: address
change_approved: bool


@external
def __init__(_authorized: address[2]):
"""
@notice Contract constructor
@param _authorized Admin accounts for this contract
"""
self.admins = _authorized


@payable
@external
def execute(_target: address, _calldata: Bytes[100000]):
"""
@notice Execute a contract call
@dev Ether sent when calling this function is forwarded onward
@param _target Address of the contract to call
@param _calldata Calldata to use in the call
"""
assert msg.sender in self.admins # dev: only admin

raw_call(_target, _calldata, value=msg.value)
log TransactionExecuted(msg.sender, _target, _calldata, msg.value)


@view
@external
def get_admin_change_status() -> (address, address, bool):
"""
@notice Get information about a pending admin change
@return Admin address to be replaced,
admin address to be added,
has change been approved?
"""
idx: uint256 = self.pending_current_admin
if idx == 0:
return ZERO_ADDRESS, ZERO_ADDRESS, False
else:
return self.admins[idx - 1], self.pending_new_admin, self.change_approved


@external
def request_admin_change(_new_admin: address):
"""
@notice Initiate changing an admin address
@param _new_admin New admin address (replaces msg.sender)
"""
assert self.pending_current_admin == 0 # dev: already an active request

admin_list: address[2] = self.admins
assert _new_admin not in admin_list # dev: new admin is already admin

for i in range(2):
if admin_list[i] == msg.sender:
self.pending_current_admin = i + 1
self.pending_new_admin = _new_admin
log RequestAdminChange(msg.sender, _new_admin)
return

raise # dev: only admin


@external
def approve_admin_change():
"""
@notice Approve changing an admin address
@dev Only callable by the 2nd admin address (the one that will not change)
"""
idx: uint256 = self.pending_current_admin

assert idx > 0 # dev: no active request
assert msg.sender == self.admins[idx % 2] # dev: caller is not 2nd admin

self.change_approved = True
log ApproveAdminChange(self.admins[idx - 1], self.pending_new_admin, msg.sender)


@external
def revoke_admin_change():
"""
@notice Revoke changing an admin address
@dev May be called by either admin at any time to reset the process,
even if approval has previous been given
"""
assert msg.sender in self.admins # dev: only admin

idx: uint256 = self.pending_current_admin
pending_admin: address = ZERO_ADDRESS
if idx > 0:
pending_admin = self.admins[idx - 1]

log RevokeAdminChange(pending_admin, self.pending_new_admin, msg.sender)

self.pending_current_admin = 0
self.pending_new_admin = ZERO_ADDRESS
self.change_approved = False



@external
def accept_admin_change():
"""
@notice Accept a changed admin address
@dev Only callable by the new admin address, after approval has been given
"""
assert self.change_approved == True # dev: change not approved
assert msg.sender == self.pending_new_admin # dev: only new admin

idx: uint256 = self.pending_current_admin - 1
log AcceptAdminChange(self.admins[idx], msg.sender)
self.admins[idx] = msg.sender

self.pending_current_admin = 0
self.pending_new_admin = ZERO_ADDRESS
self.change_approved = False
Loading

0 comments on commit 4902993

Please sign in to comment.