Skip to content

Commit

Permalink
Merge branch 'multisig-plan' of github.com:makerdao/dss-direct-deposi…
Browse files Browse the repository at this point in the history
…t into multisig-plan
  • Loading branch information
hexonaut committed Mar 15, 2024
2 parents de4730a + 057b0cb commit 1e49d36
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 24 deletions.
51 changes: 33 additions & 18 deletions src/pools/D3M4626TypePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ interface VatLike {
function nope(address) external;
}

interface D3mHubLike {
function vat() external view returns (address);
function end() external view returns (EndLike);
}

interface EndLike {
function Art(bytes32) external view returns (uint256);
}

contract D3M4626TypePool is ID3MPool {
/* EVENTS */

Expand All @@ -37,23 +46,28 @@ contract D3M4626TypePool is ID3MPool {
IERC20 public immutable dai;
IERC4626 public immutable vault;
VatLike public immutable vat;
bytes32 public immutable ilk;

/* STORAGE */

address public hub;
uint256 public exited;
mapping(address => uint256) public wards;

/* CONSTRUCTOR */

constructor(address newDai, address newVault, address newVat) {
require(newDai != address(0), "D3M4626TypePool/zero-address");
require(newVat != address(0), "D3M4626TypePool/zero-address");
require(newVault != address(0), "D3M4626TypePool/zero-address");
require(IERC4626(newVault).asset() == address(newDai), "D3M4626TypePool/vault-asset-is-not-dai");
constructor(bytes32 ilk_, address hub_, address dai_, address vault_) {
require(ilk_ != bytes32(0), "D3M4626TypePool/zero-bytes32");
require(hub_ != address(0), "D3M4626TypePool/zero-address");
require(dai_ != address(0), "D3M4626TypePool/zero-address");
require(vault_ != address(0), "D3M4626TypePool/zero-address");
require(IERC4626(vault_).asset() == dai_, "D3M4626TypePool/vault-asset-is-not-dai");

dai = IERC20(newDai);
vault = IERC4626(newVault);
vat = VatLike(newVat);
ilk = ilk_;
hub = hub_;
dai = IERC20(dai_);
vault = IERC4626(vault_);
vat = VatLike(D3mHubLike(hub).vat());

wards[msg.sender] = 1;
emit Rely(msg.sender);
Expand All @@ -64,7 +78,7 @@ contract D3M4626TypePool is ID3MPool {
/* MODIFIERS */

modifier onlyHub() {
require(msg.sender == hub, "D3M4626TypePool/only-hub");
require(msg.sender == address(hub), "D3M4626TypePool/only-hub");
_;
}

Expand All @@ -76,28 +90,29 @@ contract D3M4626TypePool is ID3MPool {
/* ONLY HUB */

/// @inheritdoc ID3MPool
function deposit(uint256 assets) external override onlyHub {
vault.deposit(assets, address(this));
function deposit(uint256 wad) external override onlyHub {
vault.deposit(wad, address(this));
}

/// @inheritdoc ID3MPool
function withdraw(uint256 assets) external override onlyHub {
vault.withdraw(assets, msg.sender, address(this));
function withdraw(uint256 wad) external override onlyHub {
vault.withdraw(wad, msg.sender, address(this));
}

/// @inheritdoc ID3MPool
/// @dev prop = 100 ether exists 100%.
function exit(address dst, uint256 prop) external onlyHub {
uint256 shares = prop * vault.balanceOf(address(this)) / 100 ether;
vault.transfer(dst, shares);
function exit(address dst, uint256 wad) external override onlyHub {
uint256 exited_ = exited;
exited = exited_ + wad;
uint256 amt = wad * vault.balanceOf(address(this)) / (D3mHubLike(hub).end().Art(ilk) - exited_);
require(vault.transfer(dst, amt), "D3M4626TypePool/transfer-failed");
}

/* ONLY AUTHORIZED */

/// @inheritdoc ID3MPool
function quit(address dst) external auth {
require(vat.live() == 1, "D3M4626TypePool/no-quit-during-shutdown");
vault.transfer(dst, vault.balanceOf(address(this)));
require(vault.transfer(dst, vault.balanceOf(address(this))), "D3M4626TypePool/transfer-failed");
}

function rely(address usr) public auth {
Expand Down
19 changes: 13 additions & 6 deletions src/tests/pools/D3M4626TypePool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ contract D3M4626TypePoolTest is D3MPoolBaseTest {

D3M4626TypePool pool;
ERC4626 vault;
bytes32 constant ILK = "TEST-ILK";

function setUp() public {
baseInit("D3M4626TypePool");

vault = new ERC4626(ERC20(address(dai)), "dai vault", "DV");

setPoolContract(pool = new D3M4626TypePool(address(dai), address(vault), address(vat)));
setPoolContract(pool = new D3M4626TypePool(ILK, address(hub), address(dai), address(vault)));

pool.file("hub", address(hub));

Expand All @@ -61,6 +62,10 @@ contract D3M4626TypePoolTest is D3MPoolBaseTest {
assertEq(address(pool.vat()), address(vat));
}

function invariant_ilk_value() public {
assertEq(pool.ilk(), ILK);
}

function test_cannot_file_hub_no_auth() public {
pool.deny(address(this));
vm.expectRevert("D3M4626TypePool/not-authorized");
Expand Down Expand Up @@ -103,14 +108,16 @@ contract D3M4626TypePoolTest is D3MPoolBaseTest {
function test_exit_adai() public {
deal(address(dai), address(this), 1e18);
vault.deposit(1e18, address(this));
vault.transfer(address(pool), vault.balanceOf(address(this)));
uint256 tokens = vault.totalSupply();
vault.transfer(address(pool), tokens);
assertEq(vault.balanceOf(address(this)), 0);
assertEq(vault.balanceOf(address(pool)), 1e18);
assertEq(vault.balanceOf(address(pool)), tokens);

vm.prank(address(hub)); pool.exit(address(this), 1e18);
end.setArt(tokens);
vm.prank(address(hub)); pool.exit(address(this), tokens);

assertEq(vault.balanceOf(address(this)), 0.01e18);
assertEq(vault.balanceOf(address(pool)), 0.99e18);
assertEq(vault.balanceOf(address(this)), tokens);
assertEq(vault.balanceOf(address(pool)), 0);
}

function test_quit_moves_balance() public {
Expand Down
3 changes: 3 additions & 0 deletions src/tests/pools/D3MPoolBase.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,19 @@ abstract contract D3MPoolBaseTest is DssTest {
end.setArt(100 ether);

assertEq(redeemableToken.balanceOf(TEST_ADDRESS), 0);
assertEq(ExitLike(address(pool)).exited(), 0);

vm.prank(address(hub)); pool.exit(TEST_ADDRESS, 10 ether); // Exit 10%

assertApproxEqAbs(redeemableToken.balanceOf(TEST_ADDRESS), initialBalance * 10 / 100, 10);
assertApproxEqAbs(redeemableToken.balanceOf(address(pool)), initialBalance * 90 / 100, 10);
assertEq(ExitLike(address(pool)).exited(), 10 ether);

vm.prank(address(hub)); pool.exit(TEST_ADDRESS, 20 ether); // Exit another 20%

assertApproxEqAbs(redeemableToken.balanceOf(TEST_ADDRESS), initialBalance * 30 / 100, 10);
assertApproxEqAbs(redeemableToken.balanceOf(address(pool)), initialBalance * 70 / 100, 10);
assertEq(ExitLike(address(pool)).exited(), 30 ether);
}

}

0 comments on commit 1e49d36

Please sign in to comment.