diff --git a/contracts/p0/BackingManager.sol b/contracts/p0/BackingManager.sol index 00feb14b2..de11a8a82 100644 --- a/contracts/p0/BackingManager.sol +++ b/contracts/p0/BackingManager.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.19; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/math/Math.sol"; import "./mixins/TradingLib.sol"; import "./mixins/Trading.sol"; import "../interfaces/IAsset.sol"; @@ -65,6 +66,8 @@ contract BackingManagerP0 is TradingP0, IBackingManager { trade = super.settleTrade(sell); delete tokensOut[trade.sell()]; + tradeEnd[trade.KIND()] = uint48(Math.min(tradeEnd[trade.KIND()], block.timestamp)); + // if the settler is the trade contract itself, try chaining with another rebalance() if (_msgSender() == address(trade)) { // solhint-disable-next-line no-empty-blocks diff --git a/contracts/p1/BackingManager.sol b/contracts/p1/BackingManager.sol index a5837bc6b..2129eab87 100644 --- a/contracts/p1/BackingManager.sol +++ b/contracts/p1/BackingManager.sol @@ -86,6 +86,9 @@ contract BackingManagerP1 is TradingP1, IBackingManager { delete tokensOut[sell]; trade = super.settleTrade(sell); // nonReentrant + TradeKind kind = trade.KIND(); + if (tradeEnd[kind] > block.timestamp) tradeEnd[kind] = uint48(block.timestamp); + // if the settler is the trade contract itself, try chaining with another rebalance() if (_msgSender() == address(trade)) { // solhint-disable-next-line no-empty-blocks diff --git a/test/Recollateralization.test.ts b/test/Recollateralization.test.ts index d2d32b059..d19467fbb 100644 --- a/test/Recollateralization.test.ts +++ b/test/Recollateralization.test.ts @@ -3412,11 +3412,36 @@ describe(`Recollateralization - P${IMPLEMENTATION}`, () => { expect(await trade2.canSettle()).to.equal(false) // Bid + settle RSR auction + await expect(await router.connect(addr1).bid(trade2.address, addr1.address)).to.emit( + backingManager, + 'TradeSettled' + ) + }) + + it('and be able to continue rebalance immediately -- regression test 09/05/2024', async () => { + // Context: https://github.com/code-423n4/2024-07-reserve-findings/issues/6 + + await token1.connect(addr1).approve(trade2.address, initialBal) + + // Advance to midpoint of auction + await advanceToTimestamp((await getLatestBlockTimestamp()) + 900) + expect(await trade2.status()).to.equal(1) // TradeStatus.OPEN + expect(await trade2.canSettle()).to.equal(false) + // Bid + settle RSR auction await expect(await router.connect(addr1).bid(trade2.address, addr1.address)).to.emit( backingManager, 'TradeSettled' ) + expect(await broker.dutchTradeDisabled(token1.address)).to.equal(false) + + // Should be able to immediately continue + const amt = await token1.balanceOf(backingManager.address) + await token1.burn(backingManager.address, amt) + + // Should not revert, if we were to continue + await backingManager.callStatic.rebalance(TradeKind.DUTCH_AUCTION) + await token1.mint(backingManager.address, amt) }) it('via fallback to Batch Auction', async () => {