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

MetaMorpho D3M #117

Merged
merged 76 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
d8f53b4
test: change aave irm of DAI
MathisGD Mar 14, 2024
439f8ae
feat: D3M 4626 pool
MathisGD Mar 15, 2024
a967466
add operator plan and tests
hexonaut Mar 15, 2024
697f0c3
RAY unused
hexonaut Mar 15, 2024
0b6de36
new lines at end of file
hexonaut Mar 15, 2024
959cdc8
refactor: revert wards type change and remove urd claim
MathisGD Mar 15, 2024
3d84643
test: minor improvements
MathisGD Mar 15, 2024
66b01df
fix: exit proportionnal
MathisGD Mar 15, 2024
5e39eca
chore: fmt
MathisGD Mar 15, 2024
ac32c5a
Merge remote-tracking branch 'origin/master' into feat/4626-vault-d3m
MathisGD Mar 15, 2024
ab9846e
style: renaming
MathisGD Mar 15, 2024
062b526
style: match more style
MathisGD Mar 15, 2024
a888da1
return 0 target assets when disabled
hexonaut Mar 15, 2024
b1cb6a2
Merge pull request #116 from MathisGD/feat/4626-vault-d3m
hexonaut Mar 15, 2024
d09a093
fix: exit and constructor inputs
MathisGD Mar 15, 2024
057b0cb
style: match more repo style
MathisGD Mar 15, 2024
de4730a
add deploy/init libraries and scripts
hexonaut Mar 15, 2024
1e49d36
Merge branch 'multisig-plan' of github.com:makerdao/dss-direct-deposi…
hexonaut Mar 15, 2024
a0efe5d
fix compiler errors
hexonaut Mar 15, 2024
3fef536
fix: hope hub at construction
MathisGD Mar 15, 2024
3c5006f
fix: minor fixes
MathisGD Mar 15, 2024
2643eb9
view on library; pause proxy is d3m admin
hexonaut Mar 15, 2024
42c6a68
re-arrange 4626 pool to match Spark one to make diff easier for revie…
hexonaut Mar 15, 2024
bc257f5
switch auth and onlyHub
hexonaut Mar 15, 2024
c9348c6
add deposit/withdraw links
hexonaut Mar 15, 2024
cb604b1
set multisig
hexonaut Mar 15, 2024
3052f83
hub to hub_
hexonaut Mar 15, 2024
ce81124
change to not-operator
hexonaut Mar 15, 2024
db98418
unused ilk
hexonaut Mar 15, 2024
d4e2110
remove useless hub
hexonaut Mar 15, 2024
03af9eb
fix naming
hexonaut Mar 15, 2024
2d79650
test: wip integration tests
MathisGD Mar 15, 2024
9183aae
Merge remote-tracking branch 'refs/remotes/origin/multisig-plan' into…
MathisGD Mar 15, 2024
f65e1a0
test: various improvements
MathisGD Mar 17, 2024
686e304
use new vault
hexonaut Mar 17, 2024
c6e9214
remove aave v3-specific stuff
hexonaut Mar 17, 2024
5e655cc
test: minor improvements
MathisGD Mar 17, 2024
c160121
Merge remote-tracking branch 'origin/multisig-plan' into multisig-plan
MathisGD Mar 17, 2024
3615bb4
test: fix invariant_vault_maxDeposit
MathisGD Mar 17, 2024
bbdea8b
fixing some test behaviour
hexonaut Mar 17, 2024
698ec5c
fix morpho integration tests
hexonaut Mar 17, 2024
da5ae45
chore: update CI to CVL version 7
QGarchery Mar 18, 2024
d8a85f8
fix: separate multiple prover args
QGarchery Mar 18, 2024
efa9fd3
docs: small changes to the README
QGarchery Mar 18, 2024
940cb93
test: first metamorpho specific integration test
MathisGD Mar 18, 2024
da33537
docs: typo
MathisGD Mar 18, 2024
6cab878
Merge pull request #118 from QGarchery/certora/update-certora-ci
hexonaut Mar 18, 2024
7f9752a
revert certora changes
hexonaut Mar 18, 2024
574965d
remove increase in error threshold
hexonaut Mar 19, 2024
6b827d0
enable the asserts again with the rounding taken into account
hexonaut Mar 19, 2024
bcd532c
use approx eq instead and remove comments
hexonaut Mar 19, 2024
3a008e2
test: more integration test
MathisGD Mar 19, 2024
5e659d1
Merge remote-tracking branch 'origin/multisig-plan' into multisig-plan
MathisGD Mar 19, 2024
f6fc31d
Merge branch 'master' into multisig-plan
hexonaut Mar 19, 2024
22298e7
Merge branch 'multisig-plan' of github.com:makerdao/dss-direct-deposi…
hexonaut Mar 19, 2024
d0998b4
chore: revert prettier changes
MathisGD Mar 19, 2024
1930068
test: deposit in 2 markets, reallocation
MathisGD Mar 21, 2024
d52372f
Merge remote-tracking branch 'origin/multisig-plan' into multisig-plan
MathisGD Mar 21, 2024
0ddf50f
test: remove vm.assume
MathisGD Mar 21, 2024
22c79f6
test: fmt and variables for addresses
MathisGD Mar 21, 2024
df2fd08
test: one test for each path
MathisGD Mar 21, 2024
e120253
update deploy params to match risk values
hexonaut Mar 21, 2024
2929fab
add chainsecurity audit report
hexonaut Mar 21, 2024
4eedf4f
test: concrete values deposit test
MathisGD Mar 21, 2024
13916d8
Merge remote-tracking branch 'origin/multisig-plan' into multisig-plan
MathisGD Mar 21, 2024
aed0dc3
add date to audit
hexonaut Mar 22, 2024
9dd885f
Merge branch 'master' into multisig-plan
hexonaut Mar 22, 2024
576c75c
test: improve withdraw test
MathisGD Mar 22, 2024
52856ab
Merge remote-tracking branch 'origin/multisig-plan' into multisig-plan
MathisGD Mar 22, 2024
c78d7e1
test: hardcode block before compound 227
MathisGD Mar 22, 2024
8a18cb3
Merge pull request #121 from makerdao/test/fix-d3m-compound
hexonaut Mar 22, 2024
a9c6329
adding spearbit audit report
hexonaut Mar 26, 2024
fe9e4c7
update audit file name
hexonaut Mar 27, 2024
45114d8
chore: remove metamorpho dependancy
MathisGD Mar 28, 2024
2e1bdbd
chore: remove submodule
MathisGD Mar 28, 2024
651ac7e
Merge pull request #122 from makerdao/chore/remove-metamorpho-dep
hexonaut Mar 29, 2024
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
6 changes: 3 additions & 3 deletions .github/workflows/certora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3

