Skip to content

Commit

Permalink
feat(billboard): revise interface
Browse files Browse the repository at this point in the history
  • Loading branch information
robertu7 committed Jun 27, 2024
1 parent 1c30390 commit ee08b27
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 425 deletions.
3 changes: 0 additions & 3 deletions src/Billboard/Billboard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,5 @@ contract Billboard is IBillboard {

// transfer bid price and tax back to the bidder
registry.transferAmount(msg.sender, amount);

// emit BidWithdrawn
registry.emitBidWithdrawn(tokenId_, auctionId_, msg.sender, _bid.price, _bid.tax);
}
}
257 changes: 105 additions & 152 deletions src/Billboard/BillboardRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,55 +9,44 @@ import "./IBillboardRegistry.sol";

contract BillboardRegistry is IBillboardRegistry, ERC721 {
using Counters for Counters.Counter;
Counters.Counter public lastTokenId;

// access control
address public operator;

Counters.Counter public lastTokenId;

// token to be used for auction
IERC20 public immutable token;
uint256 public taxRate;
uint64 public leaseTerm;

// tokenId => Board
mapping(uint256 => Board) public boards;

// tokenId => auctionId => Auction
mapping(uint256 => mapping(uint256 => Auction)) public boardAuctions;
// tokenId => address => whitelisted
mapping(uint256 => mapping(address => bool)) public boardWhitelists;

// tokenId => nextAuctionId (start from 1 if exists)
mapping(uint256 => uint256) public nextBoardAuctionId;
// tokenId => epoch => bidder
mapping(uint256 => mapping(uint256 => address)) public auctionHiggestBidder;

// tokenId => auctionId => bidders
// tokenId => epoch => bidders
mapping(uint256 => mapping(uint256 => address[])) public auctionBidders;

// tokenId => auctionId => bidder => Bid
// tokenId => epoch => bidder => Bid
mapping(uint256 => mapping(uint256 => mapping(address => Bid))) public auctionBids;

// board creator => TaxTreasury
mapping(address => TaxTreasury) public taxTreasury;

constructor(
address token_,
address operator_,
uint256 taxRate_,
uint64 leaseTerm_,
string memory name_,
string memory symbol_
) ERC721(name_, symbol_) {
//////////////////////////////
/// Constructor
//////////////////////////////
constructor(address token_, address operator_, string memory name_, string memory symbol_) ERC721(name_, symbol_) {
require(operator_ != address(0), "Zero address");
require(token_ != address(0), "Zero address");

token = IERC20(token_);
operator = operator_;
taxRate = taxRate_;
leaseTerm = leaseTerm_;
token = IERC20(token_);
}

//////////////////////////////
/// Modifier
//////////////////////////////

modifier isFromOperator() {
require(msg.sender == operator, "Operator");
_;
Expand All @@ -78,9 +67,12 @@ contract BillboardRegistry is IBillboardRegistry, ERC721 {
//////////////////////////////
/// Board
//////////////////////////////

/// @inheritdoc IBillboardRegistry
function mintBoard(address to_) external isFromOperator returns (uint256 tokenId) {
function newBoard(
address to_,
uint256 taxRate_,
uint256 epochInterval_
) external isFromOperator returns (uint256 tokenId) {
lastTokenId.increment();
tokenId = lastTokenId.current();

Expand All @@ -90,170 +82,147 @@ contract BillboardRegistry is IBillboardRegistry, ERC721 {
creator: to_,
name: "",
description: "",
imageURI: "",
location: "",
contentURI: "",
redirectURI: ""
taxRate: taxRate_,
epochInterval: epochInterval_,
createdAt: block.number
});
}

/// @inheritdoc IBillboardRegistry
function safeTransferByOperator(address from_, address to_, uint256 tokenId_) external isFromOperator {
_safeTransfer(from_, to_, tokenId_, "");
}

/// @inheritdoc IBillboardRegistry
function getBoard(uint256 tokenId_) external view returns (Board memory board) {
board = boards[tokenId_];
emit BoardCreated(tokenId, to_, taxRate_, epochInterval_);
}

/// @inheritdoc IBillboardRegistry
function setBoardName(uint256 tokenId_, string calldata name_) external isFromOperator {
function setBoard(
uint256 tokenId_,
string calldata name_,
string calldata description_,
string calldata imageURI_,
string calldata location_
) external isFromOperator {
boards[tokenId_].name = name_;
emit BoardNameUpdated(tokenId_, name_);
}

/// @inheritdoc IBillboardRegistry
function setBoardDescription(uint256 tokenId_, string calldata description_) external isFromOperator {
boards[tokenId_].description = description_;
emit BoardDescriptionUpdated(tokenId_, description_);
}

/// @inheritdoc IBillboardRegistry
function setBoardLocation(uint256 tokenId_, string calldata location_) external isFromOperator {
boards[tokenId_].imageURI = imageURI_;
boards[tokenId_].location = location_;
emit BoardLocationUpdated(tokenId_, location_);
}

/// @inheritdoc IBillboardRegistry
function setBoardContentURI(uint256 tokenId_, string calldata contentURI_) external isFromOperator {
boards[tokenId_].contentURI = contentURI_;
emit BoardContentURIUpdated(tokenId_, contentURI_);
}

function setBoardRedirectURI(uint256 tokenId_, string calldata redirectURI_) external isFromOperator {
boards[tokenId_].redirectURI = redirectURI_;
emit BoardRedirectURIUpdated(tokenId_, redirectURI_);
emit BoardUpdated(tokenId_, name_, description_, imageURI_, location_);
}

//////////////////////////////
/// Auction
/// Auction & Bid
//////////////////////////////

/// @inheritdoc IBillboardRegistry
function getAuction(uint256 tokenId_, uint256 auctionId_) external view returns (Auction memory auction) {
auction = boardAuctions[tokenId_][auctionId_];
function getBidCount(uint256 tokenId_, uint256 epoch_) external view returns (uint256 count) {
count = auctionBidders[tokenId_][epoch_].length;
}

/// @inheritdoc IBillboardRegistry
function newAuction(
function newBid(
uint256 tokenId_,
uint64 startAt_,
uint64 endAt_
) external isFromOperator returns (uint256 newAuctionId) {
nextBoardAuctionId[tokenId_]++;

newAuctionId = nextBoardAuctionId[tokenId_];

boardAuctions[tokenId_][newAuctionId] = Auction({
startAt: startAt_,
endAt: endAt_,
leaseStartAt: 0,
leaseEndAt: 0,
highestBidder: address(0)
uint256 epoch_,
address bidder_,
uint256 price_,
uint256 tax_,
string calldata contentURI_,
string calldata redirectURI_
) external isFromOperator {
Bid memory _bid = Bid({
price: price_,
tax: tax_,
contentURI: contentURI_,
redirectURI: redirectURI_,
createdAt: block.number,
updatedAt: block.number,
isWithdrawn: false,
isWon: false
});

emit AuctionCreated(tokenId_, newAuctionId, startAt_, endAt_);
}
// add to auction bids
auctionBids[tokenId_][epoch_][bidder_] = _bid;

/// @inheritdoc IBillboardRegistry
function setAuctionLease(
uint256 tokenId_,
uint256 auctionId_,
uint64 leaseStartAt_,
uint64 leaseEndAt_
) external isFromOperator {
boardAuctions[tokenId_][auctionId_].leaseStartAt = leaseStartAt_;
boardAuctions[tokenId_][auctionId_].leaseEndAt = leaseEndAt_;
}
// add to auction bidders if new bid
auctionBidders[tokenId_][epoch_].push(bidder_);

/// @inheritdoc IBillboardRegistry
function getBidCount(uint256 tokenId_, uint256 auctionId_) external view returns (uint256 count) {
count = auctionBidders[tokenId_][auctionId_].length;
}
_setHiggestBidder(tokenId_, epoch_, price_, bidder_);

/// @inheritdoc IBillboardRegistry
function getBid(uint256 tokenId_, uint256 auctionId_, address bidder_) external view returns (Bid memory bid) {
bid = auctionBids[tokenId_][auctionId_][bidder_];
emit BidUpdated(tokenId_, epoch_, bidder_, price_, tax_, contentURI_, redirectURI_);
}

/// @inheritdoc IBillboardRegistry
function newBid(
function setBid(
uint256 tokenId_,
uint256 auctionId_,
uint256 epoch_,
address bidder_,
uint256 price_,
uint256 tax_
uint256 tax_,
string calldata contentURI_,
string calldata redirectURI_
) external isFromOperator {
Bid memory _bid = Bid({price: price_, tax: tax_, placedAt: block.number, isWithdrawn: false, isWon: false});
Bid memory _bid = auctionBids[tokenId_][epoch_][bidder_];
require(_bid.createdAt != 0, "Bid not found");

// add to auction bids
auctionBids[tokenId_][auctionId_][bidder_] = _bid;
_bid.price = price_;
_bid.tax = tax_;
_bid.contentURI = contentURI_;
_bid.redirectURI = redirectURI_;
_bid.updatedAt = block.number;

_setHiggestBidder(tokenId_, epoch_, price_, bidder_);

// add to auction bidders
auctionBidders[tokenId_][auctionId_].push(bidder_);
emit BidUpdated(tokenId_, epoch_, bidder_, price_, tax_, contentURI_, redirectURI_);
}

// set auction highest bidder if no highest bidder or price is higher.
//
// Note: for same price, the first bidder will always be
// the highest bidder since the block.number is always greater.
address highestBidder = boardAuctions[tokenId_][auctionId_].highestBidder;
Bid memory highestBid = auctionBids[tokenId_][auctionId_][highestBidder];
// Set auction highest bidder if no highest bidder or price is higher.
//
// Note: for same price, the first bidder will always be
// the highest bidder since the block.number is always greater.
function _setHiggestBidder(uint256 tokenId_, uint256 epoch_, uint256 price_, address bidder_) internal {
address highestBidder = auctionHiggestBidder[tokenId_][epoch_];
Bid memory highestBid = auctionBids[tokenId_][epoch_][highestBidder];
if (highestBidder == address(0) || price_ > highestBid.price) {
boardAuctions[tokenId_][auctionId_].highestBidder = bidder_;
auctionHiggestBidder[tokenId_][epoch_] = bidder_;
}

emit BidCreated(tokenId_, auctionId_, bidder_, price_, tax_);
}

/// @inheritdoc IBillboardRegistry
function setBidWon(uint256 tokenId_, uint256 auctionId_, address bidder_, bool isWon_) external isFromOperator {
auctionBids[tokenId_][auctionId_][bidder_].isWon = isWon_;

emit BidWon(tokenId_, auctionId_, bidder_);
function setBidWon(uint256 tokenId_, uint256 epoch_, address bidder_, bool isWon_) external isFromOperator {
auctionBids[tokenId_][epoch_][bidder_].isWon = isWon_;
emit BidWon(tokenId_, epoch_, bidder_);
}

/// @inheritdoc IBillboardRegistry
function setBidWithdrawn(
uint256 tokenId_,
uint256 auctionId_,
uint256 epoch_,
address bidder_,
bool isWithdrawn_
) external isFromOperator {
auctionBids[tokenId_][auctionId_][bidder_].isWithdrawn = isWithdrawn_;
auctionBids[tokenId_][epoch_][bidder_].isWithdrawn = isWithdrawn_;
emit BidWithdrawn(tokenId_, epoch_, msg.sender);
}

/// @inheritdoc IBillboardRegistry
function transferAmount(address to_, uint256 amount_) external isFromOperator {
require(to_ != address(0), "Zero address");
//////////////////////////////
/// Tax & Withdraw
//////////////////////////////

require(token.transfer(to_, amount_), "Failed token transfer");
/// @inheritdoc IBillboardRegistry
function setTaxTreasury(address owner_, uint256 accumulated_, uint256 withdrawn_) external isFromOperator {
taxTreasury[owner_].accumulated = accumulated_;
taxTreasury[owner_].withdrawn = withdrawn_;
}

//////////////////////////////
/// Tax & Withdraw
/// Transfer
//////////////////////////////

/// @inheritdoc IBillboardRegistry
function setTaxRate(uint256 taxRate_) external isFromOperator {
taxRate = taxRate_;

emit TaxRateUpdated(taxRate_);
function transferTokenByOperator(address to_, uint256 amount_) external isFromOperator {
require(to_ != address(0), "Zero address");
require(token.transfer(to_, amount_), "Failed token transfer");
}

/// @inheritdoc IBillboardRegistry
function setTaxTreasury(address owner_, uint256 accumulated_, uint256 withdrawn_) external isFromOperator {
taxTreasury[owner_].accumulated = accumulated_;
taxTreasury[owner_].withdrawn = withdrawn_;
function safeTransferByOperator(address from_, address to_, uint256 tokenId_) external isFromOperator {
_safeTransfer(from_, to_, tokenId_, "");
}

//////////////////////////////
Expand All @@ -264,7 +233,8 @@ contract BillboardRegistry is IBillboardRegistry, ERC721 {
* @notice See {IERC721-tokenURI}.
*/
function tokenURI(uint256 tokenId_) public view override(ERC721) returns (string memory uri) {
return boards[tokenId_].contentURI;
// TODO
// return boards[tokenId_].contentURI;
}

/**
Expand All @@ -279,25 +249,8 @@ contract BillboardRegistry is IBillboardRegistry, ERC721 {
//////////////////////////////

/// @inheritdoc IBillboardRegistry
function emitAuctionCleared(
uint256 tokenId_,
uint256 auctionId_,
address highestBidder_,
uint64 leaseStartAt_,
uint64 leaseEndAt_
) external {
emit AuctionCleared(tokenId_, auctionId_, highestBidder_, leaseStartAt_, leaseEndAt_);
}

/// @inheritdoc IBillboardRegistry
function emitBidWithdrawn(
uint256 tokenId_,
uint256 auctionId_,
address bidder_,
uint256 price_,
uint256 tax_
) external {
emit BidWithdrawn(tokenId_, auctionId_, bidder_, price_, tax_);
function emitAuctionCleared(uint256 tokenId_, uint256 epoch_, address highestBidder_) external {
emit AuctionCleared(tokenId_, epoch_, highestBidder_);
}

/// @inheritdoc IBillboardRegistry
Expand Down
Loading

0 comments on commit ee08b27

Please sign in to comment.