Source Code
Overview
ETH Balance
0 ETH
Token Holdings
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 25 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Create Auction | 8808093 | 353 days ago | IN | 0 ETH | 0.0091029 | ||||
Create Auction | 8789854 | 356 days ago | IN | 0 ETH | 0.03662873 | ||||
Create Auction | 8787139 | 357 days ago | IN | 0 ETH | 0.01379082 | ||||
Create Auction | 8778989 | 358 days ago | IN | 0 ETH | 0.00715982 | ||||
Create Auction | 8104442 | 475 days ago | IN | 0 ETH | 0.00028612 | ||||
Create Auction | 8039550 | 486 days ago | IN | 0 ETH | 0.00028191 | ||||
Create Auction | 7766525 | 532 days ago | IN | 0 ETH | 0.00028191 | ||||
Create Auction | 7766507 | 532 days ago | IN | 0 ETH | 0.00028184 | ||||
Create Auction | 7764799 | 532 days ago | IN | 0 ETH | 0.00028186 | ||||
Create Auction | 7747689 | 535 days ago | IN | 0 ETH | 0.00028189 | ||||
Create Auction | 7747680 | 535 days ago | IN | 0 ETH | 0.00028186 | ||||
Create Auction | 7719267 | 540 days ago | IN | 0 ETH | 0.00028198 | ||||
Create Auction | 7712727 | 541 days ago | IN | 0 ETH | 0.00028184 | ||||
Create Auction | 7711709 | 541 days ago | IN | 0 ETH | 0.00028193 | ||||
Create Auction | 7700426 | 543 days ago | IN | 0 ETH | 0.00028191 | ||||
Create Auction | 7690198 | 545 days ago | IN | 0 ETH | 0.00028186 | ||||
Create Auction | 7689935 | 545 days ago | IN | 0 ETH | 0.00018794 | ||||
Create Auction | 7689901 | 545 days ago | IN | 0 ETH | 0.00018794 | ||||
Create Auction | 7689889 | 545 days ago | IN | 0 ETH | 0.000162 | ||||
Create Auction | 7689437 | 545 days ago | IN | 0 ETH | 0.00028195 | ||||
Create Auction | 7689369 | 545 days ago | IN | 0 ETH | 0.00028191 | ||||
Create Auction | 7689204 | 545 days ago | IN | 0 ETH | 0.00028189 | ||||
Create Auction | 7689182 | 545 days ago | IN | 0 ETH | 0.00028191 | ||||
Create Auction | 7689138 | 545 days ago | IN | 0 ETH | 0.00028191 | ||||
0x60a06040 | 7688568 | 545 days ago | IN | Create: DualAuctionFactory | 0 ETH | 0.00001993 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
8808093 | 353 days ago | 0 ETH | ||||
8808093 | 353 days ago | Contract Creation | 0 ETH | |||
8789854 | 356 days ago | 0 ETH | ||||
8789854 | 356 days ago | Contract Creation | 0 ETH | |||
8787139 | 357 days ago | 0 ETH | ||||
8787139 | 357 days ago | Contract Creation | 0 ETH | |||
8778989 | 358 days ago | 0 ETH | ||||
8778989 | 358 days ago | Contract Creation | 0 ETH | |||
8104442 | 475 days ago | 0 ETH | ||||
8104442 | 475 days ago | Contract Creation | 0 ETH | |||
8039550 | 486 days ago | 0 ETH | ||||
8039550 | 486 days ago | Contract Creation | 0 ETH | |||
7766525 | 532 days ago | 0 ETH | ||||
7766525 | 532 days ago | Contract Creation | 0 ETH | |||
7766507 | 532 days ago | 0 ETH | ||||
7766507 | 532 days ago | Contract Creation | 0 ETH | |||
7764799 | 532 days ago | 0 ETH | ||||
7764799 | 532 days ago | Contract Creation | 0 ETH | |||
7747689 | 535 days ago | 0 ETH | ||||
7747689 | 535 days ago | Contract Creation | 0 ETH | |||
7747680 | 535 days ago | 0 ETH | ||||
7747680 | 535 days ago | Contract Creation | 0 ETH | |||
7719267 | 540 days ago | 0 ETH | ||||
7719267 | 540 days ago | Contract Creation | 0 ETH | |||
7712727 | 541 days ago | 0 ETH |
Loading...
Loading
Contract Name:
DualAuctionFactory
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import {ClonesWithImmutableArgs} from "clones-with-immutable-args/ClonesWithImmutableArgs.sol"; import {DualAuction} from "./DualAuction.sol"; import {IDualAuction} from "./interfaces/IDualAuction.sol"; import {IAuctionFactory} from "./interfaces/IAuctionFactory.sol"; contract DualAuctionFactory is IAuctionFactory { using ClonesWithImmutableArgs for address; address public immutable implementation; constructor(address _implementation) { if (_implementation == address(0)) revert InvalidParams(); implementation = _implementation; } /** * @inheritdoc IAuctionFactory */ function createAuction( address bidAsset, address askAsset, uint256 minPrice, uint256 maxPrice, uint256 tickWidth, uint256 priceDenominator, uint256 endDate ) public returns (IDualAuction) { bytes memory data = abi.encodePacked( bidAsset, askAsset, minPrice, maxPrice, tickWidth, priceDenominator, endDate ); DualAuction clone = DualAuction(implementation.clone(data)); clone.initialize(); emit AuctionCreated(bidAsset, askAsset, endDate, msg.sender, address(clone)); return clone; } }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.4; /// @title ClonesWithImmutableArgs /// @author wighawag, zefram.eth /// @notice Enables creating clone contracts with immutable args library ClonesWithImmutableArgs { error CreateFail(); /// @notice Creates a clone proxy of the implementation contract, with immutable args /// @dev data cannot exceed 65535 bytes, since 2 bytes are used to store the data length /// @param implementation The implementation contract to clone /// @param data Encoded immutable args /// @return instance The address of the created clone function clone(address implementation, bytes memory data) internal returns (address payable instance) { // unrealistic for memory ptr or data length to exceed 256 bits unchecked { uint256 extraLength = data.length + 2; // +2 bytes for telling how much data there is appended to the call uint256 creationSize = 0x41 + extraLength; uint256 runSize = creationSize - 10; uint256 dataPtr; uint256 ptr; // solhint-disable-next-line no-inline-assembly assembly { ptr := mload(0x40) // ------------------------------------------------------------------------------------------------------------- // CREATION (10 bytes) // ------------------------------------------------------------------------------------------------------------- // 61 runtime | PUSH2 runtime (r) | r | – mstore( ptr, 0x6100000000000000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x01), shl(240, runSize)) // size of the contract running bytecode (16 bits) // creation size = 0a // 3d | RETURNDATASIZE | 0 r | – // 81 | DUP2 | r 0 r | – // 60 creation | PUSH1 creation (c) | c r 0 r | – // 3d | RETURNDATASIZE | 0 c r 0 r | – // 39 | CODECOPY | 0 r | [0-runSize): runtime code // f3 | RETURN | | [0-runSize): runtime code // ------------------------------------------------------------------------------------------------------------- // RUNTIME (55 bytes + extraLength) // ------------------------------------------------------------------------------------------------------------- // 3d | RETURNDATASIZE | 0 | – // 3d | RETURNDATASIZE | 0 0 | – // 3d | RETURNDATASIZE | 0 0 0 | – // 3d | RETURNDATASIZE | 0 0 0 0 | – // 36 | CALLDATASIZE | cds 0 0 0 0 | – // 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | – // 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | – // 37 | CALLDATACOPY | 0 0 0 0 | [0, cds) = calldata // 61 | PUSH2 extra | extra 0 0 0 0 | [0, cds) = calldata mstore( add(ptr, 0x03), 0x3d81600a3d39f33d3d3d3d363d3d376100000000000000000000000000000000 ) mstore(add(ptr, 0x13), shl(240, extraLength)) // 60 0x37 | PUSH1 0x37 | 0x37 extra 0 0 0 0 | [0, cds) = calldata // 0x37 (55) is runtime size - data // 36 | CALLDATASIZE | cds 0x37 extra 0 0 0 0 | [0, cds) = calldata // 39 | CODECOPY | 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 36 | CALLDATASIZE | cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 61 extra | PUSH2 extra | extra cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData mstore( add(ptr, 0x15), 0x6037363936610000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x1b), shl(240, extraLength)) // 01 | ADD | cds+extra 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 73 addr | PUSH20 0x123… | addr 0 cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData mstore( add(ptr, 0x1d), 0x013d730000000000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x20), shl(0x60, implementation)) // 5a | GAS | gas addr 0 cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // f4 | DELEGATECALL | success 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3d | RETURNDATASIZE | rds success 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3d | RETURNDATASIZE | rds rds success 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 93 | SWAP4 | 0 rds success 0 rds | [0, cds) = calldata, [cds, cds+0x37) = extraData // 80 | DUP1 | 0 0 rds success 0 rds | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3e | RETURNDATACOPY | success 0 rds | [0, rds) = return data (there might be some irrelevant leftovers in memory [rds, cds+0x37) when rds < cds+0x37) // 60 0x35 | PUSH1 0x35 | 0x35 sucess 0 rds | [0, rds) = return data // 57 | JUMPI | 0 rds | [0, rds) = return data // fd | REVERT | – | [0, rds) = return data // 5b | JUMPDEST | 0 rds | [0, rds) = return data // f3 | RETURN | – | [0, rds) = return data mstore( add(ptr, 0x34), 0x5af43d3d93803e603557fd5bf300000000000000000000000000000000000000 ) } // ------------------------------------------------------------------------------------------------------------- // APPENDED DATA (Accessible from extcodecopy) // (but also send as appended data to the delegatecall) // ------------------------------------------------------------------------------------------------------------- extraLength -= 2; uint256 counter = extraLength; uint256 copyPtr = ptr + 0x41; // solhint-disable-next-line no-inline-assembly assembly { dataPtr := add(data, 32) } for (; counter >= 32; counter -= 32) { // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, mload(dataPtr)) } copyPtr += 32; dataPtr += 32; } uint256 mask = ~(256**(32 - counter) - 1); // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, and(mload(dataPtr), mask)) } copyPtr += counter; // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, shl(240, extraLength)) } // solhint-disable-next-line no-inline-assembly assembly { instance := create(0, ptr, creationSize) } if (instance == address(0)) { revert CreateFail(); } } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {ReentrancyGuardUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol"; import {ERC1155SupplyUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155SupplyUpgradeable.sol"; import {Initializable} from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import {Clone} from "clones-with-immutable-args/Clone.sol"; import {IDualAuction} from "./interfaces/IDualAuction.sol"; import {AuctionImmutableArgs} from "./utils/AuctionImmutableArgs.sol"; import {AuctionConversions} from "./utils/AuctionConversions.sol"; /** * @notice DualAuction contract */ contract DualAuction is ERC1155SupplyUpgradeable, Clone, ReentrancyGuardUpgradeable, AuctionImmutableArgs, AuctionConversions, IDualAuction { /// @notice the maximum allowed price is 2^255 because we save the top bit for /// differentiating between bids and asks in the token id uint256 internal constant MAXIMUM_ALLOWED_PRICE = 2**255 - 1; /// @notice The number of ticks allowed between the minimum and maximum price (inclusive) uint256 internal constant NUM_TICKS = 100; /// @notice The highest bid received so far uint256 public maxBid; /// @notice The lowest ask received so far uint256 public minAsk; /// @notice The clearing bid price of the auction, set after settlement uint256 public clearingBidPrice; /// @notice The clearing ask price of the auction, set after settlement uint256 public clearingAskPrice; /// @notice The number of bid tokens cleared at the tick closest to clearing price uint256 public bidTokensClearedAtClearing; /// @notice The number of ask tokens cleared at the tick closest to clearing price uint256 public askTokensClearedAtClearing; /// @notice True if the auction has been settled, else false bool public settled; /** * @notice Ensures that the given price is valid * validity is defined as in range (minPrice, maxPrice) and * on a valid tick */ modifier onlyValidPrice(uint256 price) { if (price < minPrice() || price > maxPrice()) revert InvalidPrice(); if ((price - minPrice()) % tickWidth() != 0) revert InvalidPrice(); _; } /** * @notice Ensures that the auction is active */ modifier onlyAuctionActive() { if (block.timestamp >= endDate()) revert AuctionHasEnded(); _; } /** * @notice Ensures that the auction is finalized */ modifier onlyAuctionEnded() { if (block.timestamp < endDate()) revert AuctionIsActive(); _; } /** * @notice Ensures that the auction has been settled */ modifier onlyAuctionSettled() { if (!settled) revert AuctionHasNotSettled(); _; } /** * @notice Initializes the auction, should be called by DualAuctionFactory */ function initialize() external initializer { __ERC1155_init(""); __ERC1155Supply_init(); __ReentrancyGuard_init(); if (bidAsset() == askAsset()) revert MatchingAssets(); if ( address(bidAsset()) == address(0) || address(askAsset()) == address(0) ) revert ZeroAddressAsset(); if (minPrice() == 0) revert InvalidPrice(); if (minPrice() >= maxPrice()) revert InvalidPrice(); if (maxPrice() > MAXIMUM_ALLOWED_PRICE) revert InvalidPrice(); if ((maxPrice() - minPrice()) != (NUM_TICKS - 1) * tickWidth()) revert InvalidPrice(); if (priceDenominator() == 0) revert InvalidPrice(); if (endDate() <= block.timestamp) revert AuctionHasEnded(); minAsk = type(uint256).max; } /** * @inheritdoc IDualAuction */ function bid(uint256 amountIn, uint256 price) external onlyValidPrice(price) onlyAuctionActive nonReentrant returns (uint256) { if (amountIn == 0) revert ZeroAmount(); if (price > maxBid) maxBid = price; uint256 preTransferBalance = bidAsset().balanceOf(address(this)); SafeTransferLib.safeTransferFrom( bidAsset(), msg.sender, address(this), amountIn ); uint256 postTransferBalance = bidAsset().balanceOf(address(this)); uint256 bidAmount = postTransferBalance - preTransferBalance; _mint(msg.sender, toBidTokenId(price), bidAmount, ""); emit Bid(msg.sender, amountIn, bidAmount, price); return bidAmount; } /** * @inheritdoc IDualAuction */ function ask(uint256 amountIn, uint256 price) external onlyValidPrice(price) onlyAuctionActive nonReentrant returns (uint256) { if (amountIn == 0) revert ZeroAmount(); if (minAsk == 0 || price < minAsk) minAsk = price; uint256 preTransferBalance = askAsset().balanceOf(address(this)); SafeTransferLib.safeTransferFrom( askAsset(), msg.sender, address(this), amountIn ); uint256 postTransferBalance = askAsset().balanceOf(address(this)); uint256 askAmount = postTransferBalance - preTransferBalance; _mint(msg.sender, toAskTokenId(price), askAmount, ""); emit Ask(msg.sender, amountIn, askAmount, price); return askAmount; } /** * @inheritdoc IDualAuction */ function settle() external onlyAuctionEnded returns (uint256) { if (settled) revert AuctionHasSettled(); settled = true; uint256 currentBid = maxBid; uint256 currentAsk = minAsk; uint256 _tickWidth = tickWidth(); // no overlap, nothing will be cleared if (currentBid < currentAsk) { emit Settle(msg.sender, 0); return 0; } uint256 lowBid = currentBid; uint256 highAsk = currentAsk; uint256 currentAskTokens; uint256 currentDesiredAskTokens; uint256 lastBidClear; uint256 lastAskClear; while ( currentBid >= currentAsk && currentBid >= minPrice() && currentAsk <= maxPrice() ) { if (currentAskTokens == 0) { currentAskTokens = totalSupply(toAskTokenId(currentAsk)); if (currentAskTokens > 0) lastBidClear = 0; } if (currentDesiredAskTokens == 0) { currentDesiredAskTokens = bidToAsk( totalSupply(toBidTokenId(currentBid)), currentBid ); if (currentDesiredAskTokens > 0) lastAskClear = 0; } uint256 cleared = min(currentAskTokens, currentDesiredAskTokens); if (cleared > 0) { currentAskTokens -= cleared; currentDesiredAskTokens -= cleared; lastBidClear += cleared; lastAskClear += cleared; highAsk = currentAsk; lowBid = currentBid; } if (currentAskTokens == 0) currentAsk += _tickWidth; if (currentDesiredAskTokens == 0) currentBid -= _tickWidth; } clearingBidPrice = lowBid; clearingAskPrice = highAsk; uint256 _clearingPrice = clearingPrice(); askTokensClearedAtClearing = lastAskClear; bidTokensClearedAtClearing = askToBid(lastBidClear, _clearingPrice); emit Settle(msg.sender, _clearingPrice); return _clearingPrice; } /** * @inheritdoc IDualAuction */ function redeem(uint256 tokenId, uint256 amount) external onlyAuctionSettled nonReentrant returns (uint256 bidTokens, uint256 askTokens) { if (amount == 0) revert ZeroAmount(); (bidTokens, askTokens) = shareValue(amount, tokenId); bool isBid = isBidTokenId(tokenId); _burn(msg.sender, tokenId, amount); if (bidTokens > 0) { if (!isBid && toPrice(tokenId) == clearingAskPrice) bidTokensClearedAtClearing -= bidTokens; bidTokens = min(bidTokens, bidAsset().balanceOf(address(this))); SafeTransferLib.safeTransfer(bidAsset(), msg.sender, bidTokens); } if (askTokens > 0) { if (isBid && toPrice(tokenId) == clearingBidPrice) askTokensClearedAtClearing -= askTokens; askTokens = min(askTokens, askAsset().balanceOf(address(this))); SafeTransferLib.safeTransfer(askAsset(), msg.sender, askTokens); } emit Redeem(msg.sender, tokenId, amount, bidTokens, askTokens); } /** * @inheritdoc IDualAuction */ function clearingPrice() public view override returns (uint256) { return (clearingBidPrice + clearingAskPrice) / 2; } /** * @dev returns the value of the shares after settlement * @param shareAmount The number of bid/ask slips to check * @param tokenId The token id of the share * @return bidTokens The number of bid tokens the share tokens are worth * @return askTokens The number of ask tokens the share tokens are worth */ function shareValue(uint256 shareAmount, uint256 tokenId) internal view returns (uint256 bidTokens, uint256 askTokens) { uint256 price = toPrice(tokenId); uint256 _clearingPrice = clearingPrice(); if (isBidTokenId(tokenId)) { uint256 _clearingBid = clearingBidPrice; if (_clearingPrice == 0 || price < _clearingBid) { // not cleared at all return (shareAmount, 0); } else if (price > _clearingBid) { // fully cleared uint256 cleared = bidToAsk(shareAmount, price); return ( shareAmount - askToBid(cleared, _clearingPrice), cleared ); } else { // partially cleared uint256 cleared = FixedPointMathLib.mulDivDown( shareAmount, askTokensClearedAtClearing, totalSupply(tokenId) ); return ( shareAmount - askToBid(cleared, _clearingPrice), cleared ); } } else { uint256 _clearingAsk = clearingAskPrice; if (_clearingPrice == 0 || price > _clearingAsk) { // not cleared at all return (0, shareAmount); } else if (price < _clearingAsk) { // fully cleared, all ask tokens match at clearing price return (askToBid(shareAmount, _clearingPrice), 0); } else { // partially cleared uint256 cleared = FixedPointMathLib.mulDivDown( shareAmount, bidTokensClearedAtClearing, totalSupply(tokenId) ); uint256 askValue = askToBid(shareAmount, _clearingPrice); // sometimes due to floor rounding ask value is slightly too high uint256 notCleared = askValue <= cleared ? 0 : bidToAsk(askValue - cleared, _clearingPrice); return (cleared, notCleared); } } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {ERC1155SupplyUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/token/ERC1155/extensions/ERC1155SupplyUpgradeable.sol"; import {Initializable} from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import {OwnableUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; import {Clone} from "clones-with-immutable-args/Clone.sol"; import {IAuctionConversions} from "./IAuctionConversions.sol"; interface IDualAuction is IAuctionConversions { /// @notice Zero address given for asset error ZeroAddressAsset(); /// @notice Matching buy/sell assets error MatchingAssets(); /// @notice Zero amount of asset given error ZeroAmount(); /// @notice The end date has not yet passed error AuctionIsActive(); /// @notice The end date has passed error AuctionHasEnded(); /// @notice The auction has not been settled error AuctionHasNotSettled(); /// @notice The auction has already been settled error AuctionHasSettled(); /// @notice The auction ended with no clearing price error NoClearingPrice(); /// @notice The settlement somehow ended with cleared tokens but no clearing price error SettleHasFailed(); /// @notice Event declaring that a bid was made event Bid( address indexed actor, uint256 amountIn, uint256 amountOut, uint256 indexed price ); /// @notice Event declaring that an ask was made event Ask( address indexed actor, uint256 amountIn, uint256 amountOut, uint256 indexed price ); /// @notice Event notifying about the settlement of an auction event Settle(address indexed actor, uint256 clearingPrice); /// @notice Event notifying about the redemption of share tokens event Redeem( address indexed actor, uint256 indexed tokenId, uint256 shareAmount, uint256 bidValue, uint256 askValue ); /// @notice The highest bid received so far function maxBid() external view returns (uint256); /// @notice The lowest ask received so far function minAsk() external view returns (uint256); /// @notice The clearing price of the auction, set after settlement function clearingPrice() external view returns (uint256); /// @notice True if the auction has been settled, eles false function settled() external view returns (bool); /** * @notice Places a bid using amountIn bidAsset tokens, * for askAsset tokens at the given price * @param amountIn The amount to bid, in bidAsset * @param price the price at which to bid, denominated in terms of bidAsset per askAsset * @return The number of shares output */ function bid(uint256 amountIn, uint256 price) external returns (uint256); /** * @notice Places an ask using amountIn askAsset tokens, * for bidAsset tokens at the given price * @param amountIn The amount to sell, in askAsset * @param price the price at which to ask, denominated in terms of bidAsset per askAsset * @return The number of shares output */ function ask(uint256 amountIn, uint256 price) external returns (uint256); /** * @notice Settles the auction after the end date * @dev iterates through the bids and asks to determine * The clearing price, setting the clearingPrice variable afterwards * @return The settled clearing price, or 0 if none */ function settle() external returns (uint256); /** * @notice Redeems bid/ask slips after the auction has concluded * @param tokenId The id of the bid/ask slip to redeem * @param amount The amount of slips to redeem * @return The number of tokens received */ function redeem(uint256 tokenId, uint256 amount) external returns (uint256, uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import {IDualAuction} from "./IDualAuction.sol"; /** * @notice Interface for Auction factory contracts */ interface IAuctionFactory { event AuctionCreated( address indexed bidAsset, address indexed askAsset, uint256 endDate, address indexed creator, address newAuctionAddress ); /// @notice Some parameters are invalid error InvalidParams(); /** * @notice Creates a new auction * @param bidAsset The asset that bids are made with * @param askAsset The asset that asks are made with * @param minPrice The minimum allowed price in terms of bidAsset * @param maxPrice The maximum allowed price in terms of bidAsset * @param tickWidth The spacing between valid prices * @param endDate The timestamp at which the auction will end */ function createAuction( address bidAsset, address askAsset, uint256 minPrice, uint256 maxPrice, uint256 tickWidth, uint256 priceDenominator, uint256 endDate ) external returns (IDualAuction); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // First, divide z - 1 by the denominator and add 1. // We allow z - 1 to underflow if z is 0, because we multiply the // end result by 0 if z is zero, ensuring we return 0 if z is zero. z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { // Start off with z at 1. z := 1 // Used below to help find a nearby power of 2. let y := x // Find the lowest power of 2 that is at least sqrt(x). if iszero(lt(y, 0x100000000000000000000000000000000)) { y := shr(128, y) // Like dividing by 2 ** 128. z := shl(64, z) // Like multiplying by 2 ** 64. } if iszero(lt(y, 0x10000000000000000)) { y := shr(64, y) // Like dividing by 2 ** 64. z := shl(32, z) // Like multiplying by 2 ** 32. } if iszero(lt(y, 0x100000000)) { y := shr(32, y) // Like dividing by 2 ** 32. z := shl(16, z) // Like multiplying by 2 ** 16. } if iszero(lt(y, 0x10000)) { y := shr(16, y) // Like dividing by 2 ** 16. z := shl(8, z) // Like multiplying by 2 ** 8. } if iszero(lt(y, 0x100)) { y := shr(8, y) // Like dividing by 2 ** 8. z := shl(4, z) // Like multiplying by 2 ** 4. } if iszero(lt(y, 0x10)) { y := shr(4, y) // Like dividing by 2 ** 4. z := shl(2, z) // Like multiplying by 2 ** 2. } if iszero(lt(y, 0x8)) { // Equivalent to 2 ** z. z := shl(1, z) } // Shifting right by 1 is like dividing by 2. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // Compute a rounded down version of z. let zRoundDown := div(x, z) // If zRoundDown is smaller, use it. if lt(zRoundDown, z) { z := zRoundDown } } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { event Debug(bool one, bool two, uint256 retsize); /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/extensions/ERC1155Supply.sol) pragma solidity ^0.8.0; import "../ERC1155Upgradeable.sol"; import "../../../proxy/utils/Initializable.sol"; /** * @dev Extension of ERC1155 that adds tracking of total supply per id. * * Useful for scenarios where Fungible and Non-fungible tokens have to be * clearly identified. Note: While a totalSupply of 1 might mean the * corresponding is an NFT, there is no guarantees that no other token with the * same id are not going to be minted. */ abstract contract ERC1155SupplyUpgradeable is Initializable, ERC1155Upgradeable { function __ERC1155Supply_init() internal onlyInitializing { } function __ERC1155Supply_init_unchained() internal onlyInitializing { } mapping(uint256 => uint256) private _totalSupply; /** * @dev Total amount of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return ERC1155SupplyUpgradeable.totalSupply(id) > 0; } /** * @dev See {ERC1155-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (from == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { _totalSupply[ids[i]] += amounts[i]; } } if (to == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 supply = _totalSupply[id]; require(supply >= amount, "ERC1155: burn amount exceeds totalSupply"); unchecked { _totalSupply[id] = supply - amount; } } } } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = _setInitializedVersion(1); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { bool isTopLevelCall = _setInitializedVersion(version); if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(version); } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { _setInitializedVersion(type(uint8).max); } function _setInitializedVersion(uint8 version) private returns (bool) { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level // of initializers, because in other contexts the contract may have been reentered. if (_initializing) { require( version == 1 && !AddressUpgradeable.isContract(address(this)), "Initializable: contract is already initialized" ); return false; } else { require(_initialized < version, "Initializable: contract is already initialized"); _initialized = version; return true; } } }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.4; /// @title Clone /// @author zefram.eth /// @notice Provides helper functions for reading immutable args from calldata contract Clone { /// @notice Reads an immutable arg with type address /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint256 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := calldataload(add(offset, argOffset)) } } /// @notice Reads a uint256 array stored in the immutable args. /// @param argOffset The offset of the arg in the packed data /// @param arrLen Number of elements in the array /// @return arr The array function _getArgUint256Array(uint256 argOffset, uint64 arrLen) internal pure returns (uint256[] memory arr) { uint256 offset = _getImmutableArgsOffset(); uint256 el; arr = new uint256[](arrLen); for (uint64 i = 0; i < arrLen; i++) { assembly { // solhint-disable-next-line no-inline-assembly el := calldataload(add(add(offset, argOffset), mul(i, 32))) } arr[i] = el; } return arr; } /// @notice Reads an immutable arg with type uint64 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint8 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /// @return offset The offset of the packed immutable args in calldata function _getImmutableArgsOffset() internal pure returns (uint256 offset) { // solhint-disable-next-line no-inline-assembly assembly { offset := sub( calldatasize(), add(shr(240, calldataload(sub(calldatasize(), 2))), 2) ) } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import {ERC20} from "solmate/tokens/ERC20.sol"; import {Clone} from "clones-with-immutable-args/Clone.sol"; /** * @notice Defines the immutable arguments for a dual auction * @dev using the clones-with-immutable-args library * we fetch args from the code section */ contract AuctionImmutableArgs is Clone { /** * @notice The asset being used to make bids * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The asset being used to make bids */ function bidAsset() public pure returns (ERC20) { return ERC20(_getArgAddress(0)); } /** * @notice The asset being used to make asks * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The asset being used to make asks */ function askAsset() public pure returns (ERC20) { return ERC20(_getArgAddress(20)); } /** * @notice The minimum allowed price * @dev prices are denominated as the numerator of the bidAsset/askAsset fraction. priceDenominator is the denominator. * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The minimum allowed price */ function minPrice() public pure returns (uint256) { return _getArgUint256(40); } /** * @notice The maximum allowed price * @dev prices are denominated as the numerator of the bidAsset/askAsset fraction. priceDenominator is the denominator. * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The maximum allowed price */ function maxPrice() public pure returns (uint256) { return _getArgUint256(72); } /** * @notice The width of ticks i.e. allowed prices * @dev prices are denominated as the numerator of the bidAsset/askAsset fraction. priceDenominator is the denominator. * @dev Must evenly divide the range between minPrice and maxPrice by NUM_TICKS = 100. * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The width of ticks */ function tickWidth() public pure returns (uint256) { return _getArgUint256(104); } /** * @notice The underlying denominator used to calculate all the price fractions * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The number of decimals for the bid asset */ function priceDenominator() public pure returns (uint256) { return _getArgUint256(136); } /** * @notice The timestamp at which the auction will end * @dev using ClonesWithImmutableArgs pattern here to save gas * @dev https://github.com/wighawag/clones-with-immutable-args * @return The timestamp at which the auction will end */ function endDate() public pure returns (uint256) { return _getArgUint256(168); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {AuctionImmutableArgs} from "./AuctionImmutableArgs.sol"; import {IAuctionConversions} from "../interfaces/IAuctionConversions.sol"; /** * @notice Defines some helper conversion functions for dual auctions */ contract AuctionConversions is IAuctionConversions, AuctionImmutableArgs { /** * @notice Transforms a price into an ask token id * @dev ask token ids are just the price, with the top bit equal to 1 */ function toAskTokenId(uint256 price) public pure returns (uint256) { if (price >= 2**255) revert InvalidPrice(); // 0b10000000... | price // sets the top bit to 1, leaving the rest unchanged return price | (2**255); } /** * @notice Transforms a price into a bid token id * @dev bid token ids are just the price, with the top bit equal to 0 */ function toBidTokenId(uint256 price) public pure returns (uint256) { if (price >= 2**255) revert InvalidPrice(); // Price is required to be less than 2**255, so we can just return it since top bit is already 0 return price; } /** * @notice Checks if tokenId is a bid token id */ function isBidTokenId(uint256 tokenId) public pure returns (bool) { // Top bit is 0 return (tokenId >> 255) == 0; } /** * @notice Transforms a tokenId into a normal price */ function toPrice(uint256 tokenId) public pure returns (uint256) { // Bit-shifting up and then back down to clear the top bit to 0 return (tokenId << 1) >> 1; } /** * @notice helper to translate ask tokens to bid tokens at a given price * @param askTokens The number of ask tokens to calculate * @param price The price, denominated in bidAssetDecimals * @return The equivalent value of bid tokens */ function askToBid(uint256 askTokens, uint256 price) public pure returns (uint256) { return FixedPointMathLib.mulDivDown( askTokens, price, priceDenominator() ); } /** * @notice helper to translate bid tokens to ask tokens at a given price * @param bidTokens The number of bid tokens to calculate * @param price The price, denominated in bidAssetDecimals * @return The equivalent value of ask tokens */ function bidToAsk(uint256 bidTokens, uint256 price) public pure returns (uint256) { if (price == 0) revert InvalidPrice(); return FixedPointMathLib.mulDivDown( bidTokens, priceDenominator(), price ); } /** * @notice determine the max of two numbers * @param a the first number * @param a the second number * @return the maximum of the two numbers */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @notice determine the min of two numbers * @param a the first number * @param a the second number * @return the minimum of the two numbers */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; interface IAuctionConversions { /// @notice Price out of bounds error InvalidPrice(); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155Upgradeable.sol"; import "./IERC1155ReceiverUpgradeable.sol"; import "./extensions/IERC1155MetadataURIUpgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import "../../utils/introspection/ERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable { using AddressUpgradeable for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ function __ERC1155_init(string memory uri_) internal onlyInitializing { __ERC1155_init_unchained(uri_); } function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) { return interfaceId == type(IERC1155Upgradeable).interfaceId || interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: address zero is not a valid owner"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not owner nor approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: transfer caller is not owner nor approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits a {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[47] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155Upgradeable is IERC165Upgradeable { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165Upgradeable.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155ReceiverUpgradeable is IERC165Upgradeable { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155Upgradeable.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "remappings": [ "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "ds-test/=lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/", "src/=src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_implementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CreateFail","type":"error"},{"inputs":[],"name":"InvalidParams","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bidAsset","type":"address"},{"indexed":true,"internalType":"address","name":"askAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"endDate","type":"uint256"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"address","name":"newAuctionAddress","type":"address"}],"name":"AuctionCreated","type":"event"},{"inputs":[{"internalType":"address","name":"bidAsset","type":"address"},{"internalType":"address","name":"askAsset","type":"address"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"},{"internalType":"uint256","name":"tickWidth","type":"uint256"},{"internalType":"uint256","name":"priceDenominator","type":"uint256"},{"internalType":"uint256","name":"endDate","type":"uint256"}],"name":"createAuction","outputs":[{"internalType":"contract IDualAuction","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b5060405161044a38038061044a83398101604081905261002f91610067565b6001600160a01b03811661005657604051635435b28960e11b815260040160405180910390fd5b6001600160a01b0316608052610097565b60006020828403121561007957600080fd5b81516001600160a01b038116811461009057600080fd5b9392505050565b6080516103936100b7600039600081816040015260fe01526103936000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b578063c15f513e1461007e575b600080fd5b6100627f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61006261008c3660046102ff565b6040516bffffffffffffffffffffffff19606089811b8216602084015288901b16603482015260488101869052606881018590526088810184905260a8810183905260c88101829052600090819060e80160408051601f19818403018152919052905060006101246001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016836101d1565b9050806001600160a01b0316638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561016157600080fd5b505af1158015610175573d6000803e3d6000fd5b5050604080518781526001600160a01b0385811660208301523394508d811693508e16917f940d581882dfdc08832be51562bf530e14c44fed62563ee0caad451c1a5eba73910160405180910390a49998505050505050505050565b8051604051606160f81b81526039820160f081811b60018401526f3d81600a3d39f33d3d3d3d363d3d376160801b600384015260028401901b601383018190526560373639366160d01b6015840152601b83015262013d7360e81b601d830152606085901b6020808401919091526c5af43d3d93803e603557fd5bf360981b60348401526000939260438401929186019084604182015b602082106102875783518152602093840193601f199092019101610268565b835160001960208490036101000a0119908116825260f088901b91830191825286846000f098506001600160a01b0389166102d557604051631d7fde3160e31b815260040160405180910390fd5b505050505050505092915050565b80356001600160a01b03811681146102fa57600080fd5b919050565b600080600080600080600060e0888a03121561031a57600080fd5b610323886102e3565b9650610331602089016102e3565b96999698505050506040850135946060810135946080820135945060a0820135935060c090910135915056fea26469706673582212200230b5a4e549645a8fa54b5a23787d5fd4a423d17eadd1dfe11f93177f22967664736f6c634300080a00330000000000000000000000004a88e71d9afb35bd4eec3e33f3e0320347059e55
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635c60da1b1461003b578063c15f513e1461007e575b600080fd5b6100627f0000000000000000000000004a88e71d9afb35bd4eec3e33f3e0320347059e5581565b6040516001600160a01b03909116815260200160405180910390f35b61006261008c3660046102ff565b6040516bffffffffffffffffffffffff19606089811b8216602084015288901b16603482015260488101869052606881018590526088810184905260a8810183905260c88101829052600090819060e80160408051601f19818403018152919052905060006101246001600160a01b037f0000000000000000000000004a88e71d9afb35bd4eec3e33f3e0320347059e5516836101d1565b9050806001600160a01b0316638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561016157600080fd5b505af1158015610175573d6000803e3d6000fd5b5050604080518781526001600160a01b0385811660208301523394508d811693508e16917f940d581882dfdc08832be51562bf530e14c44fed62563ee0caad451c1a5eba73910160405180910390a49998505050505050505050565b8051604051606160f81b81526039820160f081811b60018401526f3d81600a3d39f33d3d3d3d363d3d376160801b600384015260028401901b601383018190526560373639366160d01b6015840152601b83015262013d7360e81b601d830152606085901b6020808401919091526c5af43d3d93803e603557fd5bf360981b60348401526000939260438401929186019084604182015b602082106102875783518152602093840193601f199092019101610268565b835160001960208490036101000a0119908116825260f088901b91830191825286846000f098506001600160a01b0389166102d557604051631d7fde3160e31b815260040160405180910390fd5b505050505050505092915050565b80356001600160a01b03811681146102fa57600080fd5b919050565b600080600080600080600060e0888a03121561031a57600080fd5b610323886102e3565b9650610331602089016102e3565b96999698505050506040850135946060810135946080820135945060a0820135935060c090910135915056fea26469706673582212200230b5a4e549645a8fa54b5a23787d5fd4a423d17eadd1dfe11f93177f22967664736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004a88e71d9afb35bd4eec3e33f3e0320347059e55
-----Decoded View---------------
Arg [0] : _implementation (address): 0x4A88e71D9aFB35BD4eEC3E33f3E0320347059e55
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004a88e71d9afb35bd4eec3e33f3e0320347059e55
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.