MathisGD marked this conversation as resolved.
Show resolved Hide resolved
- uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
distribution: "zulu"
java-version: "11"
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
java-package: jre

- name: Set up Python 3.8
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
[submodule "lib/dss-test"]
path = lib/dss-test
url = https://github.com/makerdao/dss-test
[submodule "lib/solmate"]
sunbreak1211 marked this conversation as resolved.
Show resolved Hide resolved
path = lib/solmate
url = https://github.com/transmissions11/solmate
[submodule "lib/metamorpho"]
path = lib/metamorpho
url = https://github.com/morpho-org/metamorpho
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Direct Deposit Module for Maker

![Build Status](https://github.com/makerdao/dss-direct-deposit/actions/workflows/.github/workflows/tests.yaml/badge.svg?branch=master)

The Dai Direct Deposit Module (D3M) is a tool for directly injecting DAI into third party protocols.
Expand All @@ -11,7 +12,7 @@ The D3M is made of 3 components on the Maker side:

### D3MHub

The primary manager contract responsible for collecting all information and determining which action to take (if any). Each D3M instance is regsitered on the Hub using relevant `file(ilk, ...)` admin functions.
The primary manager contract responsible for collecting all information and determining which action to take (if any). Each D3M instance is registered on the Hub using relevant `file(ilk, ...)` admin functions.

A permissionless `exec(ilk)` function exists which will perform all necessary steps to update the provided liquidity within the debt ceiling and external protocol constraints. `exec(ilk)` will need to be called on a somewhat regular basis to keep the system running properly. During each call to this function, interest will automatically be collected.

Expand Down Expand Up @@ -51,7 +52,7 @@ Below is a configurable parameter for the Compound DAI D3M:

Any Comp that is accured can be permissionlessly collected into the pause proxy by calling `collect()`.

### Setup and Testing
# Setup and Testing

To set up the environment and run tests, run the following commands:

Expand Down
1 change: 1 addition & 0 deletions lib/metamorpho
Submodule metamorpho added at f5faa9
1 change: 1 addition & 0 deletions lib/solmate
Submodule solmate added at c89230
14 changes: 14 additions & 0 deletions script/D3MDeploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ contract D3MDeployScript is Script {
hub,
config.readAddress(".cdai")
);
} else if (poolType.eq("erc4626")) {
d3m.pool = D3MDeploy.deploy4626TypePool(
msg.sender,
admin,
ilk,
hub,
address(dss.dai),
config.readAddress(".vault")
);
} else {
revert("Unknown pool type");
}
Expand Down Expand Up @@ -135,6 +144,11 @@ contract D3MDeployScript is Script {
} else {
revert("Invalid pool type for liquidity buffer plan type");
}
} else if (planType.eq("operator")) {
d3m.plan = D3MDeploy.deployOperatorPlan(
msg.sender,
admin
);
} else {
revert("Unknown plan type");
}
Expand Down
22 changes: 22 additions & 0 deletions script/D3MInit.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ import {
D3MAaveBufferPlanConfig,
D3MCompoundPoolLike,
D3MCompoundRateTargetPlanLike,
D3M4626PoolLike,
D3M4626PoolConfig,
D3MOperatorPlanLike,
D3MOperatorPlanConfig,
CDaiLike
} from "../src/deploy/D3MInit.sol";

