From 1078d09d5e834e63e23713cb83c4d39839e20935 Mon Sep 17 00:00:00 2001 From: gzeon Date: Thu, 24 Oct 2024 17:11:19 +0900 Subject: [PATCH] Revert "chore: format" This reverts commit 738c3dcab3a89a57b86aa2097cb22a1fb70842fb. --- src/express-lane-auction/Balance.sol | 15 +- src/express-lane-auction/Burner.sol | 9 +- src/express-lane-auction/ELCRound.sol | 17 +- .../ExpressLaneAuction.sol | 168 ++++---- .../IExpressLaneAuction.sol | 87 ++-- src/express-lane-auction/RoundTimingInfo.sol | 41 +- test/foundry/ExpressLaneAuction.t.sol | 375 ++++++++++++------ test/foundry/ExpressLaneBalance.t.sol | 31 +- test/foundry/ExpressLaneBurner.t.sol | 5 +- test/foundry/ExpressLaneELCRound.t.sol | 17 +- test/foundry/ExpressLaneRoundTiming.t.sol | 105 +++-- 11 files changed, 494 insertions(+), 376 deletions(-) diff --git a/src/express-lane-auction/Balance.sol b/src/express-lane-auction/Balance.sol index ad7ca5239..c9433b99a 100644 --- a/src/express-lane-auction/Balance.sol +++ b/src/express-lane-auction/Balance.sol @@ -34,10 +34,11 @@ library BalanceLib { /// of this account is returned. Otherwise 0. /// @param bal The balance to query /// @param round The round to check the withdrawable balance in - function withdrawableBalanceAtRound( - Balance storage bal, - uint64 round - ) internal view returns (uint256) { + function withdrawableBalanceAtRound(Balance storage bal, uint64 round) + internal + view + returns (uint256) + { return round >= bal.withdrawalRound ? bal.balance : 0; } @@ -71,7 +72,11 @@ library BalanceLib { /// @param round The round to check withdrawals against. A withdrawal after this round will be ignored /// and the balance reduced anyway, withdrawals before or on this round will be respected /// and the reduce will revert - function reduce(Balance storage bal, uint256 amount, uint64 round) internal { + function reduce( + Balance storage bal, + uint256 amount, + uint64 round + ) internal { uint256 balRnd = balanceAtRound(bal, round); // we add a zero check since it's possible for the amount to be zero // but even in that case the user must have some balance diff --git a/src/express-lane-auction/Burner.sol b/src/express-lane-auction/Burner.sol index 3ee9d4b35..e3fe3fb80 100644 --- a/src/express-lane-auction/Burner.sol +++ b/src/express-lane-auction/Burner.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; -import {ERC20BurnableUpgradeable} from - "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; +import { + ERC20BurnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; import "./Errors.sol"; /// @notice A simple contract that can burn any tokens that are transferred to it @@ -10,9 +11,7 @@ import "./Errors.sol"; contract Burner { ERC20BurnableUpgradeable public immutable token; - constructor( - address _token - ) { + constructor(address _token) { if (_token == address(0)) { revert ZeroAddress(); } diff --git a/src/express-lane-auction/ELCRound.sol b/src/express-lane-auction/ELCRound.sol index b1483e8b6..5cc9a25a0 100644 --- a/src/express-lane-auction/ELCRound.sol +++ b/src/express-lane-auction/ELCRound.sol @@ -19,9 +19,11 @@ library LatestELCRoundsLib { /// @param rounds The stored resolved rounds /// @return The last resolved elc round /// @return The index of that last resolved round within the supplied array - function latestELCRound( - ELCRound[2] storage rounds - ) internal view returns (ELCRound storage, uint8) { + function latestELCRound(ELCRound[2] storage rounds) + internal + view + returns (ELCRound storage, uint8) + { ELCRound storage latestRound = rounds[0]; uint8 index = 0; if (latestRound.round < rounds[1].round) { @@ -34,10 +36,11 @@ library LatestELCRoundsLib { /// @notice Finds the elc round that matches the supplied round. Reverts if no matching round found. /// @param latestResolvedRounds The resolved elc rounds /// @param round The round number to find a resolved round for - function resolvedRound( - ELCRound[2] storage latestResolvedRounds, - uint64 round - ) internal view returns (ELCRound storage) { + function resolvedRound(ELCRound[2] storage latestResolvedRounds, uint64 round) + internal + view + returns (ELCRound storage) + { if (latestResolvedRounds[0].round == round) { return latestResolvedRounds[0]; } else if (latestResolvedRounds[1].round == round) { diff --git a/src/express-lane-auction/ExpressLaneAuction.sol b/src/express-lane-auction/ExpressLaneAuction.sol index 5e9e72b91..2ede3b194 100644 --- a/src/express-lane-auction/ExpressLaneAuction.sol +++ b/src/express-lane-auction/ExpressLaneAuction.sol @@ -5,14 +5,16 @@ import "./Errors.sol"; import {Balance, BalanceLib} from "./Balance.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import {AccessControlEnumerableUpgradeable} from - "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; +import { + AccessControlEnumerableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; import {DelegateCallAware} from "../libraries/DelegateCallAware.sol"; import {IExpressLaneAuction, Bid, InitArgs, Transferor} from "./IExpressLaneAuction.sol"; import {ELCRound, LatestELCRoundsLib} from "./ELCRound.sol"; import {RoundTimingInfo, RoundTimingInfoLib} from "./RoundTimingInfo.sol"; -import {EIP712Upgradeable} from - "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; +import { + EIP712Upgradeable +} from "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; /// @title ExpressLaneAuction /// @notice The express lane allows a controller to submit undelayed transactions to the sequencer @@ -74,9 +76,7 @@ contract ExpressLaneAuction is mapping(address => Transferor) public transferorOf; /// @inheritdoc IExpressLaneAuction - function initialize( - InitArgs calldata args - ) public initializer onlyDelegated { + function initialize(InitArgs calldata args) public initializer onlyDelegated { __AccessControl_init(); __EIP712_init("ExpressLaneAuction", "1"); @@ -108,7 +108,10 @@ contract ExpressLaneAuction is // the following roles are expected to be controlled by hot wallets, so we add // additional custom admin role for each of them to allow for key rotation management setRoleAndAdmin( - AUCTIONEER_ROLE, args._auctioneer, AUCTIONEER_ADMIN_ROLE, args._auctioneerAdmin + AUCTIONEER_ROLE, + args._auctioneer, + AUCTIONEER_ADMIN_ROLE, + args._auctioneerAdmin ); setRoleAndAdmin( RESERVE_SETTER_ROLE, @@ -143,28 +146,22 @@ contract ExpressLaneAuction is /// @inheritdoc IExpressLaneAuction function isReserveBlackout() external view returns (bool) { - (ELCRound storage lastRoundResolved,) = latestResolvedRounds.latestELCRound(); + (ELCRound storage lastRoundResolved, ) = latestResolvedRounds.latestELCRound(); return roundTimingInfo.isReserveBlackout(lastRoundResolved.round); } /// @inheritdoc IExpressLaneAuction - function roundTimestamps( - uint64 round - ) external view returns (uint64, uint64) { + function roundTimestamps(uint64 round) external view returns (uint64, uint64) { return roundTimingInfo.roundTimestamps(round); } /// @inheritdoc IExpressLaneAuction - function setBeneficiary( - address newBeneficiary - ) external onlyRole(BENEFICIARY_SETTER_ROLE) { + function setBeneficiary(address newBeneficiary) external onlyRole(BENEFICIARY_SETTER_ROLE) { emit SetBeneficiary(beneficiary, newBeneficiary); beneficiary = newBeneficiary; } - function _setReservePrice( - uint256 newReservePrice - ) private { + function _setReservePrice(uint256 newReservePrice) private { if (newReservePrice < minReservePrice) { revert ReservePriceTooLow(newReservePrice, minReservePrice); } @@ -173,9 +170,7 @@ contract ExpressLaneAuction is reservePrice = newReservePrice; } - function setRoundTimingInfoInternal( - RoundTimingInfo calldata newRoundTimingInfo - ) internal { + function setRoundTimingInfoInternal(RoundTimingInfo calldata newRoundTimingInfo) internal { // auction closing seconds of 0 wouldnt make sense as it would then be impossible to close the round // due to the check below this also causes round duration > 0 if (newRoundTimingInfo.auctionClosingSeconds == 0) { @@ -191,8 +186,8 @@ contract ExpressLaneAuction is // the same check as in initialization - reserve submission and auction closing are non overlapping // sub sections of a round, so must fit within it if ( - newRoundTimingInfo.reserveSubmissionSeconds + newRoundTimingInfo.auctionClosingSeconds - > newRoundTimingInfo.roundDurationSeconds + newRoundTimingInfo.reserveSubmissionSeconds + newRoundTimingInfo.auctionClosingSeconds > + newRoundTimingInfo.roundDurationSeconds ) { revert RoundDurationTooShort(); } @@ -208,9 +203,10 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function setRoundTimingInfo( - RoundTimingInfo calldata newRoundTimingInfo - ) external onlyRole(ROUND_TIMING_SETTER_ROLE) { + function setRoundTimingInfo(RoundTimingInfo calldata newRoundTimingInfo) + external + onlyRole(ROUND_TIMING_SETTER_ROLE) + { RoundTimingInfo memory currentRoundTimingInfo = roundTimingInfo; uint64 currentCurrentRound = currentRoundTimingInfo.currentRound(); uint64 newCurrentRound = newRoundTimingInfo.currentRound(); @@ -220,8 +216,8 @@ contract ExpressLaneAuction is revert InvalidNewRound(currentCurrentRound, newCurrentRound); } - (uint64 currentStart,) = currentRoundTimingInfo.roundTimestamps(currentCurrentRound + 1); - (uint64 newStart,) = newRoundTimingInfo.roundTimestamps(newCurrentRound + 1); + (uint64 currentStart, ) = currentRoundTimingInfo.roundTimestamps(currentCurrentRound + 1); + (uint64 newStart, ) = newRoundTimingInfo.roundTimestamps(newCurrentRound + 1); // we also ensure that the current round end time/next round start time, will not change if (currentStart != newStart) { revert InvalidNewStart(currentStart, newStart); @@ -231,9 +227,10 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function setMinReservePrice( - uint256 newMinReservePrice - ) external onlyRole(MIN_RESERVE_SETTER_ROLE) { + function setMinReservePrice(uint256 newMinReservePrice) + external + onlyRole(MIN_RESERVE_SETTER_ROLE) + { emit SetMinReservePrice(minReservePrice, newMinReservePrice); minReservePrice = newMinReservePrice; @@ -244,10 +241,8 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function setReservePrice( - uint256 newReservePrice - ) external onlyRole(RESERVE_SETTER_ROLE) { - (ELCRound storage lastRoundResolved,) = latestResolvedRounds.latestELCRound(); + function setReservePrice(uint256 newReservePrice) external onlyRole(RESERVE_SETTER_ROLE) { + (ELCRound storage lastRoundResolved, ) = latestResolvedRounds.latestELCRound(); if (roundTimingInfo.isReserveBlackout(lastRoundResolved.round)) { revert ReserveBlackout(); } @@ -256,9 +251,7 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function balanceOf( - address account - ) external view returns (uint256) { + function balanceOf(address account) external view returns (uint256) { return _balanceOf[account].balanceAtRound(roundTimingInfo.currentRound()); } @@ -271,17 +264,16 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function withdrawableBalance( - address account - ) external view returns (uint256) { + function withdrawableBalance(address account) external view returns (uint256) { return _balanceOf[account].withdrawableBalanceAtRound(roundTimingInfo.currentRound()); } /// @inheritdoc IExpressLaneAuction - function withdrawableBalanceAtRound( - address account, - uint64 round - ) external view returns (uint256) { + function withdrawableBalanceAtRound(address account, uint64 round) + external + view + returns (uint256) + { if (round < roundTimingInfo.currentRound()) { revert RoundTooOld(round, roundTimingInfo.currentRound()); } @@ -289,9 +281,7 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function deposit( - uint256 amount - ) external { + function deposit(uint256 amount) external { _balanceOf[msg.sender].increase(amount); biddingToken.safeTransferFrom(msg.sender, address(this), amount); emit Deposit(msg.sender, amount); @@ -310,8 +300,9 @@ contract ExpressLaneAuction is /// @inheritdoc IExpressLaneAuction function finalizeWithdrawal() external { - uint256 amountReduced = - _balanceOf[msg.sender].finalizeWithdrawal(roundTimingInfo.currentRound()); + uint256 amountReduced = _balanceOf[msg.sender].finalizeWithdrawal( + roundTimingInfo.currentRound() + ); biddingToken.safeTransfer(msg.sender, amountReduced); emit WithdrawalFinalized(msg.sender, amountReduced); } @@ -387,19 +378,21 @@ contract ExpressLaneAuction is address expressLaneController, uint256 amount ) public view returns (bytes32) { - return _hashTypedDataV4( - keccak256(abi.encode(BID_DOMAIN, round, expressLaneController, amount)) - ); + return + _hashTypedDataV4( + keccak256(abi.encode(BID_DOMAIN, round, expressLaneController, amount)) + ); } /// @notice Recover the signing address of the provided bid, and check that that address has enough funds to fulfil that bid /// Returns the signing address and the bid hash that was signed /// @param bid The bid to recover the signing address of /// @param biddingForRound The round the bid is for the control of - function recoverAndCheckBalance( - Bid memory bid, - uint64 biddingForRound - ) internal view returns (address, bytes32) { + function recoverAndCheckBalance(Bid memory bid, uint64 biddingForRound) + internal + view + returns (address, bytes32) + { bytes32 bidHash = getBidHash(biddingForRound, bid.expressLaneController, bid.amount); address bidder = bidHash.recover(bid.signature); // we are always bidding for in the current round for the next round @@ -407,7 +400,9 @@ contract ExpressLaneAuction is // always check that the bidder has as much as they're claiming if (_balanceOf[bidder].balanceAtRound(curRnd) < bid.amount) { revert InsufficientBalanceAcc( - bidder, bid.amount, _balanceOf[bidder].balanceAtRound(curRnd) + bidder, + bid.amount, + _balanceOf[bidder].balanceAtRound(curRnd) ); } @@ -415,9 +410,10 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function resolveSingleBidAuction( - Bid calldata firstPriceBid - ) external onlyRole(AUCTIONEER_ROLE) { + function resolveSingleBidAuction(Bid calldata firstPriceBid) + external + onlyRole(AUCTIONEER_ROLE) + { RoundTimingInfo memory info = roundTimingInfo; if (!info.isAuctionRoundClosed()) { revert AuctionNotClosed(); @@ -429,7 +425,7 @@ contract ExpressLaneAuction is uint64 biddingInRound = info.currentRound(); uint64 biddingForRound = biddingInRound + 1; - (address firstPriceBidder,) = recoverAndCheckBalance(firstPriceBid, biddingForRound); + (address firstPriceBidder, ) = recoverAndCheckBalance(firstPriceBid, biddingForRound); (uint64 roundStart, uint64 roundEnd) = info.roundTimestamps(biddingForRound); resolveAuction( @@ -444,10 +440,10 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function resolveMultiBidAuction( - Bid calldata firstPriceBid, - Bid calldata secondPriceBid - ) external onlyRole(AUCTIONEER_ROLE) { + function resolveMultiBidAuction(Bid calldata firstPriceBid, Bid calldata secondPriceBid) + external + onlyRole(AUCTIONEER_ROLE) + { RoundTimingInfo memory info = roundTimingInfo; if (!info.isAuctionRoundClosed()) { revert AuctionNotClosed(); @@ -466,10 +462,14 @@ contract ExpressLaneAuction is uint64 biddingForRound = biddingInRound + 1; // check the signatures and balances of both bids // even the second price bid must have the balance it's claiming - (address firstPriceBidder, bytes32 firstBidHash) = - recoverAndCheckBalance(firstPriceBid, biddingForRound); - (address secondPriceBidder, bytes32 secondBidHash) = - recoverAndCheckBalance(secondPriceBid, biddingForRound); + (address firstPriceBidder, bytes32 firstBidHash) = recoverAndCheckBalance( + firstPriceBid, + biddingForRound + ); + (address secondPriceBidder, bytes32 secondBidHash) = recoverAndCheckBalance( + secondPriceBid, + biddingForRound + ); // The bidders must be different so that our balance check isnt fooled into thinking // that the same balance is valid for both the first and second bid @@ -481,9 +481,9 @@ contract ExpressLaneAuction is // although we include equality in the check we know this isnt possible due // to the check above that ensures the first price bidder and second price bidder are different if ( - firstPriceBid.amount == secondPriceBid.amount - && uint256(keccak256(abi.encodePacked(firstPriceBidder, firstBidHash))) - < uint256(keccak256(abi.encodePacked(secondPriceBidder, secondBidHash))) + firstPriceBid.amount == secondPriceBid.amount && + uint256(keccak256(abi.encodePacked(firstPriceBidder, firstBidHash))) < + uint256(keccak256(abi.encodePacked(secondPriceBidder, secondBidHash))) ) { revert TieBidsWrongOrder(); } @@ -501,14 +501,12 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function setTransferor( - Transferor calldata transferor - ) external { + function setTransferor(Transferor calldata transferor) external { // if a transferor has already been set, it may be fixed until a future round Transferor storage currentTransferor = transferorOf[msg.sender]; if ( - currentTransferor.addr != address(0) - && currentTransferor.fixedUntilRound > roundTimingInfo.currentRound() + currentTransferor.addr != address(0) && + currentTransferor.fixedUntilRound > roundTimingInfo.currentRound() ) { revert FixedTransferor(currentTransferor.fixedUntilRound); } @@ -519,10 +517,9 @@ contract ExpressLaneAuction is } /// @inheritdoc IExpressLaneAuction - function transferExpressLaneController( - uint64 round, - address newExpressLaneController - ) external { + function transferExpressLaneController(uint64 round, address newExpressLaneController) + external + { // past rounds cannot be transferred RoundTimingInfo memory info = roundTimingInfo; uint64 curRnd = info.currentRound(); @@ -560,8 +557,9 @@ contract ExpressLaneAuction is /// @inheritdoc IExpressLaneAuction function resolvedRounds() external view returns (ELCRound memory, ELCRound memory) { - return latestResolvedRounds[0].round > latestResolvedRounds[1].round - ? (latestResolvedRounds[0], latestResolvedRounds[1]) - : (latestResolvedRounds[1], latestResolvedRounds[0]); + return + latestResolvedRounds[0].round > latestResolvedRounds[1].round + ? (latestResolvedRounds[0], latestResolvedRounds[1]) + : (latestResolvedRounds[1], latestResolvedRounds[0]); } } diff --git a/src/express-lane-auction/IExpressLaneAuction.sol b/src/express-lane-auction/IExpressLaneAuction.sol index 7540a8940..8d4452bf1 100644 --- a/src/express-lane-auction/IExpressLaneAuction.sol +++ b/src/express-lane-auction/IExpressLaneAuction.sol @@ -4,10 +4,12 @@ pragma solidity ^0.8.0; import {IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {RoundTimingInfo} from "./RoundTimingInfo.sol"; import {ELCRound} from "./ELCRound.sol"; -import {IAccessControlEnumerableUpgradeable} from - "@openzeppelin/contracts-upgradeable/access/IAccessControlEnumerableUpgradeable.sol"; -import {IERC165Upgradeable} from - "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol"; +import { + IAccessControlEnumerableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/IAccessControlEnumerableUpgradeable.sol"; +import { + IERC165Upgradeable +} from "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol"; /// @notice A bid to control the express lane for a specific round struct Bid { @@ -76,7 +78,9 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// @param withdrawalAmount The amount beind withdrawn /// @param roundWithdrawable The round the funds will become withdrawable in event WithdrawalInitiated( - address indexed account, uint256 withdrawalAmount, uint256 roundWithdrawable + address indexed account, + uint256 withdrawalAmount, + uint256 roundWithdrawable ); /// @notice An account has finalized a withdrawal @@ -126,7 +130,9 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// @param transferor The transferor chosen /// @param fixedUntilRound The round until which this transferor is fixed for this controller event SetTransferor( - address indexed expressLaneController, address indexed transferor, uint64 fixedUntilRound + address indexed expressLaneController, + address indexed transferor, + uint64 fixedUntilRound ); /// @notice The minimum reserve price was set @@ -204,15 +210,13 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// to transfer their controller rights. This function returns the transferor if one has been set /// Returns the transferor for the supplied controller, and the round until which this /// transferor is fixed if set. - function transferorOf( - address expressLaneController - ) external returns (address addr, uint64 fixedUntil); + function transferorOf(address expressLaneController) + external + returns (address addr, uint64 fixedUntil); /// @notice Initialize the auction /// @param args Initialization parameters - function initialize( - InitArgs memory args - ) external; + function initialize(InitArgs memory args) external; /// @notice Round timing components: offset, auction closing, round duration and reserve submission function roundTimingInfo() @@ -248,9 +252,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// @param round The round to find the timestamps for /// @return start The start of the round in seconds, inclusive /// @return end The end of the round in seconds, inclusive - function roundTimestamps( - uint64 round - ) external view returns (uint64 start, uint64 end); + function roundTimestamps(uint64 round) external view returns (uint64 start, uint64 end); /// @notice Update the beneficiary to a new address /// Setting the beneficiary does not flush any pending balance, so anyone calling this function should consider @@ -258,9 +260,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// It is expected that the DAO will have the rights to set beneficiary, and since they execute calls via /// action contract they can atomically call flush and set beneficiary together. /// @param newBeneficiary The new beneficiary - function setBeneficiary( - address newBeneficiary - ) external; + function setBeneficiary(address newBeneficiary) external; /// @notice Set the minimum reserve. The reserve cannot be set below this value /// Having a minimum reserve ensures that the reserve setter doesn't set the reserve too low @@ -273,9 +273,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// the min reserve setter is therefore trusted not to do this as it would DOS the auction. Note that even if this occurs /// bidders will not lose their funds and will still be able to withdraw them. /// @param newMinReservePrice The new minimum reserve - function setMinReservePrice( - uint256 newMinReservePrice - ) external; + function setMinReservePrice(uint256 newMinReservePrice) external; /// @notice Set the auction reserve price. Must be greater than or equal the minimum reserve. /// A reserve price setter is given the ability to change the reserve price to ensure that express lane control rights @@ -289,9 +287,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// bidders will not lose their funds and will still be able to withdraw them. /// Note to reserve price setter, setting reserve price is dependent on the time into the round, which can change if the round timing info is updated /// @param newReservePrice The price to set the reserve to - function setReservePrice( - uint256 newReservePrice - ) external; + function setReservePrice(uint256 newReservePrice) external; /// @notice Sets new round timing info. When setting a new round timing info the current round and the start /// timestamp of the next round cannot change. The caller can ensure this by dynamically calculating @@ -309,16 +305,12 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// the maximum round duration is 1 day it should be possible to have many thousands of years worth of /// rounds before it is not longer possible (due to int underflow) to change from 1 second to 1 day duration /// @param newRoundTimingInfo The new timing info to set - function setRoundTimingInfo( - RoundTimingInfo calldata newRoundTimingInfo - ) external; + function setRoundTimingInfo(RoundTimingInfo calldata newRoundTimingInfo) external; /// @notice Get the current balance of specified account. /// If a withdrawal is initiated this balance will reduce in current round + 2 /// @param account The specified account - function balanceOf( - address account - ) external view returns (uint256); + function balanceOf(address account) external view returns (uint256); /// @notice Get what the balance will be at some future round /// Since withdrawals are scheduled for future rounds it is possible to see that a balance @@ -332,9 +324,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// @notice The amount of balance that can currently be withdrawn via the finalize method /// This balance only increases current round + 2 after a withdrawal is initiated /// @param account The account the check the withdrawable balance for - function withdrawableBalance( - address account - ) external view returns (uint256); + function withdrawableBalance(address account) external view returns (uint256); /// @notice The amount of balance that can currently be withdrawn via the finalize method /// Since withdrawals are scheduled for future rounds it is possible to see that a withdrawal balance @@ -344,10 +334,10 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// This balance only increases current round + 2 after a withdrawal is initiated /// @param account The account the check the withdrawable balance for /// @param round The round to query the withdrawable balance at - function withdrawableBalanceAtRound( - address account, - uint64 round - ) external view returns (uint256); + function withdrawableBalanceAtRound(address account, uint64 round) + external + view + returns (uint256); /// @notice Deposit an amount of ERC20 token to the auction to make bids with /// Deposits must be submitted prior to bidding. @@ -357,9 +347,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// are made before that time they will need to wait until 2 rounds after that offset has occurred /// @dev Deposits are submitted first so that the auctioneer can be sure that the accepted bids can actually be paid /// @param amount The amount to deposit. - function deposit( - uint256 amount - ) external; + function deposit(uint256 amount) external; /// @notice Initiate a withdrawal of the full account balance of the message sender /// Once funds have been deposited they can only be retrieved by initiating + finalizing a withdrawal @@ -400,9 +388,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// @dev We do not enforce it, but the following accounts or their sybils, are trusted not to send bids to the auctioneer /// Auctioneer, beneficiary, beneficiary setter, reserve price setter, min reserve price setter, role admin, round timing info setter /// @param firstPriceBid The highest price bid. Must have a price higher than the reserve. Price paid is the reserve - function resolveSingleBidAuction( - Bid calldata firstPriceBid - ) external; + function resolveSingleBidAuction(Bid calldata firstPriceBid) external; /// @notice Resolves the auction round with the two highest bids for that round /// The highest price bidder pays the price of the second highest bid @@ -411,18 +397,14 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// Auctioneer, beneficiary, beneficiary setter, reserve price setter, min reserve price setter, role admin, round timing info setter /// @param firstPriceBid The highest price bid /// @param secondPriceBid The second highest price bid - function resolveMultiBidAuction( - Bid calldata firstPriceBid, - Bid calldata secondPriceBid - ) external; + function resolveMultiBidAuction(Bid calldata firstPriceBid, Bid calldata secondPriceBid) + external; /// @notice Sets a transferor for an express lane controller /// The transferor is an address that will have the right to transfer express lane controller rights /// on behalf an express lane controller. /// @param transferor The transferor to set - function setTransferor( - Transferor calldata transferor - ) external; + function setTransferor(Transferor calldata transferor) external; /// @notice Express lane controllers are allowed to transfer their express lane rights for the current or future /// round to another address. They may use this for reselling their rights after purchasing them @@ -430,10 +412,7 @@ interface IExpressLaneAuction is IAccessControlEnumerableUpgradeable, IERC165Upg /// Although they cannot stop someone transferring the rights to them, they should not use the controller rights if that does occur /// @param round The round to transfer rights for /// @param newExpressLaneController The new express lane controller to transfer the rights to - function transferExpressLaneController( - uint64 round, - address newExpressLaneController - ) external; + function transferExpressLaneController(uint64 round, address newExpressLaneController) external; /// @notice The last two auction rounds that were resolved /// @return The most recent resolved auction round diff --git a/src/express-lane-auction/RoundTimingInfo.sol b/src/express-lane-auction/RoundTimingInfo.sol index bda911091..21326b6a7 100644 --- a/src/express-lane-auction/RoundTimingInfo.sol +++ b/src/express-lane-auction/RoundTimingInfo.sol @@ -26,25 +26,19 @@ struct RoundTimingInfo { library RoundTimingInfoLib { /// @dev Using signed offset involves a lot of casting when comparing the to the block timestamp /// so we provide a helper method here - function blockTimestampBeforeOffset( - int64 offsetTimestamp - ) private view returns (bool) { + function blockTimestampBeforeOffset(int64 offsetTimestamp) private view returns (bool) { return int64(uint64(block.timestamp)) < offsetTimestamp; } /// @dev Using signed offset involves a lot of casting when comparing the to the block timestamp /// so we provide a helper method here /// Notice! this helper method should not be used before checking that the offset is less than the timestamp - function unsignedSinceTimestamp( - int64 offsetTimestamp - ) private view returns (uint64) { + function unsignedSinceTimestamp(int64 offsetTimestamp) private view returns (uint64) { return uint64(int64(uint64(block.timestamp)) - offsetTimestamp); } /// @notice The current round, given the current timestamp, the offset and the round duration - function currentRound( - RoundTimingInfo memory info - ) internal view returns (uint64) { + function currentRound(RoundTimingInfo memory info) internal view returns (uint64) { if (blockTimestampBeforeOffset(info.offsetTimestamp)) { return 0; } @@ -53,9 +47,7 @@ library RoundTimingInfoLib { } /// @notice Has the current auction round closed - function isAuctionRoundClosed( - RoundTimingInfo memory info - ) internal view returns (bool) { + function isAuctionRoundClosed(RoundTimingInfo memory info) internal view returns (bool) { if (blockTimestampBeforeOffset(info.offsetTimestamp)) { return false; } @@ -70,10 +62,11 @@ library RoundTimingInfoLib { /// This period runs from ReserveSubmissionSeconds before the auction closes and ends when the round resolves, or when the round ends. /// @param info Round timing info /// @param latestResolvedRound The last auction round number that was resolved - function isReserveBlackout( - RoundTimingInfo memory info, - uint64 latestResolvedRound - ) internal view returns (bool) { + function isReserveBlackout(RoundTimingInfo memory info, uint64 latestResolvedRound) + internal + view + returns (bool) + { if (blockTimestampBeforeOffset(info.offsetTimestamp)) { // no rounds have started, can't be in blackout return false; @@ -92,8 +85,11 @@ library RoundTimingInfoLib { // otherwise we're not uint64 timeSinceOffset = unsignedSinceTimestamp(info.offsetTimestamp); uint64 timeInRound = timeSinceOffset % info.roundDurationSeconds; - return timeInRound - >= (info.roundDurationSeconds - info.auctionClosingSeconds - info.reserveSubmissionSeconds); + return + timeInRound >= + (info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds); } /// @notice Gets the start and end timestamps (seconds) of a specified round @@ -103,10 +99,11 @@ library RoundTimingInfoLib { /// @param round The specified round /// @return The timestamp at which the round starts /// @return The timestamp at which the round ends - function roundTimestamps( - RoundTimingInfo memory info, - uint64 round - ) internal pure returns (uint64, uint64) { + function roundTimestamps(RoundTimingInfo memory info, uint64 round) + internal + pure + returns (uint64, uint64) + { int64 intRoundStart = info.offsetTimestamp + int64(info.roundDurationSeconds * round); if (intRoundStart < 0) { revert NegativeRoundStart(intRoundStart); diff --git a/test/foundry/ExpressLaneAuction.t.sol b/test/foundry/ExpressLaneAuction.t.sol index 74ad5961f..31652b752 100644 --- a/test/foundry/ExpressLaneAuction.t.sol +++ b/test/foundry/ExpressLaneAuction.t.sol @@ -4,7 +4,8 @@ pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "../../src/express-lane-auction/ExpressLaneAuction.sol"; import { - ERC20Burnable, IERC20 + ERC20Burnable, + IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; @@ -25,7 +26,9 @@ contract ExpressLaneAuctionTest is Test { event Deposit(address indexed account, uint256 amount); event WithdrawalInitiated( - address indexed account, uint256 withdrawalAmount, uint256 roundWithdrawable + address indexed account, + uint256 withdrawalAmount, + uint256 roundWithdrawable ); event WithdrawalFinalized(address indexed account, uint256 withdrawalAmount); event AuctionResolved( @@ -50,7 +53,9 @@ contract ExpressLaneAuctionTest is Test { ); event SetBeneficiary(address oldBeneficiary, address newBeneficiary); event SetTransferor( - address indexed expressLaneController, address indexed transferor, uint64 fixedUntilRound + address indexed expressLaneController, + address indexed transferor, + uint64 fixedUntilRound ); event SetRoundTimingInfo( uint64 currentRound, @@ -73,8 +78,12 @@ contract ExpressLaneAuctionTest is Test { TestBidder[4] bidders; function setUp() public { - bidders[0] = - TestBidder({privKey: 137, addr: vm.addr(137), elc: vm.addr(138), amount: roundDuration}); + bidders[0] = TestBidder({ + privKey: 137, + addr: vm.addr(137), + elc: vm.addr(138), + amount: roundDuration + }); bidders[1] = TestBidder({ privKey: 139, addr: vm.addr(139), @@ -123,34 +132,33 @@ contract ExpressLaneAuctionTest is Test { auction.initialize(args); // move to round test round - (, uint64 roundDurationSeconds,,) = auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = auction.roundTimingInfo(); vm.warp(uint64(offsetTimestamp) + roundDurationSeconds * testRound); return (token, IExpressLaneAuction(auction)); } - function createArgs( - address token - ) internal view returns (InitArgs memory) { - return InitArgs({ - _auctioneer: auctioneer, - _beneficiary: beneficiary, - _biddingToken: token, - _roundTimingInfo: RoundTimingInfo({ - offsetTimestamp: offsetTimestamp, - roundDurationSeconds: roundDuration, - auctionClosingSeconds: roundDuration / 4, - reserveSubmissionSeconds: roundDuration / 4 - }), - _minReservePrice: minReservePrice, - _auctioneerAdmin: auctioneerAdmin, - _minReservePriceSetter: minReservePriceSetter, - _reservePriceSetter: reservePriceSetter, - _reservePriceSetterAdmin: reservePriceSetterAdmin, - _beneficiarySetter: beneficiarySetter, - _roundTimingSetter: roundTimingSetter, - _masterAdmin: masterAdmin - }); + function createArgs(address token) internal view returns (InitArgs memory) { + return + InitArgs({ + _auctioneer: auctioneer, + _beneficiary: beneficiary, + _biddingToken: token, + _roundTimingInfo: RoundTimingInfo({ + offsetTimestamp: offsetTimestamp, + roundDurationSeconds: roundDuration, + auctionClosingSeconds: roundDuration / 4, + reserveSubmissionSeconds: roundDuration / 4 + }), + _minReservePrice: minReservePrice, + _auctioneerAdmin: auctioneerAdmin, + _minReservePriceSetter: minReservePriceSetter, + _reservePriceSetter: reservePriceSetter, + _reservePriceSetterAdmin: reservePriceSetterAdmin, + _beneficiarySetter: beneficiarySetter, + _roundTimingSetter: roundTimingSetter, + _masterAdmin: masterAdmin + }); } function testRoundTimingInit(IExpressLaneAuction auction, MockERC20 token) internal { @@ -261,26 +269,31 @@ contract ExpressLaneAuctionTest is Test { ); assertEq(auction.getRoleAdmin(auction.AUCTIONEER_ROLE()), auction.AUCTIONEER_ADMIN_ROLE()); assertEq( - auction.getRoleAdmin(auction.MIN_RESERVE_SETTER_ROLE()), auction.DEFAULT_ADMIN_ROLE() + auction.getRoleAdmin(auction.MIN_RESERVE_SETTER_ROLE()), + auction.DEFAULT_ADMIN_ROLE() ); assertEq( - auction.getRoleAdmin(auction.RESERVE_SETTER_ROLE()), auction.RESERVE_SETTER_ADMIN_ROLE() + auction.getRoleAdmin(auction.RESERVE_SETTER_ROLE()), + auction.RESERVE_SETTER_ADMIN_ROLE() ); assertEq( - auction.getRoleAdmin(auction.BENEFICIARY_SETTER_ROLE()), auction.DEFAULT_ADMIN_ROLE() + auction.getRoleAdmin(auction.BENEFICIARY_SETTER_ROLE()), + auction.DEFAULT_ADMIN_ROLE() ); assertEq( - auction.getRoleAdmin(auction.AUCTIONEER_ADMIN_ROLE()), auction.DEFAULT_ADMIN_ROLE() + auction.getRoleAdmin(auction.AUCTIONEER_ADMIN_ROLE()), + auction.DEFAULT_ADMIN_ROLE() ); assertEq( - auction.getRoleAdmin(auction.RESERVE_SETTER_ADMIN_ROLE()), auction.DEFAULT_ADMIN_ROLE() + auction.getRoleAdmin(auction.RESERVE_SETTER_ADMIN_ROLE()), + auction.DEFAULT_ADMIN_ROLE() ); vm.expectRevert("Initializable: contract is already initialized"); auction.initialize(args); // cannot send funds to the contract - (bool success,) = address(auction).call{value: 10}(hex""); + (bool success, ) = address(auction).call{value: 10}(hex""); assertFalse(success, "auction value call"); assertEq(address(auction).balance, 0, "bal after"); } @@ -354,14 +367,16 @@ contract ExpressLaneAuctionTest is Test { assertEq(auction.balanceOf(bidders[0].addr), bidders[0].amount, "Full first balance"); assertEq(erc20.balanceOf(bidders[0].addr), 0, "Full first bidders[0].addr erc20 balance"); assertEq( - erc20.balanceOf(address(auction)), bidders[0].amount, "Full dirst auction erc20 balance" + erc20.balanceOf(address(auction)), + bidders[0].amount, + "Full dirst auction erc20 balance" ); vm.stopPrank(); // can deposit different bidder, do it once per second for 2 rounds // to ensure that deposit can occur at any time vm.startPrank(bidders[1].addr); - (, uint64 roundDurationSeconds,,) = auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = auction.roundTimingInfo(); erc20.approve(address(auction), roundDurationSeconds * 3); for (uint256 i = 0; i < roundDurationSeconds * 3; i++) { vm.warp(block.timestamp + 1); @@ -406,7 +421,9 @@ contract ExpressLaneAuctionTest is Test { auction.deposit(20); assertEq(auction.balanceOf(bidders[0].addr), 20, "First balance"); assertEq( - auction.balanceOfAtRound(bidders[0].addr, currentRound), 20, "First balance at round" + auction.balanceOfAtRound(bidders[0].addr, currentRound), + 20, + "First balance at round" ); assertEq( auction.balanceOfAtRound(bidders[0].addr, currentRound + 1), @@ -634,7 +651,7 @@ contract ExpressLaneAuctionTest is Test { vm.warp(1); assertEq(auction.currentRound(), 0); - (int64 offsetTimestampA, uint64 roundDurationSeconds,,) = auction.roundTimingInfo(); + (int64 offsetTimestampA, uint64 roundDurationSeconds, , ) = auction.roundTimingInfo(); vm.warp(uint64(offsetTimestampA) - 1); assertEq(auction.currentRound(), 0); @@ -668,7 +685,7 @@ contract ExpressLaneAuctionTest is Test { assertEq(auction.withdrawableBalance(bidders[0].addr), 0); // round 1.5 - (, uint64 roundDurationSeconds,,) = auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = auction.roundTimingInfo(); vm.warp(block.timestamp + roundDurationSeconds / 2); assertEq(auction.currentRound(), curRound); @@ -779,7 +796,7 @@ contract ExpressLaneAuctionTest is Test { vm.expectRevert(abi.encodeWithSelector(NothingToWithdraw.selector)); auction.finalizeWithdrawal(); - (, uint64 roundDurationSeconds,,) = auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = auction.roundTimingInfo(); vm.warp(block.timestamp + roundDurationSeconds); assertEq(auction.currentRound(), curRound + 1); @@ -810,7 +827,9 @@ contract ExpressLaneAuctionTest is Test { uint256 auctionErc20BalAfter = erc20.balanceOf(address(auction)); assertEq(bidderErc20BalAfter, bidderErc20BalBefore + bidders[0].amount, "balance after"); assertEq( - auctionErc20BalAfter, auctionErc20BalBefore - bidders[0].amount, "auction balance after" + auctionErc20BalAfter, + auctionErc20BalBefore - bidders[0].amount, + "auction balance after" ); // expect revert @@ -833,7 +852,7 @@ contract ExpressLaneAuctionTest is Test { auction.initiateWithdrawal(); - (, uint64 roundDurationSeconds,,) = auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = auction.roundTimingInfo(); vm.warp(block.timestamp + roundDurationSeconds * 5); assertEq(auction.currentRound(), curRound + 5); @@ -891,21 +910,22 @@ contract ExpressLaneAuctionTest is Test { signature: sign(bidders[1].privKey, h1) }); - (, uint64 roundDurationSeconds, uint64 auctionClosingSeconds,) = auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, uint64 auctionClosingSeconds, ) = auction.roundTimingInfo(); vm.warp(block.timestamp + roundDurationSeconds - auctionClosingSeconds); vm.startPrank(auctioneer); - return ResolveSetup({ - erc20: erc20, - auction: auction, - bid0: bid0, - bid1: bid1, - h0: h0, - h1: h1, - biddingForRound: biddingForRound - }); + return + ResolveSetup({ + erc20: erc20, + auction: auction, + bid0: bid0, + bid1: bid1, + h0: h0, + h1: h1, + biddingForRound: biddingForRound + }); } function testGetDomainSeparator() public { @@ -986,11 +1006,13 @@ contract ExpressLaneAuctionTest is Test { auction.deposit(bidders[1].amount); vm.stopPrank(); - (int64 o, uint64 roundDurationSeconds, uint64 auctionClosingSeconds,) = - auction.roundTimingInfo(); + (int64 o, uint64 roundDurationSeconds, uint64 auctionClosingSeconds, ) = auction + .roundTimingInfo(); vm.warp( - uint64(o) + (roundDurationSeconds * testRound) + roundDurationSeconds - - auctionClosingSeconds + uint64(o) + + (roundDurationSeconds * testRound) + + roundDurationSeconds - + auctionClosingSeconds ); uint64 biddingForRound = auction.currentRound() + 1; @@ -1074,8 +1096,11 @@ contract ExpressLaneAuctionTest is Test { ResolveSetup memory rs = deployDepositAndBids(); // bid1.amount == bid0.amount - bytes32 h1 = - rs.auction.getBidHash(rs.biddingForRound, bidders[0].elc, bidders[0].amount / 2); + bytes32 h1 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[0].elc, + bidders[0].amount / 2 + ); Bid memory bid1 = Bid({ amount: bidders[0].amount / 2, expressLaneController: bidders[0].elc, @@ -1101,14 +1126,18 @@ contract ExpressLaneAuctionTest is Test { vm.expectRevert( abi.encodeWithSelector( - ReservePriceNotMet.selector, minReservePrice - 1, minReservePrice + ReservePriceNotMet.selector, + minReservePrice - 1, + minReservePrice ) ); rs.auction.resolveMultiBidAuction(rs.bid1, bid0); vm.expectRevert( abi.encodeWithSelector( - ReservePriceNotMet.selector, minReservePrice - 1, minReservePrice + ReservePriceNotMet.selector, + minReservePrice - 1, + minReservePrice ) ); rs.auction.resolveSingleBidAuction(bid0); @@ -1117,8 +1146,11 @@ contract ExpressLaneAuctionTest is Test { function testCannotResolveInsufficientFunds() public { ResolveSetup memory rs = deployDepositAndBids(); - bytes32 h1 = - rs.auction.getBidHash(rs.biddingForRound, bidders[1].elc, bidders[1].amount * 2); + bytes32 h1 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[1].elc, + bidders[1].amount * 2 + ); Bid memory bid1 = Bid({ amount: bidders[1].amount * 2, expressLaneController: bidders[1].elc, @@ -1135,8 +1167,11 @@ contract ExpressLaneAuctionTest is Test { ); rs.auction.resolveMultiBidAuction(bid1, rs.bid0); - bytes32 h0 = - rs.auction.getBidHash(rs.biddingForRound, bidders[0].elc, (bidders[0].amount * 3) / 2); + bytes32 h0 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[0].elc, + (bidders[0].amount * 3) / 2 + ); Bid memory bid0 = Bid({ amount: (bidders[0].amount * 3) / 2, expressLaneController: bidders[0].elc, @@ -1167,12 +1202,18 @@ contract ExpressLaneAuctionTest is Test { function testCannotResolveWrongChain() public { ResolveSetup memory rs = deployDepositAndBids(); vm.chainId(31337); - bytes32 h1 = - rs.auction.getBidHash(rs.biddingForRound, bidders[1].elc, bidders[1].amount / 2); + bytes32 h1 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[1].elc, + bidders[1].amount / 2 + ); vm.chainId(137); - bytes32 correctH1 = - rs.auction.getBidHash(rs.biddingForRound, bidders[1].elc, bidders[1].amount / 2); + bytes32 correctH1 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[1].elc, + bidders[1].amount / 2 + ); Bid memory bid1 = Bid({ amount: bidders[1].amount / 2, expressLaneController: bidders[1].elc, @@ -1184,18 +1225,27 @@ contract ExpressLaneAuctionTest is Test { // wrong chain means wrong hash means wrong address vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, wrongBidder1, bidders[1].amount / 2, 0 + InsufficientBalanceAcc.selector, + wrongBidder1, + bidders[1].amount / 2, + 0 ) ); rs.auction.resolveMultiBidAuction(bid1, rs.bid0); vm.chainId(31337); - bytes32 h0 = - rs.auction.getBidHash(rs.biddingForRound, bidders[0].elc, bidders[0].amount / 2); + bytes32 h0 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[0].elc, + bidders[0].amount / 2 + ); vm.chainId(137); - bytes32 correctH0 = - rs.auction.getBidHash(rs.biddingForRound, bidders[0].elc, bidders[0].amount / 2); + bytes32 correctH0 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[0].elc, + bidders[0].amount / 2 + ); Bid memory bid0 = Bid({ amount: bidders[0].amount / 2, expressLaneController: bidders[0].elc, @@ -1207,7 +1257,10 @@ contract ExpressLaneAuctionTest is Test { // wrong chain means wrong hash means wrong address vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, wrongBidder0, bidders[0].amount / 2, 0 + InsufficientBalanceAcc.selector, + wrongBidder0, + bidders[0].amount / 2, + 0 ) ); rs.auction.resolveMultiBidAuction(rs.bid1, bid0); @@ -1215,7 +1268,10 @@ contract ExpressLaneAuctionTest is Test { // wrong chain means wrong hash means wrong address vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, wrongBidder1, bidders[1].amount / 2, 0 + InsufficientBalanceAcc.selector, + wrongBidder1, + bidders[1].amount / 2, + 0 ) ); rs.auction.resolveSingleBidAuction(bid1); @@ -1239,14 +1295,20 @@ contract ExpressLaneAuctionTest is Test { expressLaneController: bidders[1].elc, signature: sign(bidders[1].privKey, h1) }); - bytes32 correctH1 = - rs.auction.getBidHash(rs.biddingForRound, bidders[1].elc, bidders[1].amount / 2); + bytes32 correctH1 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[1].elc, + bidders[1].amount / 2 + ); address wrongBidder1 = correctH1.recover(bid1.signature); // wrong chain means wrong hash means wrong address vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, wrongBidder1, bidders[1].amount / 2, 0 + InsufficientBalanceAcc.selector, + wrongBidder1, + bidders[1].amount / 2, + 0 ) ); rs.auction.resolveMultiBidAuction(bid1, rs.bid0); @@ -1265,14 +1327,20 @@ contract ExpressLaneAuctionTest is Test { expressLaneController: bidders[0].elc, signature: sign(bidders[0].privKey, h0) }); - bytes32 correctH0 = - rs.auction.getBidHash(rs.biddingForRound, bidders[0].elc, bidders[0].amount / 2); + bytes32 correctH0 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[0].elc, + bidders[0].amount / 2 + ); address wrongBidder0 = correctH0.recover(bid0.signature); // wrong chain means wrong hash means wrong address vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, wrongBidder0, bidders[0].amount / 2, 0 + InsufficientBalanceAcc.selector, + wrongBidder0, + bidders[0].amount / 2, + 0 ) ); rs.auction.resolveMultiBidAuction(rs.bid1, bid0); @@ -1280,7 +1348,10 @@ contract ExpressLaneAuctionTest is Test { // wrong chain means wrong hash means wrong address vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, wrongBidder0, bidders[0].amount / 2, 0 + InsufficientBalanceAcc.selector, + wrongBidder0, + bidders[0].amount / 2, + 0 ) ); rs.auction.resolveSingleBidAuction(bid0); @@ -1291,8 +1362,11 @@ contract ExpressLaneAuctionTest is Test { function testCannotResolveWrongSig() public { ResolveSetup memory rs = deployDepositAndBids(); - bytes32 h1 = - rs.auction.getBidHash(rs.biddingForRound, bidders[1].elc, bidders[1].amount / 2); + bytes32 h1 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[1].elc, + bidders[1].amount / 2 + ); (, bytes32 r2, bytes32 s2) = vm.sign(bidders[1].privKey, h1); uint8 badV = 17; Bid memory bid1 = Bid({ @@ -1306,8 +1380,11 @@ contract ExpressLaneAuctionTest is Test { vm.expectRevert(abi.encodePacked("ECDSA: invalid signature 'v' value")); rs.auction.resolveMultiBidAuction(bid1, rs.bid0); - bytes32 h0 = - rs.auction.getBidHash(rs.biddingForRound, bidders[0].elc, bidders[0].amount / 2); + bytes32 h0 = rs.auction.getBidHash( + rs.biddingForRound, + bidders[0].elc, + bidders[0].amount / 2 + ); (, bytes32 r1, bytes32 s1) = vm.sign(bidders[0].privKey, h0); Bid memory bid0 = Bid({ amount: bidders[0].amount / 2, @@ -1362,8 +1439,9 @@ contract ExpressLaneAuctionTest is Test { function testResolveMultiBidAuction() public { ResolveSetup memory rs = deployDepositAndBids(); uint64 biddingForRound = rs.auction.currentRound() + 1; - (, uint64 roundDurationSeconds, uint64 auctionClosingSeconds,) = - rs.auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, uint64 auctionClosingSeconds, ) = rs + .auction + .roundTimingInfo(); uint256 auctionBalanceBefore = rs.erc20.balanceOf(address(rs.auction)); vm.expectEmit(true, true, true, true); @@ -1429,9 +1507,14 @@ contract ExpressLaneAuctionTest is Test { vm.expectRevert( abi.encodeWithSelector( InsufficientBalanceAcc.selector, - rs.auction.getBidHash( - rs.auction.currentRound() + 1, bidders[3].elc, bidders[3].amount / 4 - ).recover(bid34[1].signature), + rs + .auction + .getBidHash( + rs.auction.currentRound() + 1, + bidders[3].elc, + bidders[3].amount / 4 + ) + .recover(bid34[1].signature), bidders[3].amount / 4, 0 ) @@ -1488,7 +1571,9 @@ contract ExpressLaneAuctionTest is Test { "bidders[3].addr balance" ); assertEq( - rs.auction.balanceOf(bidders[2].addr), bidders[2].amount, "bidders[2].addr balance" + rs.auction.balanceOf(bidders[2].addr), + bidders[2].amount, + "bidders[2].addr balance" ); assertEq( rs.auction.beneficiaryBalance() - beneficiaryBalanceBefore, @@ -1497,7 +1582,9 @@ contract ExpressLaneAuctionTest is Test { ); assertEq(rs.erc20.balanceOf(address(rs.auction)), auctionBalanceBefore, "auction balance"); checkResolvedRounds( - rs.auction, ELCRound(bid34[1].expressLaneController, biddingForRound), expected0 + rs.auction, + ELCRound(bid34[1].expressLaneController, biddingForRound), + expected0 ); vm.stopPrank(); @@ -1533,8 +1620,11 @@ contract ExpressLaneAuctionTest is Test { }); { bytes32 h1 = rs.auction.getBidHash(biddingForRound, vm.addr(1667), 0); - Bid memory bid1 = - Bid({amount: 0, expressLaneController: vm.addr(1667), signature: sign(1668, h1)}); + Bid memory bid1 = Bid({ + amount: 0, + expressLaneController: vm.addr(1667), + signature: sign(1668, h1) + }); vm.expectRevert(abi.encodeWithSelector(InsufficientBalance.selector, 0, 0)); vm.prank(auctioneer); rs.auction.resolveMultiBidAuction(bid1, bid0); @@ -1595,8 +1685,11 @@ contract ExpressLaneAuctionTest is Test { { bytes32 h1 = rs.auction.getBidHash(biddingForRound, vm.addr(1667), 0); - Bid memory bid1 = - Bid({amount: 0, expressLaneController: vm.addr(1667), signature: sign(1668, h1)}); + Bid memory bid1 = Bid({ + amount: 0, + expressLaneController: vm.addr(1667), + signature: sign(1668, h1) + }); vm.expectRevert(abi.encodeWithSelector(InsufficientBalance.selector, 0, 0)); vm.prank(auctioneer); rs.auction.resolveSingleBidAuction(bid1); @@ -1658,7 +1751,7 @@ contract ExpressLaneAuctionTest is Test { vm.stopPrank(); // go back and initiate a withdrawal - (, uint64 roundDurationSeconds,,) = rs.auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = rs.auction.roundTimingInfo(); vm.warp(block.timestamp - 1 - roundDurationSeconds); vm.prank(bidders[0].addr); @@ -1678,7 +1771,7 @@ contract ExpressLaneAuctionTest is Test { vm.stopPrank(); // go back and initiate a withdrawal - (, uint64 roundDurationSeconds,,) = rs.auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = rs.auction.roundTimingInfo(); vm.warp(block.timestamp - 1 - roundDurationSeconds * 2); vm.prank(bidders[0].addr); @@ -1689,7 +1782,10 @@ contract ExpressLaneAuctionTest is Test { vm.prank(auctioneer); vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, bidders[0].addr, rs.bid0.amount, 0 + InsufficientBalanceAcc.selector, + bidders[0].addr, + rs.bid0.amount, + 0 ) ); rs.auction.resolveMultiBidAuction(rs.bid1, rs.bid0); @@ -1700,7 +1796,7 @@ contract ExpressLaneAuctionTest is Test { vm.stopPrank(); // go back and initiate a withdrawal - (, uint64 roundDurationSeconds,,) = rs.auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = rs.auction.roundTimingInfo(); vm.warp(block.timestamp - 1 - roundDurationSeconds * 2); vm.prank(bidders[1].addr); @@ -1711,7 +1807,10 @@ contract ExpressLaneAuctionTest is Test { vm.prank(auctioneer); vm.expectRevert( abi.encodeWithSelector( - InsufficientBalanceAcc.selector, bidders[1].addr, rs.bid1.amount, 0 + InsufficientBalanceAcc.selector, + bidders[1].addr, + rs.bid1.amount, + 0 ) ); rs.auction.resolveMultiBidAuction(rs.bid1, rs.bid0); @@ -1720,8 +1819,9 @@ contract ExpressLaneAuctionTest is Test { function testResolveSingleBidAuction() public { ResolveSetup memory rs = deployDepositAndBids(); uint64 biddingForRound = rs.auction.currentRound() + 1; - (, uint64 roundDurationSeconds, uint64 auctionClosingSeconds,) = - rs.auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, uint64 auctionClosingSeconds, ) = rs + .auction + .roundTimingInfo(); uint256 auctionBalanceBefore = rs.erc20.balanceOf(address(rs.auction)); @@ -1784,7 +1884,9 @@ contract ExpressLaneAuctionTest is Test { vm.prank(reservePriceSetter); vm.expectRevert( abi.encodeWithSelector( - ReservePriceTooLow.selector, minReservePrice - 1, minReservePrice + ReservePriceTooLow.selector, + minReservePrice - 1, + minReservePrice ) ); rs.auction.setReservePrice(minReservePrice - 1); @@ -1803,8 +1905,11 @@ contract ExpressLaneAuctionTest is Test { // during blackout vm.warp( - uint64(offsetTimestamp) + roundDurationSeconds * (testRound + 1) - auctionClosingSeconds - - reserveSubmissionSeconds + uint64(offsetTimestamp) + + roundDurationSeconds * + (testRound + 1) - + auctionClosingSeconds - + reserveSubmissionSeconds ); vm.prank(reservePriceSetter); @@ -1888,8 +1993,10 @@ contract ExpressLaneAuctionTest is Test { uint64 reserveSubmissionSeconds ) = auction.roundTimingInfo(); vm.warp( - block.timestamp + roundDurationSeconds - auctionClosingSeconds - - reserveSubmissionSeconds + block.timestamp + + roundDurationSeconds - + auctionClosingSeconds - + reserveSubmissionSeconds ); assertEq(auction.isReserveBlackout(), true); @@ -1926,7 +2033,10 @@ contract ExpressLaneAuctionTest is Test { rs.auction.transferExpressLaneController(testRound, bidders[0].elc); vm.expectRevert( abi.encodeWithSelector( - NotExpressLaneController.selector, testRound + 1, bidders[1].elc, address(this) + NotExpressLaneController.selector, + testRound + 1, + bidders[1].elc, + address(this) ) ); rs.auction.transferExpressLaneController(testRound + 1, bidders[0].elc); @@ -1935,11 +2045,16 @@ contract ExpressLaneAuctionTest is Test { vm.prank(bidders[1].elc); vm.expectEmit(true, true, true, true); emit SetExpressLaneController( - testRound + 1, bidders[1].elc, bidders[0].elc, bidders[1].elc, start, end + testRound + 1, + bidders[1].elc, + bidders[0].elc, + bidders[1].elc, + start, + end ); rs.auction.transferExpressLaneController(testRound + 1, bidders[0].elc); - (, uint64 roundDurationSeconds,,) = rs.auction.roundTimingInfo(); + (, uint64 roundDurationSeconds, , ) = rs.auction.roundTimingInfo(); vm.warp(block.timestamp + roundDurationSeconds); // round has moved forward @@ -1994,7 +2109,10 @@ contract ExpressLaneAuctionTest is Test { // cant change next from wrong sender vm.expectRevert( abi.encodeWithSelector( - NotExpressLaneController.selector, testRound + 2, bidders[3].elc, address(this) + NotExpressLaneController.selector, + testRound + 2, + bidders[3].elc, + address(this) ) ); rs.auction.transferExpressLaneController(testRound + 2, bidders[2].elc); @@ -2005,7 +2123,12 @@ contract ExpressLaneAuctionTest is Test { vm.prank(bidders[3].elc); vm.expectEmit(true, true, true, true); emit SetExpressLaneController( - testRound + 2, bidders[3].elc, bidders[2].elc, bidders[3].elc, start, end + testRound + 2, + bidders[3].elc, + bidders[2].elc, + bidders[3].elc, + start, + end ); rs.auction.transferExpressLaneController(testRound + 2, bidders[2].elc); @@ -2016,7 +2139,10 @@ contract ExpressLaneAuctionTest is Test { vm.prank(bidders[3].elc); vm.expectRevert( abi.encodeWithSelector( - NotTransferor.selector, testRound + 2, bidders[2].addr, bidders[3].elc + NotTransferor.selector, + testRound + 2, + bidders[2].addr, + bidders[3].elc ) ); rs.auction.transferExpressLaneController(testRound + 2, bidders[2].elc); @@ -2025,7 +2151,12 @@ contract ExpressLaneAuctionTest is Test { vm.prank(bidders[2].addr); vm.expectEmit(true, true, true, true); emit SetExpressLaneController( - testRound + 2, bidders[2].elc, bidders[3].elc, bidders[2].addr, start, end + testRound + 2, + bidders[2].elc, + bidders[3].elc, + bidders[2].addr, + start, + end ); rs.auction.transferExpressLaneController(testRound + 2, bidders[3].elc); } @@ -2150,7 +2281,7 @@ contract ExpressLaneAuctionTest is Test { }) ); - (uint64 start,) = auction.roundTimestamps(auction.currentRound() + 1); + (uint64 start, ) = auction.roundTimestamps(auction.currentRound() + 1); int64 newOffset = int64(start - 86401 * 24); vm.prank(roundTimingSetter); @@ -2187,7 +2318,7 @@ contract ExpressLaneAuctionTest is Test { ); uint64 cNewDuration = (roundDuration * 7) / 3; - (uint64 cStart,) = auction.roundTimestamps(auction.currentRound() + 1); + (uint64 cStart, ) = auction.roundTimestamps(auction.currentRound() + 1); int64 cNewOffset = int64(cStart - cNewDuration * (auction.currentRound() + 1)); vm.expectEmit(true, true, true, true); @@ -2201,8 +2332,8 @@ contract ExpressLaneAuctionTest is Test { reserveSubmissionSeconds: 12 }) ); - (int64 offsetAfter, uint64 durationAfter, uint64 acAfter, uint64 rsAfter) = - auction.roundTimingInfo(); + (int64 offsetAfter, uint64 durationAfter, uint64 acAfter, uint64 rsAfter) = auction + .roundTimingInfo(); assertEq(offsetAfter, cNewOffset); assertEq(durationAfter, cNewDuration); assertEq(acAfter, 13); @@ -2210,7 +2341,7 @@ contract ExpressLaneAuctionTest is Test { // set the min duration cNewDuration = 1; - (cStart,) = auction.roundTimestamps(auction.currentRound() + 1); + (cStart, ) = auction.roundTimestamps(auction.currentRound() + 1); int64 intStart = int64(cStart); // warp to just before that start - we need to be within round duration of the next round vm.warp(cStart - 1); @@ -2233,7 +2364,7 @@ contract ExpressLaneAuctionTest is Test { // fast forward 10k years - that sets a high number of rounds vm.warp(block.timestamp + (365 * 86400)); cNewDuration = 86400; - (cStart,) = auction.roundTimestamps(auction.currentRound() + 1); + (cStart, ) = auction.roundTimestamps(auction.currentRound() + 1); intStart = int64(cStart); cNewOffset = int64(intStart - int64(cNewDuration * (auction.currentRound() + 1))); vm.prank(roundTimingSetter); diff --git a/test/foundry/ExpressLaneBalance.t.sol b/test/foundry/ExpressLaneBalance.t.sol index 96f00ca7c..8178daf30 100644 --- a/test/foundry/ExpressLaneBalance.t.sol +++ b/test/foundry/ExpressLaneBalance.t.sol @@ -10,29 +10,21 @@ import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.so contract BalanceImp { using BalanceLib for Balance; - constructor( - Balance memory _bal - ) { + constructor(Balance memory _bal) { bal = _bal; } Balance public bal; - function balanceAtRound( - uint64 round - ) external view returns (uint256) { + function balanceAtRound(uint64 round) external view returns (uint256) { return bal.balanceAtRound(round); } - function withdrawableBalanceAtRound( - uint64 round - ) external view returns (uint256) { + function withdrawableBalanceAtRound(uint64 round) external view returns (uint256) { return bal.withdrawableBalanceAtRound(round); } - function increase( - uint256 amount - ) external { + function increase(uint256 amount) external { return bal.increase(amount); } @@ -40,15 +32,11 @@ contract BalanceImp { return bal.reduce(amount, round); } - function initiateWithdrawal( - uint64 round - ) external { + function initiateWithdrawal(uint64 round) external { return bal.initiateWithdrawal(round); } - function finalizeWithdrawal( - uint64 round - ) external returns (uint256) { + function finalizeWithdrawal(uint64 round) external returns (uint256) { return bal.finalizeWithdrawal(round); } } @@ -220,9 +208,10 @@ contract InvariantBalance is Test { } function invariantBalanceWithdrawableSum() public { - uint64 randRound = - uint64(uint256(keccak256(abi.encode(msg.sender, block.timestamp, "round")))); - (uint256 bal,) = balanceImp.bal(); + uint64 randRound = uint64( + uint256(keccak256(abi.encode(msg.sender, block.timestamp, "round"))) + ); + (uint256 bal, ) = balanceImp.bal(); // withdrawable balance + available balance should always equal internal balance assertEq( balanceImp.balanceAtRound(randRound) + balanceImp.withdrawableBalanceAtRound(randRound), diff --git a/test/foundry/ExpressLaneBurner.t.sol b/test/foundry/ExpressLaneBurner.t.sol index e3d34bbe7..e6bb22211 100644 --- a/test/foundry/ExpressLaneBurner.t.sol +++ b/test/foundry/ExpressLaneBurner.t.sol @@ -2,8 +2,9 @@ pragma solidity ^0.8.0; import "forge-std/Test.sol"; -import {ERC20BurnableUpgradeable} from - "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; +import { + ERC20BurnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; import {Burner} from "../../src/express-lane-auction/Burner.sol"; import "../../src/express-lane-auction/Errors.sol"; diff --git a/test/foundry/ExpressLaneELCRound.t.sol b/test/foundry/ExpressLaneELCRound.t.sol index 37f11c27b..3346d6542 100644 --- a/test/foundry/ExpressLaneELCRound.t.sol +++ b/test/foundry/ExpressLaneELCRound.t.sol @@ -9,9 +9,7 @@ contract LatestELCRoundsImp { ELCRound[2] public rounds; - constructor( - ELCRound[2] memory r - ) { + constructor(ELCRound[2] memory r) { rounds[0] = r[0]; rounds[1] = r[1]; } @@ -20,9 +18,7 @@ contract LatestELCRoundsImp { return rounds.latestELCRound(); } - function resolvedRound( - uint64 round - ) public view returns (ELCRound memory) { + function resolvedRound(uint64 round) public view returns (ELCRound memory) { return rounds.resolvedRound(round); } @@ -95,10 +91,11 @@ contract ExpressLaneELCRoundTest is Test { li.resolvedRound(10); } - function getELCRound( - LatestELCRoundsImp li, - uint8 index - ) internal view returns (ELCRound memory) { + function getELCRound(LatestELCRoundsImp li, uint8 index) + internal + view + returns (ELCRound memory) + { (address elc, uint64 round) = li.rounds(index); return ELCRound(elc, round); } diff --git a/test/foundry/ExpressLaneRoundTiming.t.sol b/test/foundry/ExpressLaneRoundTiming.t.sol index 5308a8983..681870510 100644 --- a/test/foundry/ExpressLaneRoundTiming.t.sol +++ b/test/foundry/ExpressLaneRoundTiming.t.sol @@ -9,9 +9,7 @@ contract RoundTimingInfoImp { RoundTimingInfo public timingInfo; - constructor( - RoundTimingInfo memory r - ) { + constructor(RoundTimingInfo memory r) { timingInfo = r; } @@ -23,40 +21,39 @@ contract RoundTimingInfoImp { return timingInfo.isAuctionRoundClosed(); } - function isReserveBlackout( - uint64 latestResolvedRound - ) public view returns (bool) { + function isReserveBlackout(uint64 latestResolvedRound) public view returns (bool) { return timingInfo.isReserveBlackout(latestResolvedRound); } - function roundTimestamps( - uint64 round - ) public view returns (uint64, uint64) { + function roundTimestamps(uint64 round) public view returns (uint64, uint64) { return timingInfo.roundTimestamps(round); } } contract ExpressLaneRoundTimingTest is Test { - RoundTimingInfo info = RoundTimingInfo({ - offsetTimestamp: 1000, - roundDurationSeconds: 100, - auctionClosingSeconds: 25, - reserveSubmissionSeconds: 20 - }); + RoundTimingInfo info = + RoundTimingInfo({ + offsetTimestamp: 1000, + roundDurationSeconds: 100, + auctionClosingSeconds: 25, + reserveSubmissionSeconds: 20 + }); - RoundTimingInfo matchInfo = RoundTimingInfo({ - offsetTimestamp: 1000, - roundDurationSeconds: 100, - auctionClosingSeconds: 25, - reserveSubmissionSeconds: 75 - }); + RoundTimingInfo matchInfo = + RoundTimingInfo({ + offsetTimestamp: 1000, + roundDurationSeconds: 100, + auctionClosingSeconds: 25, + reserveSubmissionSeconds: 75 + }); - RoundTimingInfo negativeInfo = RoundTimingInfo({ - offsetTimestamp: -1000, - roundDurationSeconds: 100, - auctionClosingSeconds: 25, - reserveSubmissionSeconds: 20 - }); + RoundTimingInfo negativeInfo = + RoundTimingInfo({ + offsetTimestamp: -1000, + roundDurationSeconds: 100, + auctionClosingSeconds: 25, + reserveSubmissionSeconds: 20 + }); function testCurrentRound() public { RoundTimingInfoImp ri = new RoundTimingInfoImp(info); @@ -167,22 +164,30 @@ contract ExpressLaneRoundTimingTest is Test { assertFalse(ri.isReserveBlackout(1), "At offset"); assertFalse(ri.isReserveBlackout(2), "At offset"); vm.warp( - offset + info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds - 1 + offset + + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds - + 1 ); assertFalse(ri.isReserveBlackout(0), "Before blackout"); assertFalse(ri.isReserveBlackout(1), "Before blackout"); assertFalse(ri.isReserveBlackout(2), "Before blackout"); vm.warp( - offset + info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds + offset + + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds ); assertTrue(ri.isReserveBlackout(0), "At blackout 0"); assertFalse(ri.isReserveBlackout(1), "At blackout 1"); assertFalse(ri.isReserveBlackout(2), "At blackout 2"); vm.warp( - offset + info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds + 1 + offset + + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds + + 1 ); assertTrue(ri.isReserveBlackout(0), "After blackout"); assertFalse(ri.isReserveBlackout(1), "After blackout"); @@ -196,8 +201,11 @@ contract ExpressLaneRoundTimingTest is Test { assertFalse(ri.isReserveBlackout(1), "At next round"); assertFalse(ri.isReserveBlackout(2), "At next round"); vm.warp( - offset + 2 * info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds + offset + + 2 * + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds ); assertTrue(ri.isReserveBlackout(0), "At next reserve submission deadline"); assertTrue(ri.isReserveBlackout(1), "At next reserve submission deadline"); @@ -221,22 +229,30 @@ contract ExpressLaneRoundTimingTest is Test { assertFalse(nri.isReserveBlackout(20), "At offset"); assertFalse(nri.isReserveBlackout(21), "At offset"); vm.warp( - negativeOffset + info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds - 1 + negativeOffset + + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds - + 1 ); assertFalse(nri.isReserveBlackout(19), "Before blackout"); assertFalse(nri.isReserveBlackout(20), "Before blackout"); assertFalse(nri.isReserveBlackout(21), "Before blackout"); vm.warp( - negativeOffset + info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds + negativeOffset + + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds ); assertTrue(nri.isReserveBlackout(19), "At blackout 19"); assertTrue(nri.isReserveBlackout(20), "At blackout 20"); assertFalse(nri.isReserveBlackout(21), "At blackout 21"); vm.warp( - negativeOffset + info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds + 1 + negativeOffset + + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds + + 1 ); assertTrue(nri.isReserveBlackout(19), "After blackout"); assertTrue(nri.isReserveBlackout(20), "After blackout"); @@ -262,8 +278,11 @@ contract ExpressLaneRoundTimingTest is Test { assertFalse(nri.isReserveBlackout(20), "At next round"); assertFalse(nri.isReserveBlackout(21), "At next round"); vm.warp( - negativeOffset + 2 * info.roundDurationSeconds - info.auctionClosingSeconds - - info.reserveSubmissionSeconds + negativeOffset + + 2 * + info.roundDurationSeconds - + info.auctionClosingSeconds - + info.reserveSubmissionSeconds ); assertTrue(nri.isReserveBlackout(19), "At next reserve submission deadline"); assertTrue(nri.isReserveBlackout(20), "At next reserve submission deadline");