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

AllocatorOracle: 1 WAD price #69

Merged
merged 8 commits into from
Nov 15, 2023
Merged
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
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ The allocation system includes several actor types:

Each AllocatorDAO has a unique `ilk` (collateral type) with one VAT vault set up for it.

- Each `ilk` supports a 1 trillion NST max debt ceiling.
- The collateral amount of each vault is 1 million WAD (10^6 * 10^18 indivisible units of collateral).
- All the `ilk`s have a shared simple [oracle](https://github.com/makerdao/dss-allocator/blob/dev/src/AllocatorOracle.sol) that just returns a fixed price of 1 Million (which multiplied by the collateral amount makes sure the max debt ceiling can indeed be reached).
- All the `ilk`s have a shared simple [oracle](https://github.com/makerdao/dss-allocator/blob/dev/src/AllocatorOracle.sol) that just returns a fixed price of 1:1 (which multiplied by a huge amount of collateral makes sure the max debt ceiling can indeed be reached). In case it is necessary a governance spell could also increase it further.
oldchili marked this conversation as resolved.
Show resolved Hide resolved

### AllocatorVault

Expand Down
4 changes: 2 additions & 2 deletions deploy/AllocatorInit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ library AllocatorInit {
RegistryLike(sharedInstance.registry).file(ilk, "buffer", ilkInstance.buffer);

// Initiate the allocator vault
dss.vat.slip(ilk, ilkInstance.vault, int256(1_000_000 * WAD));
dss.vat.grab(ilk, ilkInstance.vault, ilkInstance.vault, address(0), int256(1_000_000 * WAD), 0);
dss.vat.slip(ilk, ilkInstance.vault, int256(10**12 * WAD));
dss.vat.grab(ilk, ilkInstance.vault, ilkInstance.vault, address(0), int256(10**12 * WAD), 0);

VaultLike(ilkInstance.vault).file("jug", address(dss.jug));

Expand Down
8 changes: 3 additions & 5 deletions src/AllocatorOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,15 @@
pragma solidity ^0.8.16;

contract AllocatorOracle {
oldchili marked this conversation as resolved.
Show resolved Hide resolved
// 1M price together with 1M supply, allows up to 1T DAI minting
// and it is a good balance for collateral redemption in Global Shutdown
uint256 internal constant PRICE = 10**6 * 10**18; // 1M in WAD
uint256 internal constant WAD = 10**18; // For 1:1 price

/**
@notice Return value and status of the oracle
@return val PRICE constant
@return ok always true
*/
function peek() public pure returns (bytes32 val, bool ok) {
val = bytes32(PRICE);
val = bytes32(WAD);
ok = true;
}

Expand All @@ -36,6 +34,6 @@ contract AllocatorOracle {
@return val PRICE constant
*/
function read() external pure returns (bytes32 val) {
val = bytes32(PRICE);
val = bytes32(WAD);
}
}
10 changes: 5 additions & 5 deletions test/AllocatorOracle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ contract AllocatorOracleTest is DssTest {

function testOracle() public {
(bytes32 val, bool ok) = oracle.peek();
assertEq(val, bytes32(uint256(10**6 * 10**18)));
assertEq(val, bytes32(uint256(10**18)));
assertTrue(ok);
assertEq(oracle.read(), bytes32(uint256(10**6 * 10**18)));
assertEq(oracle.read(), bytes32(uint256(10**18)));
}

function testPricing() public {
uint256 par = 1 * 10**27;
uint256 price = uint256(oracle.read()); // 1 * 10**6 * 10**18;
uint256 colSupply = 1 * 10**6 * 10**18;
uint256 price = uint256(oracle.read()); // 1 * 10**18;
uint256 colSupply = 1 * 10**12 * 10**18;
uint256 colDebt = 1 * 10**6 * 10**45; // Imagine a scenario where the ilk only has 1M debt
uint256 totDebt = 50 * 10**9 * 10**45; // Imagine a scenario where the tot Supply of DAI is 50B

Expand Down Expand Up @@ -52,6 +52,6 @@ contract AllocatorOracleTest is DssTest {
console.log("1 = wad * fix / 10^27 => wad = 10^27 / fix");
uint256 amtDaiNeeded = 10**27 / fix;
console.log("Amount of wei DAI needed to get 1 wei of gem =", amtDaiNeeded);
assertEq(amtDaiNeeded, 0.00000005 * 10**18);
assertEq(amtDaiNeeded, 50_000);
}
}
102 changes: 63 additions & 39 deletions test/integration/Deployment.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ interface AutoLineLike {

contract DeploymentTest is DssTest {

using stdStorage for StdStorage;

// existing contracts
address constant LOG = 0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F;
address constant UNIV3_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
address constant UNIV3_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;

// existing contracts to be fetched from chainlog
address VAT;
address JUG;
DssInstance dss;
address ILK_REGISTRY;
address PAUSE_PROXY;
address DAI;
address USDC;

// actors
Expand Down Expand Up @@ -118,19 +118,17 @@ contract DeploymentTest is DssTest {
function setUp() public {
vm.createSelectFork(vm.envString("ETH_RPC_URL"));

VAT = ChainlogLike(LOG).getAddress("MCD_VAT");
JUG = ChainlogLike(LOG).getAddress("MCD_JUG");
dss = MCD.loadFromChainlog(LOG);
PAUSE_PROXY = ChainlogLike(LOG).getAddress("MCD_PAUSE_PROXY");
ILK_REGISTRY = ChainlogLike(LOG).getAddress("ILK_REGISTRY");
USDC = ChainlogLike(LOG).getAddress("USDC");
DAI = ChainlogLike(LOG).getAddress("MCD_DAI");

nst = address(new GemMock(0));
nstJoin = address(new NstJoinMock(VatMock(VAT), GemMock(nst)));
nstJoin = address(new NstJoinMock(VatMock(address(dss.vat)), GemMock(nst)));
uniV3Callee = address(new SwapperCalleeUniV3(UNIV3_ROUTER));

usdcDaiPath = abi.encodePacked(USDC, uint24(100), DAI);
daiUsdcPath = abi.encodePacked(DAI, uint24(100), USDC);
usdcDaiPath = abi.encodePacked(USDC, uint24(100), address(dss.dai));
daiUsdcPath = abi.encodePacked(address(dss.dai), uint24(100), USDC);

sharedInst = AllocatorDeploy.deployShared(address(this), PAUSE_PROXY);
ilkInst = AllocatorDeploy.deployIlk({
Expand All @@ -148,16 +146,14 @@ contract DeploymentTest is DssTest {
}

function emulateSpell() internal {
DssInstance memory dss = MCD.loadFromChainlog(LOG);

vm.startPrank(PAUSE_PROXY);
AllocatorInit.initShared(dss, sharedInst);

address[] memory swapTokens = new address[](1);
swapTokens[0] = DAI;
swapTokens[0] = address(dss.dai);

address[] memory depositTokens = new address[](2);
depositTokens[0] = DAI;
depositTokens[0] = address(dss.dai);
depositTokens[1] = USDC;

address[] memory facilitators = new address[](2);
Expand Down Expand Up @@ -220,16 +216,14 @@ contract DeploymentTest is DssTest {
}

function testInitIlkValues() public {
DssInstance memory dss = MCD.loadFromChainlog(LOG);

uint256 previousLine = dss.vat.Line();
uint256 previousIlkRegistryCount = IlkRegistryLike(ILK_REGISTRY).count();

emulateSpell();

(, uint256 rate, uint256 spot, uint256 line,) = dss.vat.ilks(ILK);
assertEq(rate, RAY);
assertEq(spot, 10**6 * 10**18 * RAY * 10**9 / dss.spotter.par());
assertEq(spot, 10**18 * RAY * 10**9 / dss.spotter.par());
assertEq(line, 10_000_000 * RAD);
assertEq(dss.vat.Line(), previousLine + 10_000_000 * RAD);

Expand All @@ -253,16 +247,16 @@ contract DeploymentTest is DssTest {

assertEq(dss.vat.gem(ILK, ilkInst.vault), 0);
(uint256 ink, uint256 art) = dss.vat.urns(ILK, ilkInst.vault);
assertEq(ink, 1_000_000 * WAD);
assertEq(ink, 1_000_000_000_000 * WAD);
assertEq(art, 0);

assertEq(AllocatorRegistry(sharedInst.registry).buffers(ILK), ilkInst.buffer);
assertEq(address(AllocatorVault(ilkInst.vault).jug()), address(dss.jug));

assertEq(GemLike(nst).allowance(ilkInst.buffer, ilkInst.vault), type(uint256).max);
assertEq(GemLike(DAI).allowance(ilkInst.buffer, ilkInst.swapper), type(uint256).max);
assertEq(GemLike(DAI).allowance(ilkInst.buffer, ilkInst.depositorUniV3), type(uint256).max);
assertEq(GemLike(USDC).allowance(ilkInst.buffer, ilkInst.depositorUniV3), type(uint256).max);
assertEq(GemLike(nst).allowance(ilkInst.buffer, ilkInst.vault), type(uint256).max);
assertEq(GemLike(address(dss.dai)).allowance(ilkInst.buffer, ilkInst.swapper), type(uint256).max);
assertEq(GemLike(address(dss.dai)).allowance(ilkInst.buffer, ilkInst.depositorUniV3), type(uint256).max);
assertEq(GemLike(USDC).allowance(ilkInst.buffer, ilkInst.depositorUniV3), type(uint256).max);

assertEq(AllocatorRoles(sharedInst.roles).ilkAdmins(ILK), allocatorProxy);

Expand Down Expand Up @@ -345,31 +339,31 @@ contract DeploymentTest is DssTest {
function testSwapFromFacilitator() public {
emulateSpell();

deal(DAI, ilkInst.buffer, 1_000 * WAD);
deal(address(dss.dai), ilkInst.buffer, 1_000 * WAD);

vm.prank(allocatorProxy); Swapper(ilkInst.swapper).setLimits(DAI, USDC, uint96(1_000 * WAD), 1 hours);
vm.prank(facilitator1); Swapper(ilkInst.swapper).swap(DAI, USDC, 1_000 * WAD, 990 * 10**6 , uniV3Callee, daiUsdcPath);
vm.prank(allocatorProxy); Swapper(ilkInst.swapper).setLimits(address(dss.dai), USDC, uint96(1_000 * WAD), 1 hours);
vm.prank(facilitator1); Swapper(ilkInst.swapper).swap(address(dss.dai), USDC, 1_000 * WAD, 990 * 10**6 , uniV3Callee, daiUsdcPath);
}

function testSwapFromKeeper() public {
emulateSpell();

deal(DAI, ilkInst.buffer, 1_000 * WAD);
deal(address(dss.dai), ilkInst.buffer, 1_000 * WAD);

vm.prank(allocatorProxy); Swapper(ilkInst.swapper).setLimits(DAI, USDC, uint96(1_000 * WAD), 1 hours);
vm.prank(facilitator1); StableSwapper(ilkInst.stableSwapper).setConfig(DAI, USDC, 1, 1 hours, uint96(1_000 * WAD), uint96(990 * 10**6));
vm.prank(stableSwapperKeeper1); StableSwapper(ilkInst.stableSwapper).swap(DAI, USDC, 990 * 10**6, uniV3Callee, daiUsdcPath);
vm.prank(allocatorProxy); Swapper(ilkInst.swapper).setLimits(address(dss.dai), USDC, uint96(1_000 * WAD), 1 hours);
vm.prank(facilitator1); StableSwapper(ilkInst.stableSwapper).setConfig(address(dss.dai), USDC, 1, 1 hours, uint96(1_000 * WAD), uint96(990 * 10**6));
vm.prank(stableSwapperKeeper1); StableSwapper(ilkInst.stableSwapper).swap(address(dss.dai), USDC, 990 * 10**6, uniV3Callee, daiUsdcPath);
}

function testDepositWithdrawCollectFromFacilitator() public {
emulateSpell();

deal(DAI, ilkInst.buffer, 1_000 * WAD);
deal(address(dss.dai), ilkInst.buffer, 1_000 * WAD);
deal(USDC, ilkInst.buffer, 1_000 * 10**6);

vm.prank(allocatorProxy); DepositorUniV3(ilkInst.depositorUniV3).setLimits(DAI, USDC, uint24(100), uint96(2_000 * WAD), uint96(2_000 * 10**6), 1 hours);
vm.prank(allocatorProxy); DepositorUniV3(ilkInst.depositorUniV3).setLimits(address(dss.dai), USDC, uint24(100), uint96(2_000 * WAD), uint96(2_000 * 10**6), 1 hours);
DepositorUniV3.LiquidityParams memory dp = DepositorUniV3.LiquidityParams({
gem0 : DAI,
gem0 : address(dss.dai),
gem1 : USDC,
fee : uint24(100),
tickLower : REF_TICK - 100,
Expand All @@ -385,7 +379,7 @@ contract DeploymentTest is DssTest {
vm.prank(facilitator1); DepositorUniV3(ilkInst.depositorUniV3).withdraw(dp, false);

DepositorUniV3.CollectParams memory cp = DepositorUniV3.CollectParams({
gem0 : DAI,
gem0 : address(dss.dai),
gem1 : USDC,
fee : uint24(100),
tickLower: REF_TICK - 100,
Expand All @@ -399,19 +393,19 @@ contract DeploymentTest is DssTest {
function testDepositWithdrawCollectFromKeeper() public {
emulateSpell();

deal(DAI, ilkInst.buffer, 1_000 * WAD);
deal(address(dss.dai), ilkInst.buffer, 1_000 * WAD);
deal(USDC, ilkInst.buffer, 1_000 * 10**6);

vm.prank(allocatorProxy); DepositorUniV3(ilkInst.depositorUniV3).setLimits(DAI, USDC, uint24(100), uint96(2_000 * WAD), uint96(2_000 * 10**6), 1 hours);
vm.prank(allocatorProxy); DepositorUniV3(ilkInst.depositorUniV3).setLimits(address(dss.dai), USDC, uint24(100), uint96(2_000 * WAD), uint96(2_000 * 10**6), 1 hours);

vm.prank(facilitator1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).setConfig(DAI, USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, 1, 1 hours, uint96(1_000 * WAD), uint96(1000 * 10**6), 0, 0);
vm.prank(stableDepositorUniV3Keeper1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).deposit(DAI, USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, 0, 0);
vm.prank(facilitator1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).setConfig(address(dss.dai), USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, 1, 1 hours, uint96(1_000 * WAD), uint96(1000 * 10**6), 0, 0);
vm.prank(stableDepositorUniV3Keeper1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).deposit(address(dss.dai), USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, 0, 0);

vm.prank(facilitator1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).setConfig(DAI, USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, -1, 1 hours, uint96(1_000 * WAD), uint96(1000 * 10**6), 0, 0);
vm.prank(stableDepositorUniV3Keeper1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).withdraw(DAI, USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, 0, 0);
vm.prank(facilitator1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).setConfig(address(dss.dai), USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, -1, 1 hours, uint96(1_000 * WAD), uint96(1000 * 10**6), 0, 0);
vm.prank(stableDepositorUniV3Keeper1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).withdraw(address(dss.dai), USDC, uint24(100), REF_TICK - 100, REF_TICK + 100, 0, 0);

vm.expectRevert(bytes("NP")); // Reverts since no fees to collect and not because the call is unauthorized
vm.prank(stableDepositorUniV3Keeper1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).collect(DAI, USDC, uint24(100), REF_TICK - 100, REF_TICK + 100);
vm.prank(stableDepositorUniV3Keeper1); StableDepositorUniV3(ilkInst.stableDepositorUniV3).collect(address(dss.dai), USDC, uint24(100), REF_TICK - 100, REF_TICK + 100);
}

function testMoveFromKeeper() public {
Expand All @@ -427,4 +421,34 @@ contract DeploymentTest is DssTest {
vm.prank(facilitator1); ConduitMover(ilkInst.conduitMover).setConfig(conduit1, conduit2, USDC, 1, 1 hours, 3_000 * 10**6);
vm.prank(conduitMoverKeeper1); ConduitMover(ilkInst.conduitMover).move(conduit1, conduit2, USDC);
}

function testEndCage() public {
oldchili marked this conversation as resolved.
Show resolved Hide resolved
// This test doesn't mean ES is supported, just aims to check that in case of planned governance shutdown is needed, the End could handle well a huge number of ink
emulateSpell();

vm.prank(facilitator1); AllocatorVault(ilkInst.vault).draw(1_000_000 * WAD);

uint256 ink; uint256 art;
(ink, art) = dss.vat.urns(ILK, address(ilkInst.vault));
assertEq(ink, 1_000_000_000_000 * WAD);
assertEq(art, 1_000_000 * WAD);
assertEq(dss.vat.gem(ILK, address(dss.end)), 0);

vm.prank(PAUSE_PROXY); dss.end.cage();
dss.end.cage(ILK);
assertEq(dss.end.tag(ILK), RAY);
dss.end.skim(ILK, address(ilkInst.vault));

(ink, art) = dss.vat.urns(ILK, address(ilkInst.vault));
assertEq(ink, (1_000_000_000_000 - 1_000_000) * WAD);
assertEq(art, 0);
assertEq(dss.vat.gem(ILK, address(dss.end)), 1_000_000 * WAD);

stdstore.target(address(dss.vat)).sig("dai(address)").with_key(address(dss.vow)).depth(0).checked_write(uint256(0));
vm.warp(block.timestamp + dss.end.wait());
dss.end.thaw();

dss.end.flow(ILK);
assertEq(dss.end.fix(ILK), 1_000_000 * RAD / (dss.vat.debt() / RAY));
}
}