Expand Down Expand Up @@ -119,6 +123,16 @@ contract D3MInitScript is Script {
cfg,
compoundCfg
);
} else if (poolType.eq("erc4626")) {
D3M4626PoolConfig memory erc4626Cfg = D3M4626PoolConfig({
vault: D3M4626PoolLike(d3m.pool).vault()
});
D3MInit.init4626Pool(
dss,
d3m,
cfg,
erc4626Cfg
);
} else {
revert("Unknown pool type");
}
Expand Down Expand Up @@ -165,6 +179,14 @@ contract D3MInitScript is Script {
} else {
revert("Invalid pool type for liquidity buffer plan type");
}
} else if (planType.eq("operator")) {
D3MOperatorPlanConfig memory operatorCfg = D3MOperatorPlanConfig({
operator: config.readAddress(".operator")
});
D3MInit.initOperatorPlan(
d3m,
operatorCfg
);
} else {
revert("Unknown plan type");
}
Expand Down
14 changes: 14 additions & 0 deletions script/input/1/template-morpho.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"chainlog": "0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F",
"admin": "0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB",
sunbreak1211 marked this conversation as resolved.
Show resolved Hide resolved
"poolType": "erc4626",
"planType": "operator",
"ilk": "DIRECT-SPARK-MORPHO-DAI",
"existingIlk": false,
"maxLine": 500000000,
"gap": 10000000,
"ttl": 21600,
"tau": 604800,
"vault": "0x73e65DBD630f90604062f6E02fAb9138e713edD9",
"operator": "0x298b375f24CeDb45e936D7e21d6Eb05e344adFb5"
}
24 changes: 24 additions & 0 deletions src/deploy/D3MDeploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import { D3MAaveV2TypePool } from "../pools/D3MAaveV2TypePool.sol";
import { D3MAaveV3NoSupplyCapTypePool } from "../pools/D3MAaveV3NoSupplyCapTypePool.sol";
import { D3MCompoundV2TypeRateTargetPlan } from "../plans/D3MCompoundV2TypeRateTargetPlan.sol";
import { D3MCompoundV2TypePool } from "../pools/D3MCompoundV2TypePool.sol";
import { D3M4626TypePool } from "../pools/D3M4626TypePool.sol";
import { D3MOperatorPlan } from "../plans/D3MOperatorPlan.sol";
import { D3MOracle } from "../D3MOracle.sol";

