Skip to content

Commit

Permalink
Merge pull request #81 from marsfoundation/dev
Browse files Browse the repository at this point in the history
ALM Controller v1.1.0 Merge Dev to Master
  • Loading branch information
hexonaut authored Jan 13, 2025
2 parents 25447fa + eb81921 commit 41eb420
Show file tree
Hide file tree
Showing 90 changed files with 5,926 additions and 3,832 deletions.
22 changes: 2 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,7 @@ jobs:
ARBITRUM_NOVA_RPC_URL: ${{secrets.ARBITRUM_NOVA_RPC_URL}}
GNOSIS_CHAIN_RPC_URL: ${{secrets.GNOSIS_CHAIN_RPC_URL}}
BASE_RPC_URL: ${{secrets.BASE_RPC_URL}}
run: FOUNDRY_PROFILE=ci forge test --nmc DeployEthereumTest

test-ethereum-staging:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

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

- name: Run tests
env:
MAINNET_RPC_URL: ${{secrets.MAINNET_RPC_URL}}
OPTIMISM_RPC_URL: ${{secrets.OPTIMISM_RPC_URL}}
ARBITRUM_ONE_RPC_URL: ${{secrets.ARBITRUM_ONE_RPC_URL}}
ARBITRUM_NOVA_RPC_URL: ${{secrets.ARBITRUM_NOVA_RPC_URL}}
GNOSIS_CHAIN_RPC_URL: ${{secrets.GNOSIS_CHAIN_RPC_URL}}
BASE_RPC_URL: ${{secrets.BASE_RPC_URL}}
run: FOUNDRY_PROFILE=ci forge test --mc DeployEthereumTest
run: FOUNDRY_PROFILE=ci forge test

coverage:
runs-on: ubuntu-latest
Expand All @@ -76,7 +58,7 @@ jobs:
ARBITRUM_NOVA_RPC_URL: ${{secrets.ARBITRUM_NOVA_RPC_URL}}
GNOSIS_CHAIN_RPC_URL: ${{secrets.GNOSIS_CHAIN_RPC_URL}}
BASE_RPC_URL: ${{secrets.BASE_RPC_URL}}
run: forge coverage --report summary --report lcov --nmc DeployEthereumTest
run: forge coverage --report summary --report lcov

# To ignore coverage for certain directories modify the paths in this step as needed. The
# below default ignores coverage results for the test and script directories. Alternatively,
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@
[submodule "lib/dss-test"]
path = lib/dss-test
url = https://github.com/makerdao/dss-test
[submodule "lib/metamorpho"]
path = lib/metamorpho
url = https://github.com/morpho-org/metamorpho
[submodule "lib/aave-v3-origin"]
path = lib/aave-v3-origin
url = https://github.com/aave-dao/aave-v3-origin
15 changes: 11 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# Staging Full Deployment with Dependencies
deploy-staging-full :; forge script script/staging/FullStagingDeploy.s.sol:FullStagingDeploy --sender ${ETH_FROM} --broadcast --verify

# Staging Deployments
deploy-sepolia-staging :; forge script script/staging/DeploySepolia.s.sol:DeploySepoliaStaging --sender ${ETH_FROM} --broadcast --slow
deploy-ethereum-staging :; forge script script/staging/DeployEthereum.s.sol:DeployEthereumStaging --sender ${ETH_FROM} --broadcast --slow --verify
deploy-mainnet-staging-controller :; ENV=staging forge script script/Deploy.s.sol:DeployMainnetController --sender ${ETH_FROM} --broadcast --verify

deploy-base-staging-controller :; CHAIN=base ENV=staging forge script script/Deploy.s.sol:DeployForeignController --sender ${ETH_FROM} --broadcast --verify

# Production Deployments
deploy-base :; forge script script/Deploy.s.sol:DeployBaseFull --sender ${ETH_FROM} --broadcast --verify
deploy-ethereum :; forge script script/Deploy.s.sol:DeployMainnetFull --sender ${ETH_FROM} --broadcast --verify
deploy-mainnet-production-full :; ENV=production forge script script/Deploy.s.sol:DeployMainnetFull --sender ${ETH_FROM} --broadcast --verify
deploy-mainnet-production-controller :; ENV=production forge script script/Deploy.s.sol:DeployMainnetController --sender ${ETH_FROM} --broadcast --verify

