From f5ffb2f7132a78c1f386b5d3d5eef12260363b54 Mon Sep 17 00:00:00 2001 From: nourharidy Date: Tue, 28 Oct 2025 09:31:35 +0300 Subject: [PATCH 1/5] fix reserve setters --- src/Auction.sol | 10 ++++++---- test/Auction.t.sol | 30 ++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/Auction.sol b/src/Auction.sol index c65c7ba..2922215 100644 --- a/src/Auction.sol +++ b/src/Auction.sol @@ -99,16 +99,18 @@ contract Auction { function setDolaReserve(uint _dolaReserve) external onlyGov updateReserves { require(_dolaReserve > 0, "Dola reserve must be positive"); - uint K = dolaReserve * dbrReserve; + uint newDbrReserve = _dolaReserve * dbrReserve / dolaReserve; + require(newDbrReserve > 0, "Resulting DBR reserve must be positive"); dolaReserve = _dolaReserve; - dbrReserve = K / _dolaReserve; + dbrReserve = newDbrReserve; } function setDbrReserve(uint _dbrReserve) external onlyGov updateReserves { require(_dbrReserve > 0, "DBR reserve must be positive"); - uint K = dolaReserve * dbrReserve; + uint newDolaReserve = _dbrReserve * dolaReserve / dbrReserve; + require(newDolaReserve > 0, "Resulting DOLA reserve must be positive"); dbrReserve = _dbrReserve; - dolaReserve = K / _dbrReserve; + dolaReserve = newDolaReserve; } function overrideReserves(uint _dbrReserve, uint _dolaReserve) external onlyGov { diff --git a/test/Auction.t.sol b/test/Auction.t.sol index 8ba2f3c..6db961e 100644 --- a/test/Auction.t.sol +++ b/test/Auction.t.sol @@ -124,9 +124,18 @@ contract AuctionTest is Test { vm.startPrank(gov); vm.expectRevert("Dola reserve must be positive"); auction.setDolaReserve(0); - auction.setDolaReserve(1e19); - assertEq(auction.dolaReserve(), 1e19); - assertEq(auction.dbrReserve(), 1e17); + uint oldDolaReserve = auction.dolaReserve(); + uint oldDbrReserve = auction.dbrReserve(); + uint ratioMantissaBefore = oldDbrReserve * 1e18 / oldDolaReserve; + uint newDolaReserve = 1e19; + uint expectedDbrReserve = newDolaReserve * oldDbrReserve / oldDolaReserve; + auction.setDolaReserve(newDolaReserve); + uint updatedDolaReserve = auction.dolaReserve(); + uint updatedDbrReserve = auction.dbrReserve(); + assertEq(updatedDolaReserve, newDolaReserve); + assertEq(updatedDbrReserve, expectedDbrReserve); + uint ratioMantissaAfter = updatedDbrReserve * 1e18 / updatedDolaReserve; + assertEq(ratioMantissaAfter, ratioMantissaBefore); } function test_setDbrReserve() public { @@ -135,9 +144,18 @@ contract AuctionTest is Test { vm.startPrank(gov); vm.expectRevert("DBR reserve must be positive"); auction.setDbrReserve(0); - auction.setDbrReserve(1e19); - assertEq(auction.dolaReserve(), 1e17); - assertEq(auction.dbrReserve(), 1e19); + uint oldDolaReserve = auction.dolaReserve(); + uint oldDbrReserve = auction.dbrReserve(); + uint ratioMantissaBefore = oldDbrReserve * 1e18 / oldDolaReserve; + uint newDbrReserve = 1e19; + uint expectedDolaReserve = newDbrReserve * oldDolaReserve / oldDbrReserve; + auction.setDbrReserve(newDbrReserve); + uint updatedDbrReserve = auction.dbrReserve(); + uint updatedDolaReserve = auction.dolaReserve(); + assertEq(updatedDbrReserve, newDbrReserve); + assertEq(updatedDolaReserve, expectedDolaReserve); + uint ratioMantissaAfter = updatedDbrReserve * 1e18 / updatedDolaReserve; + assertEq(ratioMantissaAfter, ratioMantissaBefore); } function test_overrideReserves() public { From 06902a6072a72cbfc8cd8337ded11e4f8f287794 Mon Sep 17 00:00:00 2001 From: nourharidy Date: Tue, 28 Oct 2025 09:42:35 +0300 Subject: [PATCH 2/5] rename dola to asset --- ...yer.s.sol => AuctionMainnetDeployer.s.sol} | 27 ++--- .../DolaSaleHandlerMainnetDeployer.s copy.sol | 28 +++++ src/Auction.sol | 64 +++++------ src/{SaleHandler.sol => DolaSaleHandler.sol} | 14 +-- src/Helper.sol | 48 ++++---- test/Auction.t.sol | 108 +++++++++--------- ...aleHandler.t.sol => DolaSaleHandler.t.sol} | 20 ++-- test/Helper.t.sol | 64 +++++------ 8 files changed, 195 insertions(+), 178 deletions(-) rename script/{MainnetDeployer.s.sol => AuctionMainnetDeployer.s.sol} (51%) create mode 100644 script/DolaSaleHandlerMainnetDeployer.s copy.sol rename src/{SaleHandler.sol => DolaSaleHandler.sol} (82%) rename test/{SaleHandler.t.sol => DolaSaleHandler.t.sol} (82%) diff --git a/script/MainnetDeployer.s.sol b/script/AuctionMainnetDeployer.s.sol similarity index 51% rename from script/MainnetDeployer.s.sol rename to script/AuctionMainnetDeployer.s.sol index b89c50e..7df386d 100644 --- a/script/MainnetDeployer.s.sol +++ b/script/AuctionMainnetDeployer.s.sol @@ -2,11 +2,10 @@ pragma solidity 0.8.21; import {Script, console2} from "forge-std/Script.sol"; -import {SaleHandler} from "../src/SaleHandler.sol"; import {Auction} from "../src/Auction.sol"; import {Helper} from "../src/Helper.sol"; -contract MainnetDeployerScript is Script { +contract AuctionMainnetDeployerScript is Script { function setUp() public {} function run() public { @@ -14,36 +13,26 @@ contract MainnetDeployerScript is Script { address gov = 0x926dF14a23BE491164dCF93f4c468A50ef659D5B; address fedChair = 0x8F97cCA30Dbe80e7a8B462F1dD1a51C32accDfC8; - address anDola = 0x7Fcb7DAC61eE35b3D4a51117A7c58D53f0a8a670; - address dola = 0x865377367054516e17014CcdED1e7d814EDC9ce4; + address asset = 0x865377367054516e17014CcdED1e7d814EDC9ce4; address dbr = 0xAD038Eb671c44b853887A7E32528FaB35dC5D710; - address borrower1 = 0xf508c58ce37ce40a40997C715075172691F92e2D; - address borrower2 = 0xeA0c959BBb7476DDD6cD4204bDee82b790AA1562; // 5:1 ratio, implying a 20c DBR starting price - uint dolaReserve = 500_000 * 1e18; - uint dbrReserve = dolaReserve * 5; - - SaleHandler handler = new SaleHandler( - dola, - anDola, - borrower1, - borrower2 - ); + uint assetReserve = 500_000 * 1e18; + uint dbrReserve = assetReserve * 5; Auction auction = new Auction( gov, fedChair, dbr, - dola, - address(handler), - dolaReserve, + asset, + address(0), + assetReserve, dbrReserve ); new Helper( address(auction), - address(dola) + address(asset) ); } } diff --git a/script/DolaSaleHandlerMainnetDeployer.s copy.sol b/script/DolaSaleHandlerMainnetDeployer.s copy.sol new file mode 100644 index 0000000..1a4cf2c --- /dev/null +++ b/script/DolaSaleHandlerMainnetDeployer.s copy.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.21; + +import {Script, console2} from "forge-std/Script.sol"; +import {DolaSaleHandler} from "../src/DolaSaleHandler.sol"; +import {Auction} from "../src/Auction.sol"; +import {Helper} from "../src/Helper.sol"; + +contract DolaSaleHandlerMainnetDeployerScript is Script { + function setUp() public {} + + function run() public { + vm.startBroadcast(); + + address anDola = 0x7Fcb7DAC61eE35b3D4a51117A7c58D53f0a8a670; + address asset = 0x865377367054516e17014CcdED1e7d814EDC9ce4; + address borrower1 = 0xf508c58ce37ce40a40997C715075172691F92e2D; + address borrower2 = 0xeA0c959BBb7476DDD6cD4204bDee82b790AA1562; + + DolaSaleHandler handler = new DolaSaleHandler( + asset, + anDola, + borrower1, + borrower2 + ); + + } +} diff --git a/src/Auction.sol b/src/Auction.sol index 2922215..fa1f340 100644 --- a/src/Auction.sol +++ b/src/Auction.sol @@ -21,9 +21,9 @@ contract Auction { address public gov; address public operator; IDBR public immutable dbr; - IERC20 public immutable dola; + IERC20 public immutable asset; ISaleHandler public saleHandler; - uint public dolaReserve; + uint public assetReserve; uint public dbrReserve; uint public dbrRatePerYear; uint public maxDbrRatePerYear; @@ -33,24 +33,24 @@ contract Auction { address _gov, address _operator, address _dbr, - address _dola, + address _asset, address handler, - uint _dolaReserve, + uint _assetReserve, uint _dbrReserve ) { - require(_dolaReserve > 0, "Dola reserve must be positive"); + require(_assetReserve > 0, "Asset reserve must be positive"); require(_dbrReserve > 0, "DBR reserve must be positive"); gov = _gov; operator = _operator; dbr = IDBR(_dbr); - dola = IERC20(_dola); + asset = IERC20(_asset); saleHandler = ISaleHandler(handler); - dolaReserve = _dolaReserve; + assetReserve = _assetReserve; dbrReserve = _dbrReserve; } modifier updateReserves { - (dolaReserve, dbrReserve) = getCurrentReserves(); + (assetReserve, dbrReserve) = getCurrentReserves(); lastUpdate = block.timestamp; _; } @@ -65,15 +65,15 @@ contract Auction { _; } - function getCurrentReserves() public view returns (uint _dolaReserve, uint _dbrReserve) { + function getCurrentReserves() public view returns (uint _assetReserve, uint _dbrReserve) { uint timeElapsed = block.timestamp - lastUpdate; if(timeElapsed > 0) { - uint K = dolaReserve * dbrReserve; + uint K = assetReserve * dbrReserve; uint DbrsIn = timeElapsed * dbrRatePerYear / 365 days; _dbrReserve = dbrReserve + DbrsIn; - _dolaReserve = K / _dbrReserve; + _assetReserve = K / _dbrReserve; } else { - _dolaReserve = dolaReserve; + _assetReserve = assetReserve; _dbrReserve = dbrReserve; } } @@ -97,47 +97,47 @@ contract Auction { emit RateUpdate(_rate); } - function setDolaReserve(uint _dolaReserve) external onlyGov updateReserves { - require(_dolaReserve > 0, "Dola reserve must be positive"); - uint newDbrReserve = _dolaReserve * dbrReserve / dolaReserve; + function setAssetReserve(uint _assetReserve) external onlyGov updateReserves { + require(_assetReserve > 0, "Asset reserve must be positive"); + uint newDbrReserve = _assetReserve * dbrReserve / assetReserve; require(newDbrReserve > 0, "Resulting DBR reserve must be positive"); - dolaReserve = _dolaReserve; + assetReserve = _assetReserve; dbrReserve = newDbrReserve; } function setDbrReserve(uint _dbrReserve) external onlyGov updateReserves { require(_dbrReserve > 0, "DBR reserve must be positive"); - uint newDolaReserve = _dbrReserve * dolaReserve / dbrReserve; - require(newDolaReserve > 0, "Resulting DOLA reserve must be positive"); + uint newAssetReserve = _dbrReserve * assetReserve / dbrReserve; + require(newAssetReserve > 0, "Resulting asset reserve must be positive"); dbrReserve = _dbrReserve; - dolaReserve = newDolaReserve; + assetReserve = newAssetReserve; } - function overrideReserves(uint _dbrReserve, uint _dolaReserve) external onlyGov { - require(_dolaReserve > 0, "Dola reserve must be positive"); + function overrideReserves(uint _dbrReserve, uint _assetReserve) external onlyGov { + require(_assetReserve > 0, "Asset reserve must be positive"); require(_dbrReserve > 0, "DBR reserve must be positive"); - dolaReserve = _dolaReserve; + assetReserve = _assetReserve; dbrReserve = _dbrReserve; lastUpdate = block.timestamp; } - function buyDBR(uint exactDolaIn, uint exactDbrOut, address to) external updateReserves { - uint K = dolaReserve * dbrReserve; - dolaReserve += exactDolaIn; + function buyDBR(uint exactAssetIn, uint exactDbrOut, address to) external updateReserves { + uint K = assetReserve * dbrReserve; + assetReserve += exactAssetIn; dbrReserve -= exactDbrOut; - require(dolaReserve * dbrReserve >= K, "Invariant"); - dola.transferFrom(msg.sender, address(this), exactDolaIn); + require(assetReserve * dbrReserve >= K, "Invariant"); + asset.transferFrom(msg.sender, address(this), exactAssetIn); dbr.mint(to, exactDbrOut); - emit Buy(msg.sender, to, exactDolaIn, exactDbrOut); + emit Buy(msg.sender, to, exactAssetIn, exactDbrOut); } function sendToSaleHandler() public { require(address(saleHandler) != address(0), "No sale handler"); - uint bal = dola.balanceOf(address(this)); - require(bal > 0, "No DOLA to send"); + uint bal = asset.balanceOf(address(this)); + require(bal > 0, "No asset to send"); uint capacity = saleHandler.getCapacity(); uint amount = bal > capacity ? capacity : bal; - dola.transfer(address(saleHandler), amount); + asset.transfer(address(saleHandler), amount); saleHandler.onReceive(); } @@ -145,7 +145,7 @@ contract Auction { IERC20(token).transfer(destination, amount); } - event Buy(address indexed caller, address indexed to, uint dolaIn, uint dbrOut); + event Buy(address indexed caller, address indexed to, uint assetIn, uint dbrOut); event RateUpdate(uint newRate); event MaxRateUpdate(uint newMaxRate); } diff --git a/src/SaleHandler.sol b/src/DolaSaleHandler.sol similarity index 82% rename from src/SaleHandler.sol rename to src/DolaSaleHandler.sol index 9e124f3..2b5524f 100644 --- a/src/SaleHandler.sol +++ b/src/DolaSaleHandler.sol @@ -11,28 +11,28 @@ interface IAnDola { function borrowBalanceStored(address account) external view returns (uint); // stored is good enough for our use case } -contract SaleHandler { +contract DolaSaleHandler { - IERC20 public immutable dola; + IERC20 public immutable asset; IAnDola public immutable anDola; address public immutable borrower1; address public immutable borrower2; constructor( - address _dola, + address _asset, address _anDola, address _borrower1, address _borrower2 ) { - dola = IERC20(_dola); + asset = IERC20(_asset); anDola = IAnDola(_anDola); borrower1 = _borrower1; borrower2 = _borrower2; - dola.approve(_anDola,type(uint).max); + asset.approve(_anDola,type(uint).max); } function onReceive() external { - uint bal = dola.balanceOf(address(this)); + uint bal = asset.balanceOf(address(this)); uint debt1 = getDebtOf(borrower1); uint debt2 = getDebtOf(borrower2); if(debt1 > debt2) { @@ -49,7 +49,7 @@ contract SaleHandler { } function getCapacity() external view returns (uint) { - return getDebtOf(borrower1) + getDebtOf(borrower2) - dola.balanceOf(address(this)); + return getDebtOf(borrower1) + getDebtOf(borrower2) - asset.balanceOf(address(this)); } } \ No newline at end of file diff --git a/src/Helper.sol b/src/Helper.sol index f80e114..e56323b 100644 --- a/src/Helper.sol +++ b/src/Helper.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.21; interface IAuction { - function getCurrentReserves() external view returns (uint dolaReserve, uint dbrReserve); - function buyDBR(uint exactDolaIn, uint exactDbrOut, address to) external; + function getCurrentReserves() external view returns (uint assetReserve, uint dbrReserve); + function buyDBR(uint exactAssetIn, uint exactDbrOut, address to) external; } interface IERC20 { @@ -14,45 +14,45 @@ interface IERC20 { contract Helper { IAuction public immutable auction; - IERC20 public immutable dola; + IERC20 public immutable asset; constructor( address _auction, - address _dola + address _asset ) { auction = IAuction(_auction); - dola = IERC20(_dola); - dola.approve(_auction, type(uint).max); + asset = IERC20(_asset); + asset.approve(_auction, type(uint).max); } - function getDbrOut(uint dolaIn) public view returns (uint dbrOut) { - require(dolaIn > 0, "dolaIn must be positive"); - (uint dolaReserve, uint dbrReserve) = auction.getCurrentReserves(); - uint numerator = dolaIn * dbrReserve; - uint denominator = dolaReserve + dolaIn; + function getDbrOut(uint assetIn) public view returns (uint dbrOut) { + require(assetIn > 0, "assetIn must be positive"); + (uint assetReserve, uint dbrReserve) = auction.getCurrentReserves(); + uint numerator = assetIn * dbrReserve; + uint denominator = assetReserve + assetIn; dbrOut = numerator / denominator; } - function getDolaIn(uint dbrOut) public view returns (uint dolaIn) { + function getAssetIn(uint dbrOut) public view returns (uint assetIn) { require(dbrOut > 0, "dbrOut must be positive"); - (uint dolaReserve, uint dbrReserve) = auction.getCurrentReserves(); - uint numerator = dbrOut * dolaReserve; + (uint assetReserve, uint dbrReserve) = auction.getCurrentReserves(); + uint numerator = dbrOut * assetReserve; uint denominator = dbrReserve - dbrOut; - dolaIn = (numerator / denominator) + 1; + assetIn = (numerator / denominator) + 1; } - function swapExactDolaForDbr(uint dolaIn, uint dbrOutMin) external returns (uint dbrOut) { - dbrOut = getDbrOut(dolaIn); + function swapExactAssetForDbr(uint assetIn, uint dbrOutMin) external returns (uint dbrOut) { + dbrOut = getDbrOut(assetIn); require(dbrOut >= dbrOutMin, "dbrOut must be greater than dbrOutMin"); - dola.transferFrom(msg.sender, address(this), dolaIn); - auction.buyDBR(dolaIn, dbrOut, msg.sender); + asset.transferFrom(msg.sender, address(this), assetIn); + auction.buyDBR(assetIn, dbrOut, msg.sender); } - function swapDolaForExactDbr(uint dbrOut, uint dolaInMax) external returns (uint dolaIn) { - dolaIn = getDolaIn(dbrOut); - require(dolaIn <= dolaInMax, "dolaIn must be less than dolaInMax"); - dola.transferFrom(msg.sender, address(this), dolaIn); - auction.buyDBR(dolaIn, dbrOut, msg.sender); + function swapAssetForExactDbr(uint dbrOut, uint assetInMax) external returns (uint assetIn) { + assetIn = getAssetIn(dbrOut); + require(assetIn <= assetInMax, "assetIn must be less than assetInMax"); + asset.transferFrom(msg.sender, address(this), assetIn); + auction.buyDBR(assetIn, dbrOut, msg.sender); } } \ No newline at end of file diff --git a/test/Auction.t.sol b/test/Auction.t.sol index 6db961e..952c07a 100644 --- a/test/Auction.t.sol +++ b/test/Auction.t.sol @@ -23,17 +23,17 @@ contract AuctionTest is Test { address gov = address(1); address operator = address(2); ERC20 dbr; - ERC20 dola; + ERC20 asset; Auction auction; function setUp() public { dbr = new ERC20(); - dola = new ERC20(); + asset = new ERC20(); auction = new Auction( gov, operator, address(dbr), - address(dola), + address(asset), address(0), 1e18, 1e18 @@ -44,25 +44,25 @@ contract AuctionTest is Test { assertEq(auction.gov(), gov); assertEq(auction.operator(), operator); assertEq(address(auction.dbr()), address(dbr)); - assertEq(address(auction.dola()), address(dola)); - assertEq(auction.dolaReserve(), 1e18); + assertEq(address(auction.asset()), address(asset)); + assertEq(auction.assetReserve(), 1e18); assertEq(auction.dbrReserve(), 1e18); } function test_getCurrentReserves() public { - (uint _dolaReserve, uint _dbrReserve) = auction.getCurrentReserves(); - assertEq(_dolaReserve, 1e18); + (uint _assetReserve, uint _dbrReserve) = auction.getCurrentReserves(); + assertEq(_assetReserve, 1e18); assertEq(_dbrReserve, 1e18); vm.prank(gov); auction.setMaxDbrRatePerYear(1e18); vm.prank(gov); auction.setDbrRatePerYear(1e18); - (_dolaReserve, _dbrReserve) = auction.getCurrentReserves(); - assertEq(_dolaReserve, 1e18); + (_assetReserve, _dbrReserve) = auction.getCurrentReserves(); + assertEq(_assetReserve, 1e18); assertEq(_dbrReserve, 1e18); vm.warp(block.timestamp + 365 days); - (_dolaReserve, _dbrReserve) = auction.getCurrentReserves(); - assertApproxEqAbs(_dolaReserve, 0.5e18, 1e7); + (_assetReserve, _dbrReserve) = auction.getCurrentReserves(); + assertApproxEqAbs(_assetReserve, 0.5e18, 1e7); assertApproxEqAbs(_dbrReserve, 2 * 1e18, 1e8); } @@ -118,23 +118,23 @@ contract AuctionTest is Test { assertEq(auction.dbrRatePerYear(), 0); } - function test_setDolaReserve() public { + function test_setAssetReserve() public { vm.expectRevert("onlyGov"); - auction.setDolaReserve(1e19); + auction.setAssetReserve(1e19); vm.startPrank(gov); - vm.expectRevert("Dola reserve must be positive"); - auction.setDolaReserve(0); - uint oldDolaReserve = auction.dolaReserve(); + vm.expectRevert("Asset reserve must be positive"); + auction.setAssetReserve(0); + uint oldAssetReserve = auction.assetReserve(); uint oldDbrReserve = auction.dbrReserve(); - uint ratioMantissaBefore = oldDbrReserve * 1e18 / oldDolaReserve; - uint newDolaReserve = 1e19; - uint expectedDbrReserve = newDolaReserve * oldDbrReserve / oldDolaReserve; - auction.setDolaReserve(newDolaReserve); - uint updatedDolaReserve = auction.dolaReserve(); + uint ratioMantissaBefore = oldDbrReserve * 1e18 / oldAssetReserve; + uint newAssetReserve = 1e19; + uint expectedDbrReserve = newAssetReserve * oldDbrReserve / oldAssetReserve; + auction.setAssetReserve(newAssetReserve); + uint updatedAssetReserve = auction.assetReserve(); uint updatedDbrReserve = auction.dbrReserve(); - assertEq(updatedDolaReserve, newDolaReserve); + assertEq(updatedAssetReserve, newAssetReserve); assertEq(updatedDbrReserve, expectedDbrReserve); - uint ratioMantissaAfter = updatedDbrReserve * 1e18 / updatedDolaReserve; + uint ratioMantissaAfter = updatedDbrReserve * 1e18 / updatedAssetReserve; assertEq(ratioMantissaAfter, ratioMantissaBefore); } @@ -144,17 +144,17 @@ contract AuctionTest is Test { vm.startPrank(gov); vm.expectRevert("DBR reserve must be positive"); auction.setDbrReserve(0); - uint oldDolaReserve = auction.dolaReserve(); + uint oldAssetReserve = auction.assetReserve(); uint oldDbrReserve = auction.dbrReserve(); - uint ratioMantissaBefore = oldDbrReserve * 1e18 / oldDolaReserve; + uint ratioMantissaBefore = oldDbrReserve * 1e18 / oldAssetReserve; uint newDbrReserve = 1e19; - uint expectedDolaReserve = newDbrReserve * oldDolaReserve / oldDbrReserve; + uint expectedAssetReserve = newDbrReserve * oldAssetReserve / oldDbrReserve; auction.setDbrReserve(newDbrReserve); uint updatedDbrReserve = auction.dbrReserve(); - uint updatedDolaReserve = auction.dolaReserve(); + uint updatedAssetReserve = auction.assetReserve(); assertEq(updatedDbrReserve, newDbrReserve); - assertEq(updatedDolaReserve, expectedDolaReserve); - uint ratioMantissaAfter = updatedDbrReserve * 1e18 / updatedDolaReserve; + assertEq(updatedAssetReserve, expectedAssetReserve); + uint ratioMantissaAfter = updatedDbrReserve * 1e18 / updatedAssetReserve; assertEq(ratioMantissaAfter, ratioMantissaBefore); } @@ -162,7 +162,7 @@ contract AuctionTest is Test { vm.expectRevert("onlyGov"); auction.overrideReserves(0,0); vm.startPrank(gov); - vm.expectRevert("Dola reserve must be positive"); + vm.expectRevert("Asset reserve must be positive"); auction.overrideReserves(1,0); vm.expectRevert("DBR reserve must be positive"); auction.overrideReserves(0,1); @@ -170,55 +170,55 @@ contract AuctionTest is Test { vm.warp(newTimestamp); auction.overrideReserves(2,3); assertEq(auction.dbrReserve(), 2); - assertEq(auction.dolaReserve(), 3); + assertEq(auction.assetReserve(), 3); assertEq(auction.lastUpdate(), newTimestamp); } function test_sweep() public { vm.expectRevert("onlyGov"); auction.sweep(address(1), address(1), 1); - dola.mint(address(auction), 1); - assertEq(dola.balanceOf(address(auction)), 1); + asset.mint(address(auction), 1); + assertEq(asset.balanceOf(address(auction)), 1); vm.prank(gov); - auction.sweep(address(dola), address(this), 1); - assertEq(dola.balanceOf(address(auction)), 0); - assertEq(dola.balanceOf(address(this)), 1); + auction.sweep(address(asset), address(this), 1); + assertEq(asset.balanceOf(address(auction)), 0); + assertEq(asset.balanceOf(address(this)), 1); } - function test_sendToSaleHandler(uint dolaIn) public { - dolaIn = bound(dolaIn, 1, type(uint).max - 1e18); // max dola in = (max uint - dola reserve) + function test_sendToSaleHandler(uint assetIn) public { + assetIn = bound(assetIn, 1, type(uint).max - 1e18); // max asset in = (max uint - asset reserve) MockSaleHandler handler = new MockSaleHandler(); vm.expectRevert("No sale handler"); auction.sendToSaleHandler(); vm.prank(gov); auction.setSaleHandler(address(handler)); - dola.mint(address(auction), dolaIn); - handler.setCapacity(dolaIn - 1); + asset.mint(address(auction), assetIn); + handler.setCapacity(assetIn - 1); auction.sendToSaleHandler(); - assertEq(dola.balanceOf(address(auction)), 1); - assertEq(dola.balanceOf(address(handler)), dolaIn - 1); + assertEq(asset.balanceOf(address(auction)), 1); + assertEq(asset.balanceOf(address(handler)), assetIn - 1); assertEq(handler.received(), true); } - function test_buyDBR(uint exactDolaIn, uint exactDbrOut) public { + function test_buyDBR(uint exactAssetIn, uint exactDbrOut) public { exactDbrOut = bound(exactDbrOut, 1, auction.dbrReserve()); - exactDolaIn = bound(exactDolaIn, 0, (type(uint).max - auction.dolaReserve()) / auction.dbrReserve() - exactDbrOut); - dola.mint(address(this), exactDolaIn); - dola.approve(address(auction), exactDolaIn); - uint K = auction.dolaReserve() * auction.dbrReserve(); + exactAssetIn = bound(exactAssetIn, 0, (type(uint).max - auction.assetReserve()) / auction.dbrReserve() - exactDbrOut); + asset.mint(address(this), exactAssetIn); + asset.approve(address(auction), exactAssetIn); + uint K = auction.assetReserve() * auction.dbrReserve(); uint newDbrReserve = auction.dbrReserve() - exactDbrOut; - uint newDolaReserve = auction.dolaReserve() + exactDolaIn; - uint newK = newDolaReserve * newDbrReserve; + uint newAssetReserve = auction.assetReserve() + exactAssetIn; + uint newK = newAssetReserve * newDbrReserve; if(newK < K) { vm.expectRevert("Invariant"); - auction.buyDBR(exactDolaIn, exactDbrOut, address(1)); + auction.buyDBR(exactAssetIn, exactDbrOut, address(1)); } else { - auction.buyDBR(exactDolaIn, exactDbrOut, address(1)); - assertEq(dola.balanceOf(address(this)), 0); - assertEq(dola.balanceOf(address(auction)), exactDolaIn); + auction.buyDBR(exactAssetIn, exactDbrOut, address(1)); + assertEq(asset.balanceOf(address(this)), 0); + assertEq(asset.balanceOf(address(auction)), exactAssetIn); assertEq(dbr.balanceOf(address(1)), exactDbrOut); assertEq(auction.dbrReserve(), newDbrReserve); - assertEq(auction.dolaReserve(), newDolaReserve); + assertEq(auction.assetReserve(), newAssetReserve); } } diff --git a/test/SaleHandler.t.sol b/test/DolaSaleHandler.t.sol similarity index 82% rename from test/SaleHandler.t.sol rename to test/DolaSaleHandler.t.sol index 01bad50..3ca75d6 100644 --- a/test/SaleHandler.t.sol +++ b/test/DolaSaleHandler.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.21; import {Test, console2} from "forge-std/Test.sol"; -import {SaleHandler} from "../src/SaleHandler.sol"; +import {DolaSaleHandler} from "../src/DolaSaleHandler.sol"; import {ERC20} from "./mocks/ERC20.sol"; contract MockAnDola { @@ -27,15 +27,15 @@ contract MockAnDola { contract SaleHandlerTest is Test { - ERC20 dola; + ERC20 asset; MockAnDola anDola; - SaleHandler handler; + DolaSaleHandler handler; function setUp() public { - dola = new ERC20(); + asset = new ERC20(); anDola = new MockAnDola(); - handler = new SaleHandler( - address(dola), + handler = new DolaSaleHandler( + address(asset), address(anDola), address(1), address(2) @@ -43,16 +43,16 @@ contract SaleHandlerTest is Test { } function test_constructor() public { - assertEq(address(handler.dola()), address(dola)); + assertEq(address(handler.asset()), address(asset)); assertEq(address(handler.anDola()), address(anDola)); assertEq(handler.borrower1(), address(1)); assertEq(handler.borrower2(), address(2)); - assertEq(dola.allowance(address(handler), address(anDola)), type(uint).max); + assertEq(asset.allowance(address(handler), address(anDola)), type(uint).max); } function test_onReceiveBorrower1(uint amount) public { amount = bound(amount, 1, type(uint).max / 2); - dola.mint(address(handler), amount); + asset.mint(address(handler), amount); anDola.setBorrowBalance(address(1), amount); handler.onReceive(); assertEq(anDola.borrower(), address(1)); @@ -61,7 +61,7 @@ contract SaleHandlerTest is Test { function test_onReceiveBorrower2(uint amount) public { amount = bound(amount, 1, type(uint).max / 2); - dola.mint(address(handler), amount); + asset.mint(address(handler), amount); anDola.setBorrowBalance(address(2), amount); handler.onReceive(); assertEq(anDola.borrower(), address(2)); diff --git a/test/Helper.t.sol b/test/Helper.t.sol index f995fb8..cea4841 100644 --- a/test/Helper.t.sol +++ b/test/Helper.t.sol @@ -9,72 +9,72 @@ import {ERC20} from "./mocks/ERC20.sol"; contract HelperTest is Test { Auction auction; - ERC20 dola; + ERC20 asset; ERC20 dbr; Helper helper; function setUp() public { - dola = new ERC20(); + asset = new ERC20(); dbr = new ERC20(); auction = new Auction( address(1), address(2), address(dbr), - address(dola), + address(asset), address(0), 1e18, 1e18 ); - helper = new Helper(address(auction), address(dola)); + helper = new Helper(address(auction), address(asset)); } function test_constructor() public { assertEq(address(helper.auction()), address(auction)); - assertEq(address(helper.dola()), address(dola)); + assertEq(address(helper.asset()), address(asset)); } - function test_getDbrOut(uint dolaIn) public { - dolaIn = bound(dolaIn, 1, (type(uint).max - auction.dolaReserve()) / auction.dbrReserve()); - uint newDbrReserve = auction.dbrReserve() - helper.getDbrOut(dolaIn); - uint newDolaReserve = auction.dolaReserve() + dolaIn; - assertGe(newDbrReserve * newDolaReserve, auction.dbrReserve() * auction.dolaReserve()); + function test_getDbrOut(uint assetIn) public { + assetIn = bound(assetIn, 1, (type(uint).max - auction.assetReserve()) / auction.dbrReserve()); + uint newDbrReserve = auction.dbrReserve() - helper.getDbrOut(assetIn); + uint newAssetReserve = auction.assetReserve() + assetIn; + assertGe(newDbrReserve * newAssetReserve, auction.dbrReserve() * auction.assetReserve()); } - function test_getDolaIn(uint dbrOut) public { + function test_getAssetIn(uint dbrOut) public { dbrOut = bound(dbrOut, 1, auction.dbrReserve() - 1); uint newDbrReserve = auction.dbrReserve() - dbrOut; - uint newDolaReserve = auction.dolaReserve() + helper.getDolaIn(dbrOut); - assertGe(newDbrReserve * newDolaReserve, auction.dbrReserve() * auction.dolaReserve()); + uint newAssetReserve = auction.assetReserve() + helper.getAssetIn(dbrOut); + assertGe(newDbrReserve * newAssetReserve, auction.dbrReserve() * auction.assetReserve()); } - function test_swapExactDolaForDbr(uint dolaIn) public { - dolaIn = bound(dolaIn, 1, (type(uint).max - auction.dolaReserve()) / auction.dbrReserve()); - uint dbrOut = helper.getDbrOut(dolaIn); + function test_swapExactAssetForDbr(uint assetIn) public { + assetIn = bound(assetIn, 1, (type(uint).max - auction.assetReserve()) / auction.dbrReserve()); + uint dbrOut = helper.getDbrOut(assetIn); uint newDbrReserve = auction.dbrReserve() - dbrOut; - uint newDolaReserve = auction.dolaReserve() + dolaIn; - dola.mint(address(this), dolaIn); - dola.approve(address(helper), dolaIn); - helper.swapExactDolaForDbr(dolaIn, dbrOut); + uint newAssetReserve = auction.assetReserve() + assetIn; + asset.mint(address(this), assetIn); + asset.approve(address(helper), assetIn); + helper.swapExactAssetForDbr(assetIn, dbrOut); assertEq(auction.dbrReserve(), newDbrReserve); - assertEq(auction.dolaReserve(), newDolaReserve); + assertEq(auction.assetReserve(), newAssetReserve); assertEq(dbr.balanceOf(address(this)), dbrOut); - assertEq(dola.balanceOf(address(this)), 0); - assertEq(dola.balanceOf(address(auction)), dolaIn); + assertEq(asset.balanceOf(address(this)), 0); + assertEq(asset.balanceOf(address(auction)), assetIn); } - function test_swapDolaForExactDbr(uint dbrOut) public { + function test_swapAssetForExactDbr(uint dbrOut) public { dbrOut = bound(dbrOut, 1, auction.dbrReserve() - 1); - uint dolaIn = helper.getDolaIn(dbrOut); + uint assetIn = helper.getAssetIn(dbrOut); uint newDbrReserve = auction.dbrReserve() - dbrOut; - uint newDolaReserve = auction.dolaReserve() + dolaIn; - dola.mint(address(this), dolaIn); - dola.approve(address(helper), dolaIn); - helper.swapDolaForExactDbr(dbrOut, dolaIn); + uint newAssetReserve = auction.assetReserve() + assetIn; + asset.mint(address(this), assetIn); + asset.approve(address(helper), assetIn); + helper.swapAssetForExactDbr(dbrOut, assetIn); assertEq(auction.dbrReserve(), newDbrReserve); - assertEq(auction.dolaReserve(), newDolaReserve); + assertEq(auction.assetReserve(), newAssetReserve); assertEq(dbr.balanceOf(address(this)), dbrOut); - assertEq(dola.balanceOf(address(this)), 0); - assertEq(dola.balanceOf(address(auction)), dolaIn); + assertEq(asset.balanceOf(address(this)), 0); + assertEq(asset.balanceOf(address(auction)), assetIn); } } \ No newline at end of file From 3e577099fde9930c033f4c2105d30faae20fafc3 Mon Sep 17 00:00:00 2001 From: nourharidy Date: Tue, 28 Oct 2025 09:46:39 +0300 Subject: [PATCH 3/5] add minDbrRatePerYear --- src/Auction.sol | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Auction.sol b/src/Auction.sol index fa1f340..652b533 100644 --- a/src/Auction.sol +++ b/src/Auction.sol @@ -26,7 +26,8 @@ contract Auction { uint public assetReserve; uint public dbrReserve; uint public dbrRatePerYear; - uint public maxDbrRatePerYear; + uint public minDbrRatePerYear; + uint public maxDbrRatePerYear = type(uint).max; uint public lastUpdate; constructor ( @@ -83,6 +84,7 @@ contract Auction { function setSaleHandler(address _saleHandler) external onlyGov { saleHandler = ISaleHandler(_saleHandler); } function setMaxDbrRatePerYear(uint _maxRate) external onlyGov updateReserves { + require(_maxRate >= minDbrRatePerYear, "Max below min"); maxDbrRatePerYear = _maxRate; emit MaxRateUpdate(_maxRate); if(dbrRatePerYear > _maxRate) { @@ -91,12 +93,24 @@ contract Auction { } } + function setMinDbrRatePerYear(uint _minRate) external onlyGov updateReserves { + require(_minRate <= maxDbrRatePerYear, "Min above max"); + minDbrRatePerYear = _minRate; + emit MinRateUpdate(_minRate); + if(dbrRatePerYear < _minRate) { + dbrRatePerYear = _minRate; + emit RateUpdate(_minRate); + } + } + function setDbrRatePerYear(uint _rate) external onlyGovOrOperator updateReserves { require(_rate <= maxDbrRatePerYear, "Rate exceeds max"); + require(_rate >= minDbrRatePerYear, "Rate below min"); dbrRatePerYear = _rate; emit RateUpdate(_rate); } + // changes K to preserve the ratio (price) function setAssetReserve(uint _assetReserve) external onlyGov updateReserves { require(_assetReserve > 0, "Asset reserve must be positive"); uint newDbrReserve = _assetReserve * dbrReserve / assetReserve; @@ -105,6 +119,7 @@ contract Auction { dbrReserve = newDbrReserve; } + // changes K to preserve the ratio (price) function setDbrReserve(uint _dbrReserve) external onlyGov updateReserves { require(_dbrReserve > 0, "DBR reserve must be positive"); uint newAssetReserve = _dbrReserve * assetReserve / dbrReserve; @@ -148,4 +163,5 @@ contract Auction { event Buy(address indexed caller, address indexed to, uint assetIn, uint dbrOut); event RateUpdate(uint newRate); event MaxRateUpdate(uint newMaxRate); + event MinRateUpdate(uint newMinRate); } From 76bc5cf10bea1800752f26a00a1b7bfd8da2d517 Mon Sep 17 00:00:00 2001 From: nourharidy Date: Tue, 28 Oct 2025 09:50:54 +0300 Subject: [PATCH 4/5] add sendToGov() --- src/Auction.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Auction.sol b/src/Auction.sol index 652b533..cb7a999 100644 --- a/src/Auction.sol +++ b/src/Auction.sol @@ -156,6 +156,14 @@ contract Auction { saleHandler.onReceive(); } + // only if no sale handler is set + function sendToGov() public { + require(address(saleHandler) == address(0), "Sale handler set"); + uint bal = asset.balanceOf(address(this)); + require(bal > 0, "No asset to send"); + asset.transfer(gov, bal); + } + function sweep(address token, address destination, uint amount) external onlyGov { IERC20(token).transfer(destination, amount); } From e11ecb3b3fdce446b3f0deed054cc6f2fdd622c3 Mon Sep 17 00:00:00 2001 From: nourharidy Date: Tue, 28 Oct 2025 16:57:08 +0300 Subject: [PATCH 5/5] fix tests and scripts --- script/AuctionMainnetDeployer.s.sol | 5 +- ...l => DolaSaleHandlerMainnetDeployer.s.sol} | 0 test/Auction.t.sol | 126 ++++++++++++++++-- 3 files changed, 122 insertions(+), 9 deletions(-) rename script/{DolaSaleHandlerMainnetDeployer.s copy.sol => DolaSaleHandlerMainnetDeployer.s.sol} (100%) diff --git a/script/AuctionMainnetDeployer.s.sol b/script/AuctionMainnetDeployer.s.sol index 7df386d..509619e 100644 --- a/script/AuctionMainnetDeployer.s.sol +++ b/script/AuctionMainnetDeployer.s.sol @@ -11,6 +11,9 @@ contract AuctionMainnetDeployerScript is Script { function run() public { vm.startBroadcast(); + // Optional: specify a handler address to deploy with + address handler = address(0); + address gov = 0x926dF14a23BE491164dCF93f4c468A50ef659D5B; address fedChair = 0x8F97cCA30Dbe80e7a8B462F1dD1a51C32accDfC8; address asset = 0x865377367054516e17014CcdED1e7d814EDC9ce4; @@ -25,7 +28,7 @@ contract AuctionMainnetDeployerScript is Script { fedChair, dbr, asset, - address(0), + handler, assetReserve, dbrReserve ); diff --git a/script/DolaSaleHandlerMainnetDeployer.s copy.sol b/script/DolaSaleHandlerMainnetDeployer.s.sol similarity index 100% rename from script/DolaSaleHandlerMainnetDeployer.s copy.sol rename to script/DolaSaleHandlerMainnetDeployer.s.sol diff --git a/test/Auction.t.sol b/test/Auction.t.sol index 952c07a..21b6c9d 100644 --- a/test/Auction.t.sol +++ b/test/Auction.t.sol @@ -47,6 +47,9 @@ contract AuctionTest is Test { assertEq(address(auction.asset()), address(asset)); assertEq(auction.assetReserve(), 1e18); assertEq(auction.dbrReserve(), 1e18); + assertEq(auction.dbrRatePerYear(), 0); + assertEq(auction.minDbrRatePerYear(), 0); + assertEq(auction.maxDbrRatePerYear(), type(uint).max); } function test_getCurrentReserves() public { @@ -94,30 +97,137 @@ contract AuctionTest is Test { vm.expectRevert("onlyGov"); auction.setMaxDbrRatePerYear(1e18); vm.startPrank(gov); + + // Test setting max rate auction.setMaxDbrRatePerYear(1e18); assertEq(auction.maxDbrRatePerYear(), 1e18); + + // Test that current rate can be set to max auction.setDbrRatePerYear(1e18); assertEq(auction.dbrRatePerYear(), 1e18); - auction.setMaxDbrRatePerYear(0); - assertEq(auction.maxDbrRatePerYear(), 0); - assertEq(auction.dbrRatePerYear(), 0); + + // Test that setting max below current rate adjusts current rate + auction.setMaxDbrRatePerYear(0.5e18); + assertEq(auction.maxDbrRatePerYear(), 0.5e18); + assertEq(auction.dbrRatePerYear(), 0.5e18); + + // Test that setting max below min rate fails + auction.setMinDbrRatePerYear(0.3e18); + vm.expectRevert("Max below min"); + auction.setMaxDbrRatePerYear(0.2e18); + } + + function test_setMinDbrRatePerYear() public { + vm.expectRevert("onlyGov"); + auction.setMinDbrRatePerYear(1e18); + vm.startPrank(gov); + + // Test setting min rate + auction.setMinDbrRatePerYear(0.1e18); + assertEq(auction.minDbrRatePerYear(), 0.1e18); + + // Test that setting min above current rate adjusts current rate + auction.setMinDbrRatePerYear(0.5e18); + assertEq(auction.minDbrRatePerYear(), 0.5e18); + assertEq(auction.dbrRatePerYear(), 0.5e18); + + // Test that setting min above max rate fails + auction.setMaxDbrRatePerYear(1e18); + vm.expectRevert("Min above max"); + auction.setMinDbrRatePerYear(2e18); + + // Test that setting min rate works when below max + auction.setMinDbrRatePerYear(0.3e18); + assertEq(auction.minDbrRatePerYear(), 0.3e18); } function test_setDbrRatePerYear() public { vm.expectRevert("onlyGov"); auction.setDbrRatePerYear(1e18); vm.startPrank(gov); - vm.expectRevert("Rate exceeds max"); - auction.setDbrRatePerYear(1e18); - assertEq(auction.dbrRatePerYear(), 0); + + // Set up min and max bounds + auction.setMinDbrRatePerYear(0.1e18); auction.setMaxDbrRatePerYear(1e18); - auction.setDbrRatePerYear(1e18); - assertEq(auction.dbrRatePerYear(), 1e18); + + // Test setting rate within bounds + auction.setDbrRatePerYear(0.5e18); + assertEq(auction.dbrRatePerYear(), 0.5e18); + + // Test setting rate above max fails + vm.expectRevert("Rate exceeds max"); + auction.setDbrRatePerYear(2e18); + + // Test setting rate below min fails + vm.expectRevert("Rate below min"); + auction.setDbrRatePerYear(0.05e18); + + // Test operator can also set rate vm.startPrank(operator); + auction.setDbrRatePerYear(0.8e18); + assertEq(auction.dbrRatePerYear(), 0.8e18); + + // Test operator cannot set rate above max + vm.expectRevert("Rate exceeds max"); + auction.setDbrRatePerYear(2e18); + + // Test operator cannot set rate below min + vm.expectRevert("Rate below min"); + auction.setDbrRatePerYear(0.05e18); + } + + function test_dbrRateBoundaryConditions() public { + vm.startPrank(gov); + + // Test setting min and max to same value + auction.setMinDbrRatePerYear(0.5e18); + auction.setMaxDbrRatePerYear(0.5e18); + assertEq(auction.minDbrRatePerYear(), 0.5e18); + assertEq(auction.maxDbrRatePerYear(), 0.5e18); + assertEq(auction.dbrRatePerYear(), 0.5e18); + + // Test that rate can only be set to the exact min/max value + auction.setDbrRatePerYear(0.5e18); + assertEq(auction.dbrRatePerYear(), 0.5e18); + + // Test that any other value fails + vm.expectRevert("Rate exceeds max"); + auction.setDbrRatePerYear(0.51e18); + vm.expectRevert("Rate below min"); + auction.setDbrRatePerYear(0.49e18); + + // Test that setting max to 0 fails when min is above 0 + vm.expectRevert("Max below min"); + auction.setMaxDbrRatePerYear(0); + + // Test that min can be set to 0 first + auction.setMinDbrRatePerYear(0); + assertEq(auction.minDbrRatePerYear(), 0); + + // Now test that max can be set to 0 + auction.setMaxDbrRatePerYear(0); + assertEq(auction.maxDbrRatePerYear(), 0); + assertEq(auction.dbrRatePerYear(), 0); + + // Test that rate can be set to 0 auction.setDbrRatePerYear(0); assertEq(auction.dbrRatePerYear(), 0); } + function test_dbrRateEvents() public { + vm.startPrank(gov); + + // Test that events are emitted (simplified test) + auction.setMinDbrRatePerYear(0.1e18); + auction.setMaxDbrRatePerYear(1e18); + auction.setDbrRatePerYear(0.5e18); + + // Verify the state changes + assertEq(auction.minDbrRatePerYear(), 0.1e18); + assertEq(auction.maxDbrRatePerYear(), 1e18); + assertEq(auction.dbrRatePerYear(), 0.5e18); + } + function test_setAssetReserve() public { vm.expectRevert("onlyGov"); auction.setAssetReserve(1e19);