// Deploy a D3M instance
Expand Down Expand Up @@ -96,6 +98,19 @@ library D3MDeploy {
ScriptTools.switchOwner(pool, deployer, owner);
}

function deploy4626TypePool(
address deployer,
address owner,
bytes32 ilk,
address hub,
address dai,
address vault
) internal returns (address pool) {
pool = address(new D3M4626TypePool(ilk, hub, dai, vault));

ScriptTools.switchOwner(pool, deployer, owner);
}

function deployAaveV2TypeRateTargetPlan(
address deployer,
address owner,
Expand Down Expand Up @@ -127,4 +142,13 @@ library D3MDeploy {
ScriptTools.switchOwner(plan, deployer, owner);
}

function deployOperatorPlan(
address deployer,
address owner
) internal returns (address plan) {
plan = address(new D3MOperatorPlan());

ScriptTools.switchOwner(plan, deployer, owner);
}

}
48 changes: 48 additions & 0 deletions src/deploy/D3MInit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,18 @@ interface CDaiLike {
function implementation() external view returns (address);
}

interface D3M4626PoolLike {
function hub() external view returns (address);
function dai() external view returns (address);
function ilk() external view returns (bytes32);
function vat() external view returns (address);
function vault() external view returns (address);
}

interface D3MOperatorPlanLike {
function file(bytes32, address) external;
}