deploy-base-production-full :; CHAIN=base ENV=production forge script script/Deploy.s.sol:DeployForeignFull --sender ${ETH_FROM} --broadcast --verify
deploy-base-production-controller :; CHAIN=base ENV=production forge script script/Deploy.s.sol:DeployForeignController --sender ${ETH_FROM} --broadcast --verify
91 changes: 88 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,14 @@ All functions below change the balance of funds in the ALMProxy contract and are
- `ForeignController`: This contract currently implements logic to:
- Deposit and withdraw on EVM compliant L2 PSM3 contracts (see [spark-psm](https://github.com/marsfoundation/spark-psm) for implementation).
- Initiate a transfer of USDC to other domains using CCTP.
- Deposit, withdraw, and redeem from ERC4626 contracts.
- Deposit and withdraw from AAVE.
- `MainnetController`: This contract currently implements logic to:
- Mint and burn USDS on Ethereum mainnet.
- Deposit, withdraw, redeem in the sUSDS contract.
- Mint and burn USDS.
- Deposit, withdraw, redeem from ERC4626 contracts.
- Deposit and withdraw from AAVE.
- Mint and burn USDe.
- Cooldown and unstake from sUSDe.
- Swap USDS to USDC and vice versa using the mainnet PSM.
- Transfer USDC to other domains using CCTP.

Expand All @@ -68,6 +73,24 @@ The rate limit is calculated as follows:

This is a linear rate limit that increases over time with a maximum limit. This rate limit is derived from these values which can be set by and admin OR updated by the `CONTROLLER` role. The `CONTROLLER` updates these values to increase/decrease the rate limit based on the functionality within the contract (e.g., decrease the rate limit after minting USDS by the minted amount by decrementing `lastAmount` and setting `lastUpdated` to `block.timestamp`).

## Trust Assumptions and Attack Mitigation
Below are all stated trust assumptions for using this contract in production:
- The `DEFAULT_ADMIN_ROLE` is fully trusted, to be run by governance.
- The `RELAYER` role is assumed to be able to be fully compromised by a malicious actor. **This should be a major consideration during auditing engagements.**
- The logic in the smart contracts must prevent the movement of value anywhere outside of the ALM system of contracts.
- Any action must be limited to "reasonable" slippage/losses/opportunity cost by rate limits.
- The `FREEZER` must be able to stop the compromised `RELAYER` from performing more harmful actions within the max rate limits by using the `freeze()` function.
- A compromised `RELAYER` can DOS Ethena unstaking, but this can be mitigated by freezing the Controller and reassigning the `RELAYER`. This is outlined in a test `test_compromisedRelayer_lockingFundsInEthenaSilo`.
- Ethena USDe Mint/Burn is trusted to not honor requests with over 50bps slippage from a delegated signer.

## Operational Requirements
- All ERC-4626 vaults that are onboarded MUST have an initial burned shares amount that prevents rounding-based frontrunning attacks. These shares have to be unrecoverable so that they cannot be removed at a later date.
- All ERC-20 tokens are to be non-rebasing with sufficiently high decimal precision.
- Rate limits must be configured for specific ERC-4626 vaults and AAVE aTokens (vaults without rate limits set will revert). Unlimited rate limits can be used as an onboarding tool.
- Rate limits must take into account:
- Risk tolerance for a given protocol
- Griefing attacks (e.g., repetitive transactions with high slippage by malicious relayer).

## Testing

To run all tests, run the following command:
Expand All @@ -76,9 +99,71 @@ To run all tests, run the following command:
forge test
```

## Deployments
All commands to deploy:
- Either the full system or just the controller
- To mainnet or base
- For staging or production

Can be found in the Makefile, with the nomenclature `make deploy-<domain>-<env>-<type>`.

Deploy a full ALM system to base production: `make deploy-base-production-full`
Deploy a controller to mainnet production: `make deploy-mainnet-production-controller`

To deploy a full staging environment from scratch, with a new allocation system and all necessary dependencies, run `make deploy-staging-full`.

## Upgrade Simulations

To perform upgrades against forks of mainnet and base for testing/simulation purposes, use the following instructions.

1. Set up two anvil nodes forked against mainnet and base.
```
anvil --fork-url $MAINNET_RPC_URL
```
```
anvil --fork-url $BASE_RPC_URL -p 8546
```

2. Point to local RPCs.

```
export MAINNET_RPC_URL=http://127.0.0.1:8545
export BASE_RPC_URL=http://127.0.0.1:8546
```

3. Upgrade mainnet contracts impersonating as the `SPARK_PROXY`.

```
export SPARK_PROXY=0x3300f198988e4C9C63F75dF86De36421f06af8c4
cast rpc --rpc-url="$MAINNET_RPC_URL" anvil_setBalance $SPARK_PROXY `cast to-wei 1000 | cast to-hex`
cast rpc --rpc-url="$MAINNET_RPC_URL" anvil_impersonateAccount $SPARK_PROXY
ENV=production \
OLD_CONTROLLER=0xb960F71ca3f1f57799F6e14501607f64f9B36F11 \
NEW_CONTROLLER=0x5cf73FDb7057E436A6eEaDFAd27E45E7ab6E431e \
forge script script/Upgrade.s.sol:UpgradeMainnetController --broadcast --unlocked --sender $SPARK_PROXY
```

4. Upgrade base contracts impersonating as the `SPARK_EXEUCTOR`.

```
export SPARK_EXECUTOR=0xF93B7122450A50AF3e5A76E1d546e95Ac1d0F579
cast rpc --rpc-url="$BASE_RPC_URL" anvil_setBalance $SPARK_EXECUTOR `cast to-wei 1000 | cast to-hex`
cast rpc --rpc-url="$BASE_RPC_URL" anvil_impersonateAccount $SPARK_EXECUTOR
CHAIN=base \
ENV=production \
OLD_CONTROLLER=0xc07f705D0C0e9F8C79C5fbb748aC1246BBCC37Ba \
NEW_CONTROLLER=0x5F032555353f3A1D16aA6A4ADE0B35b369da0440 \
forge script script/Upgrade.s.sol:UpgradeForeignController --broadcast --unlocked --sender $SPARK_EXECUTOR
```


***
*The IP in this repository was assigned to Mars SPC Limited in respect of the MarsOne SP*

<p align="center">
<img src="https://1827921443-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjvdfbhgN5UCpMtP1l8r5%2Fuploads%2Fgit-blob-c029bb6c918f8c042400dbcef7102c4e5c1caf38%2Flogomark%20colour.svg?alt=media" height="150" />
<img src="https://github.com/user-attachments/assets/841397d0-0cd4-4464-b4b4-6024b6ad6c6d" height="120" />
</p>
20 changes: 8 additions & 12 deletions deploy/ControllerDeploy.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;

import { ALMProxy } from "src/ALMProxy.sol";
import { ForeignController } from "src/ForeignController.sol";
import { MainnetController } from "src/MainnetController.sol";
import { RateLimits } from "src/RateLimits.sol";
import { ALMProxy } from "../src/ALMProxy.sol";
import { ForeignController } from "../src/ForeignController.sol";
import { MainnetController } from "../src/MainnetController.sol";
import { RateLimits } from "../src/RateLimits.sol";

import { ControllerInstance } from "./ControllerInstance.sol";

Expand Down Expand Up @@ -62,8 +62,7 @@ library MainnetControllerDeploy {
address vault,
address psm,
address daiUsds,
address cctp,
address susds
address cctp
)
internal returns (address controller)
{
Expand All @@ -74,8 +73,7 @@ library MainnetControllerDeploy {
vault_ : vault,
psm_ : psm,
daiUsds_ : daiUsds,
cctp_ : cctp,
susds_ : susds
cctp_ : cctp
}));
}

Expand All @@ -84,8 +82,7 @@ library MainnetControllerDeploy {
address vault,
address psm,
address daiUsds,
address cctp,
address susds
address cctp
)
internal returns (ControllerInstance memory instance)
{
Expand All @@ -99,8 +96,7 @@ library MainnetControllerDeploy {
vault_ : vault,
psm_ : psm,
daiUsds_ : daiUsds,
cctp_ : cctp,
susds_ : susds
cctp_ : cctp
}));
}

Expand Down
Loading

0 comments on commit 41eb420

Please sign in to comment.