Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e451af3
Cross-port from #109
0xJem Apr 11, 2024
0d81564
Cross-port changes from #102
0xJem Apr 2, 2024
5216abe
Add tests for permitting minting/deployment/validation after vesting …
0xJem Apr 3, 2024
f8cdd0c
Update implementation to permit mint/validate/deploy after vesting
0xJem Apr 3, 2024
101702c
Add setter for minAuctionDuration
0xJem Apr 3, 2024
d974545
test: fix compile error from rebase
Oighty Apr 11, 2024
31ad529
fix: configure gas claimable on blast modules
Oighty Apr 11, 2024
5d842db
fix: make blast addresses configurable in blast AH
Oighty Apr 11, 2024
012fca4
feat: add blast FPAM
Oighty Apr 11, 2024
4872086
script: fix compile errors in deploy script
Oighty Apr 11, 2024
f86eda7
chore: lint
Oighty Apr 11, 2024
f074414
refactor: require user to provide the index of their bid id to be ref…
Oighty Apr 11, 2024
6847daf
feat: add view function to batch catalogue to get ids for checking ag…
Oighty Apr 11, 2024
74346cb
test: update existing tests
Oighty Apr 11, 2024
a42a306
test: add new empa refund tests
Oighty Apr 11, 2024
4bd7e7e
fix: use consistent price math b/w auction and queue
Oighty Apr 11, 2024
3c472a0
test: update existing tests
Oighty Apr 11, 2024
7dab3a7
test: add test to confirm auction behavior consistent even with small…
Oighty Apr 11, 2024
708b7b1
Typo
0xJem Apr 12, 2024
8fac8c7
Add tests for precision in queue
0xJem Apr 12, 2024
e28e58a
Redundant TODO
0xJem Apr 12, 2024
ec551be
fix: catalogue fee calculations
Oighty Apr 15, 2024
cf6cd9e
fix: cap curator fee at the auction type max on auction creation
Oighty Apr 18, 2024
1217c79
Merge pull request #158 from Axis-Fi/cap-curator-fee
Oighty Apr 20, 2024
5cffeb0
Merge pull request #153 from Axis-Fi/fix-catalogue-estimate
Oighty Apr 20, 2024
6af45ae
Merge pull request #146 from Axis-Fi/fix-queue-price-check
Oighty Apr 20, 2024
c5170e5
Merge pull request #145 from Axis-Fi/fix-refund-dos
Oighty Apr 20, 2024
f6ffbd7
Merge pull request #144 from Axis-Fi/fix-blast-config
Oighty Apr 20, 2024
d6a7c86
Merge pull request #117 from Axis-Fi/fix-review-minauctionduration
Oighty Apr 20, 2024
9a9d842
Merge pull request #116 from Axis-Fi/fix-review-late-linear-vesting
Oighty Apr 20, 2024
69df098
Merge pull request #105 from Axis-Fi/fix-review-cancel-auction-2
Oighty Apr 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 33 additions & 14 deletions script/deploy/AxisOriginDeploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {BlastAtomicAuctionHouse} from "src/blast/BlastAtomicAuctionHouse.sol";
import {BlastBatchAuctionHouse} from "src/blast/BlastBatchAuctionHouse.sol";
import {AtomicCatalogue} from "src/AtomicCatalogue.sol";
import {BlastEMPAM} from "src/blast/modules/auctions/BlastEMPAM.sol";
import {BlastFPAM} from "src/blast/modules/auctions/BlastFPAM.sol";
import {BlastLinearVesting} from "src/blast/modules/derivatives/BlastLinearVesting.sol";