interface D3MOracleLike {
function vat() external view returns (address);
function ilk() external view returns (bytes32);
Expand Down Expand Up @@ -148,6 +160,14 @@ struct D3MCompoundRateTargetPlanConfig {
address delegate;
}

struct D3M4626PoolConfig {
address vault;
}

struct D3MOperatorPlanConfig {
address operator;
}

// Init a D3M instance
library D3MInit {

Expand Down Expand Up @@ -275,6 +295,25 @@ library D3MInit {
pool.file("king", compoundCfg.king);
}

/**
* @dev Initialize a 4626 pool.
*/
function init4626Pool(
DssInstance memory dss,
D3MInstance memory d3m,
D3MCommonConfig memory cfg,
D3M4626PoolConfig memory erc4626Cfg
) internal view {
D3M4626PoolLike pool = D3M4626PoolLike(d3m.pool);

// Sanity checks
require(pool.hub() == cfg.hub, "Pool hub mismatch");
require(pool.ilk() == cfg.ilk, "Pool ilk mismatch");
require(pool.vat() == address(dss.vat), "Pool vat mismatch");
require(pool.dai() == address(dss.dai), "Pool dai mismatch");
require(pool.vault() == erc4626Cfg.vault, "Pool vault mismatch");
}

function initAaveRateTargetPlan(
D3MInstance memory d3m,
D3MAaveRateTargetPlanConfig memory aaveCfg
Expand Down Expand Up @@ -323,4 +362,13 @@ library D3MInit {
plan.file("barb", compoundCfg.barb);
}

function initOperatorPlan(
sunbreak1211 marked this conversation as resolved.
Show resolved Hide resolved
D3MInstance memory d3m,
D3MOperatorPlanConfig memory operatorCfg
) internal {
D3MOperatorPlanLike plan = D3MOperatorPlanLike(d3m.plan);

plan.file("operator", operatorCfg.operator);
}

}
96 changes: 96 additions & 0 deletions src/plans/D3MOperatorPlan.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-FileCopyrightText: © 2022 Dai Foundation <www.daifoundation.org>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity ^0.8.14;

import "./ID3MPlan.sol";

/**
* @title D3M Operator Plan
* @notice An operator sets the desired target assets.
*/
contract D3MOperatorPlan is ID3MPlan {

mapping (address => uint256) public wards;
uint256 public enabled;

address public operator;
uint256 public targetAssets;

Choose a reason for hiding this comment

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

Because it is public, this value can be read in place of getTargetAssets which would be interpreted incorrectly in case enabled == 0 (because it seems it is expected to be interpreted as 0, per getTargetAssets's implementation)

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I think that it's better to enforce that the target assets is set back to zero before disabling the Plan. wdyt?

Copy link

@Rubilmax Rubilmax Mar 17, 2024

Choose a reason for hiding this comment

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

I like this because it avoids side-effects which ultimately avoid unexpected/undesired behaviors
Is it compatible with the usual D3M life cycle though (awaiting confirmation from the Maker side ideally)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to be able to disable without requiring target assets is 0 in the case the multisig goes rogue.

Copy link
Contributor

Choose a reason for hiding this comment

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

but any account that's capable of disabling the plan is also capable of setting themselves as operator to set the target assets at zero right?

anyway the current version is also fine to me, but it has the little tradeoff that @Rubilmax is mentioning

Choose a reason for hiding this comment

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

Or disabling the plan could also set back to zero target assets

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but any account that's capable of disabling the plan is also capable of setting themselves as operator to set the target assets at zero right?

Not in the way we have this constructed. This contract can trigger without a delay: https://github.com/makerdao/dss-direct-deposit/blob/master/src/D3MMom.sol#L76

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd just make targetAssets a private variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Going to leave this for now unless you guys feel strongly. Code is in audit, and this is somewhat of a superficial change on a backend contract which can be upgraded later if desired.


// --- Events ---
event Rely(address indexed usr);
event Deny(address indexed usr);
event File(bytes32 indexed what, address data);
event File(bytes32 indexed what, uint256 data);

constructor() {
enabled = 1;

wards[msg.sender] = 1;
emit Rely(msg.sender);
}

modifier auth {
require(wards[msg.sender] == 1, "D3MOperatorPlan/not-authorized");
_;
}

// --- Admin ---
function rely(address usr) external auth {
wards[usr] = 1;
emit Rely(usr);
}
function deny(address usr) external auth {
wards[usr] = 0;
emit Deny(usr);
}

function file(bytes32 what, address data) external auth {
if (what == "operator") {
operator = data;
} else revert("D3MOperatorPlan/file-unrecognized-param");
emit File(what, data);
}

function file(bytes32 what, uint256 data) external auth {
if (what == "enabled") {
require(data <= 1, "D3MOperatorPlan/invalid-value");
enabled = data;
} else revert("D3MOperatorPlan/file-unrecognized-param");
emit File(what, data);
}
MathisGD marked this conversation as resolved.
Show resolved Hide resolved

function setTargetAssets(uint256 value) external {
MathisGD marked this conversation as resolved.
Show resolved Hide resolved
require(msg.sender == operator, "D3MOperatorPlan/not-operator");

targetAssets = value;
}

function getTargetAssets(uint256) external override view returns (uint256) {
if (enabled == 0) return 0;

return targetAssets;
}
MathisGD marked this conversation as resolved.
Show resolved Hide resolved

function active() public view override returns (bool) {
return enabled == 1;
}

function disable() external override auth {
sunbreak1211 marked this conversation as resolved.
Show resolved Hide resolved
enabled = 0;
emit Disable();
}
}
Loading
Loading