contract AxisOriginDeploy is Script {
Expand All @@ -17,8 +18,13 @@ contract AxisOriginDeploy is Script {
AtomicCatalogue public atomicCatalogue;
// BlastFPAM public fpam;
BlastEMPAM public empam;
BlastLinearVesting public linearVesting;
BlastFPAM public fpam;
BlastLinearVesting public linearVestingA;
BlastLinearVesting public linearVestingB;
address public constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
address public blast;
address public weth;
address public usdb;

function deploy() public {
// Load the protocol address to receive fees at
Expand Down Expand Up @@ -46,36 +52,49 @@ contract AxisOriginDeploy is Script {
// vm.toString(bytecode)
// );

// TODO set blast, weth, usdb

// Load salt for Auction House
bytes32 atomicSalt = vm.envBytes32("ATOMIC_AUCTION_HOUSE_SALT");
bytes32 batchSalt = vm.envBytes32("BATCH_AUCTION_HOUSE_SALT");

atomicAuctionHouse =
new BlastAtomicAuctionHouse{salt: atomicSalt}(msg.sender, protocol, PERMIT2);
atomicAuctionHouse = new BlastAtomicAuctionHouse{salt: atomicSalt}(
msg.sender, protocol, PERMIT2, blast, weth, usdb
);
console2.log("BlastAtomicAuctionHouse deployed at: ", address(atomicAuctionHouse));
batchAuctionHouse =
new BlastBatchAuctionHouse{salt: batchSalt}(msg.sender, protocol, PERMIT2);
batchAuctionHouse = new BlastBatchAuctionHouse{salt: batchSalt}(
msg.sender, protocol, PERMIT2, blast, weth, usdb
);
console2.log("BlastBatchAuctionHouse deployed at: ", address(batchAuctionHouse));

atomicCatalogue = new AtomicCatalogue(address(atomicAuctionHouse));
console2.log("Catalogue deployed at: ", address(atomicCatalogue));

empam = new BlastEMPAM(address(batchAuctionHouse));
empam = new BlastEMPAM(address(batchAuctionHouse), blast);
console2.log("BlastEMPAM deployed at: ", address(empam));

batchAuctionHouse.installModule(empam);
console2.log("BlastEMPAM installed at BatchAuctionHouse");

// TODO FPA
fpam = new BlastFPAM(address(atomicAuctionHouse), blast);
console2.log("BlastFPAM deployed at: ", address(fpam));

atomicAuctionHouse.installModule(fpam);
console2.log("BlastFPAM installed at AtomicAuctionHouse");

// Linear vesting A
linearVestingA = new BlastLinearVesting(address(atomicAuctionHouse), blast);
console2.log("BlastLinearVesting A deployed at: ", address(linearVestingA));

atomicAuctionHouse.installModule(linearVestingA);
console2.log("BlastLinearVesting A installed at AtomicAuctionHouse");

// Linear vesting
linearVesting = new BlastLinearVesting(address(batchAuctionHouse));
console2.log("BlastLinearVesting deployed at: ", address(linearVesting));
// Linear vesting B
linearVestingB = new BlastLinearVesting(address(batchAuctionHouse), blast);
console2.log("BlastLinearVesting A deployed at: ", address(linearVestingB));

batchAuctionHouse.installModule(linearVesting);
console2.log("BlastLinearVesting installed at BatchAuctionHouse");
atomicAuctionHouse.installModule(linearVesting);
console2.log("BlastLinearVesting installed at AtomicAuctionHouse");
batchAuctionHouse.installModule(linearVestingB);
console2.log("BlastLinearVesting B installed at BatchAuctionHouse");

vm.stopBroadcast();
}
Expand Down
12 changes: 6 additions & 6 deletions src/AtomicCatalogue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ contract AtomicCatalogue is Catalogue {
// Get price from module (in quote token units)
uint256 price = module.priceFor(lotId_, payout_);

// Calculate fee estimate assuming there is a referrer and add to price
price += _calculateFeeEstimate(keycodeFromVeecode(routing.auctionReference), price);
// Calculate price with fee estimate
price = _withFee(keycodeFromVeecode(routing.auctionReference), price);

return price;
}
Expand All @@ -65,18 +65,18 @@ contract AtomicCatalogue is Catalogue {
uint256 maxAmount = module.maxAmountAccepted(lotId_);

// Calculate fee estimate assuming there is a referrer and add to max amount
maxAmount += _calculateFeeEstimate(keycodeFromVeecode(routing.auctionReference), maxAmount);
maxAmount = _withFee(keycodeFromVeecode(routing.auctionReference), maxAmount);

return maxAmount;
}

// ========== INTERNAL UTILITY FUNCTIONS ========== //

/// @notice Estimates fees for a `priceFor` or `maxAmountAccepted` calls
function _calculateFeeEstimate(
/// @notice Adds a conservative fee estimate to `priceFor` or `maxAmountAccepted` calls
function _withFee(
Keycode auctionType_,
uint256 price_
) internal view returns (uint256 feeEstimate) {
) internal view returns (uint256 priceWithFee) {
// In this case we have to invert the fee calculation
// We provide a conservative estimate by assuming there is a referrer and rounding up
(uint48 fee, uint48 referrerFee,) = FeeManager(auctionHouse).fees(auctionType_);
Expand Down
21 changes: 13 additions & 8 deletions src/BatchAuctionHouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ abstract contract BatchRouter {
///
/// @param lotId_ Lot ID
/// @param bidId_ Bid ID
function refundBid(uint96 lotId_, uint64 bidId_) external virtual;
/// @param index_ Index of the bid in the auction's bid list
function refundBid(uint96 lotId_, uint64 bidId_, uint256 index_) external virtual;

/// @notice Claim bid payouts and/or refunds after a batch auction has settled
/// @dev The implementing function must perform the following:
Expand Down Expand Up @@ -272,7 +273,7 @@ contract BatchAuctionHouse is AuctionHouse, BatchRouter {

// Record the bid on the auction module
// The module will determine if the bid is valid - minimum bid size, minimum price, auction status, etc
bidId = _getBatchModuleForId(params_.lotId).bid(
bidId = getBatchModuleForId(params_.lotId).bid(
params_.lotId, msg.sender, params_.referrer, params_.amount, params_.auctionData
);

Expand Down Expand Up @@ -304,7 +305,11 @@ contract BatchAuctionHouse is AuctionHouse, BatchRouter {
/// - the lot ID is invalid
/// - the auction module reverts when cancelling the bid
/// - re-entrancy is detected
function refundBid(uint96 lotId_, uint64 bidId_) external override nonReentrant {
function refundBid(
uint96 lotId_,
uint64 bidId_,
uint256 index_
) external override nonReentrant {
_isLotValid(lotId_);

// Transfer the quote token to the bidder
Expand All @@ -314,7 +319,7 @@ contract BatchAuctionHouse is AuctionHouse, BatchRouter {
msg.sender,
// Refund the bid on the auction module
// The auction module is responsible for validating the bid and authorizing the caller
_getBatchModuleForId(lotId_).refundBid(lotId_, bidId_, msg.sender),
getBatchModuleForId(lotId_).refundBid(lotId_, bidId_, index_, msg.sender),
false
);

Expand All @@ -333,7 +338,7 @@ contract BatchAuctionHouse is AuctionHouse, BatchRouter {
// Claim the bids on the auction module
// The auction module is responsible for validating the bid and authorizing the caller
(BatchAuction.BidClaim[] memory bidClaims, bytes memory auctionOutput) =
_getBatchModuleForId(lotId_).claimBids(lotId_, bidIds_);
getBatchModuleForId(lotId_).claimBids(lotId_, bidIds_);

// Load routing data for the lot
Routing storage routing = lotRouting[lotId_];
Expand Down Expand Up @@ -410,7 +415,7 @@ contract BatchAuctionHouse is AuctionHouse, BatchRouter {

// Settle the lot on the auction module and get the winning bids
// Reverts if the auction cannot be settled yet
BatchAuctionModule module = _getBatchModuleForId(lotId_);
BatchAuctionModule module = getBatchModuleForId(lotId_);

// Settle the auction
(totalIn_, totalOut_, auctionOutput_) = module.settle(lotId_);
Expand Down Expand Up @@ -439,7 +444,7 @@ contract BatchAuctionHouse is AuctionHouse, BatchRouter {

// Call auction module to validate and update data
(uint256 purchased_, uint256 sold_, uint256 capacity_) =
_getBatchModuleForId(lotId_).claimProceeds(lotId_);
getBatchModuleForId(lotId_).claimProceeds(lotId_);

// Load data for the lot
Routing storage routing = lotRouting[lotId_];
Expand Down Expand Up @@ -511,7 +516,7 @@ contract BatchAuctionHouse is AuctionHouse, BatchRouter {

// ========== INTERNAL FUNCTIONS ========== //

function _getBatchModuleForId(uint96 lotId_) internal view returns (BatchAuctionModule) {
function getBatchModuleForId(uint96 lotId_) public view returns (BatchAuctionModule) {
return BatchAuctionModule(address(_getModuleForId(lotId_)));
}
}
24 changes: 18 additions & 6 deletions src/BatchCatalogue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
pragma solidity 0.8.19;

import {Catalogue} from "src/bases/Catalogue.sol";
import {BatchAuction} from "src/modules/auctions/BatchAuctionModule.sol";
import {AuctionHouse} from "src/bases/AuctionHouse.sol";
import {FeeManager} from "src/bases/FeeManager.sol";
import {keycodeFromVeecode, Keycode} from "src/modules/Modules.sol";
import {BatchAuctionModule} from "src/modules/auctions/BatchAuctionModule.sol";
import {BatchAuctionHouse} from "src/BatchAuctionHouse.sol";

/// @notice Contract that provides view functions for Batch Auctions
contract BatchCatalogue is Catalogue {
Expand All @@ -15,7 +13,21 @@ contract BatchCatalogue is Catalogue {

// ========== BATCH AUCTION ========== //

// ========== RETRIEVING AUCTION IDS ========== //
// ========== RETRIEVING BIDS ========== //

// TODO determine if we even need a batch catalogue. EMP has most status' locally, instead of at the batch level.
/// @notice Get a range of bids for a batch auction, based on their current stored order
/// @dev This function is used to iterate through bids offline to find indexes for removing a bid
/// @param lotId_ The ID of the lot
/// @param start_ The index to start retrieving bid IDs from
/// @param count_ The number of bids to retrieve
function getBidIds(
uint96 lotId_,
uint256 start_,
uint256 count_
) public view returns (uint64[] memory) {
BatchAuctionModule module = BatchAuctionHouse(auctionHouse).getBatchModuleForId(lotId_);

// Validate on the start index and count is done at the module level
return module.getBidIds(lotId_, start_, count_);
}
}
9 changes: 8 additions & 1 deletion src/bases/AuctionHouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,14 @@ abstract contract AuctionHouse is WithModules, ReentrancyGuard, FeeManager {
lotFee.curated = false;

Fees storage auctionFees = fees[routing_.auctionType];
lotFee.curatorFee = auctionFees.curator[routing_.curator];

// Check that the curator's configured fee does not exceed the protocol max
// If it does, set the fee to the max
uint48 maxCuratorFee = auctionFees.maxCuratorFee;
uint48 curatorFee = auctionFees.curator[routing_.curator];
lotFee.curatorFee = curatorFee > maxCuratorFee ? maxCuratorFee : curatorFee;

// Snapshot the protocol and referrer fees
lotFee.protocolFee = auctionFees.protocol;
lotFee.referrerFee = auctionFees.referrer;
}
Expand Down
72 changes: 7 additions & 65 deletions src/blast/BlastAtomicAuctionHouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,17 @@
pragma solidity 0.8.19;

import {AtomicAuctionHouse} from "src/AtomicAuctionHouse.sol";
import {Veecode} from "src/modules/Modules.sol";

enum YieldMode {
AUTOMATIC,
VOID,
CLAIMABLE
}

interface IBlast {
function configureClaimableGas() external;
function claimMaxGas(
address contractAddress,
address recipientOfGas
) external returns (uint256);
}

interface IERC20Rebasing {
// changes the yield mode of the caller and update the balance
// to reflect the configuration
function configure(YieldMode) external returns (uint256);
// "claimable" yield mode accounts can call this this claim their yield
// to another address
function claim(address recipient, uint256 amount) external returns (uint256);
// read the claimable amount for an account
function getClaimableAmount(address account) external view returns (uint256);
}

contract BlastAtomicAuctionHouse is AtomicAuctionHouse {
// ========== STATE VARIABLES ========== //

/// @notice Blast contract for claiming gas fees
IBlast internal constant _BLAST = IBlast(0x4300000000000000000000000000000000000002);

/// @notice Address of the WETH contract on Blast
IERC20Rebasing internal constant _WETH =
IERC20Rebasing(0x4200000000000000000000000000000000000023);

/// @notice Address of the USDB contract on Blast
IERC20Rebasing internal constant _USDB =
IERC20Rebasing(0x4200000000000000000000000000000000000022);
import {BlastAuctionHouse} from "src/blast/BlastAuctionHouse.sol";

contract BlastAtomicAuctionHouse is AtomicAuctionHouse, BlastAuctionHouse {
// ========== CONSTRUCTOR ========== //

constructor(
address owner_,
address protocol_,
address permit2_
) AtomicAuctionHouse(owner_, protocol_, permit2_) {
// Set the yield mode to claimable for the WETH and USDB tokens
_WETH.configure(YieldMode.CLAIMABLE);
_USDB.configure(YieldMode.CLAIMABLE);

// Set gas fees to claimable
_BLAST.configureClaimableGas();
}

// ========== CLAIM FUNCTIONS ========== //

function claimYieldAndGas() external {
// Claim the yield for the WETH and USDB tokens and send to protocol
_WETH.claim(_protocol, _WETH.getClaimableAmount(address(this)));
_USDB.claim(_protocol, _USDB.getClaimableAmount(address(this)));

// Claim the gas consumed by this contract, send to protocol
_BLAST.claimMaxGas(address(this), _protocol);
}

function claimModuleGas(Veecode reference_) external {
// Claim the gas consumed by the module, send to protocol
_BLAST.claimMaxGas(address(_getModuleIfInstalled(reference_)), _protocol);
}
address permit2_,
address blast_,
address weth_,
address usdb_
) AtomicAuctionHouse(owner_, protocol_, permit2_) BlastAuctionHouse(blast_, weth_, usdb_) {}
}
Loading