Skip to content

Commit

Permalink
Merge branch 'main' into audit_v2_4_0_sbe_01m
Browse files Browse the repository at this point in the history
  • Loading branch information
levalleux-ludo committed Jan 9, 2024
2 parents 69089b6 + d7d16e6 commit 851a236
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 74 deletions.
3 changes: 3 additions & 0 deletions contracts/domain/BosonConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ bytes32 constant CLIENT = keccak256("CLIENT"); // Role for clients of the Protoc
bytes32 constant UPGRADER = keccak256("UPGRADER"); // Role for performing contract and config upgrades
bytes32 constant FEE_COLLECTOR = keccak256("FEE_COLLECTOR"); // Role for collecting fees from the protocol

// Generic
uint256 constant HUNDRED_PERCENT = 10000; // 100% in basis points

// Pause Handler
uint256 constant ALL_REGIONS_MASK = (1 << (uint256(type(BosonTypes.PausableRegion).max) + 1)) - 1;

Expand Down
6 changes: 0 additions & 6 deletions contracts/protocol/bases/BuyerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,9 @@ contract BuyerBase is ProtocolBase, IBosonAccountEvents {
//Check for zero address
if (_buyer.wallet == address(0)) revert InvalidAddress();

//Check active is not set to false
if (!_buyer.active) revert MustBeActive();

// Get the next account id and increment the counter
uint256 buyerId = protocolCounters().nextAccountId++;

//check that the wallet address is unique to one buyer id
if (protocolLookups().buyerIdByWallet[_buyer.wallet] != 0) revert BuyerAddressMustBeUnique();

_buyer.id = buyerId;
storeBuyer(_buyer);

Expand Down
6 changes: 3 additions & 3 deletions contracts/protocol/bases/OfferBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ contract OfferBase is ProtocolBase, IBosonOfferEvents {
disputeResolutionTerms.feeAmount = feeAmount;
disputeResolutionTerms.buyerEscalationDeposit =
(feeAmount * fees.buyerEscalationDepositPercentage) /
10000;
HUNDRED_PERCENT;
}
protocolEntities().disputeResolutionTerms[_offer.id] = disputeResolutionTerms;
}
Expand Down Expand Up @@ -236,9 +236,9 @@ contract OfferBase is ProtocolBase, IBosonOfferEvents {
uint256 protocolFee = getProtocolFee(_offer.exchangeToken, offerPrice);

// Calculate the agent fee amount
uint256 agentFeeAmount = (agent.feePercentage * offerPrice) / 10000;
uint256 agentFeeAmount = (agent.feePercentage * offerPrice) / HUNDRED_PERCENT;

uint256 totalOfferFeeLimit = (limits.maxTotalOfferFeePercentage * offerPrice) / 10000;
uint256 totalOfferFeeLimit = (limits.maxTotalOfferFeePercentage * offerPrice) / HUNDRED_PERCENT;

// Sum of agent fee amount and protocol fee amount should be <= offer fee limit and less that fee limit set by seller
uint256 totalFeeAmount = agentFeeAmount + protocolFee;
Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/bases/ProtocolBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ abstract contract ProtocolBase is PausableBase, ReentrancyGuardBase, BosonErrors
return
_exchangeToken == protocolAddresses().token
? protocolFees().flatBoson
: (protocolFees().percentage * _price) / 10000;
: (protocolFees().percentage * _price) / HUNDRED_PERCENT;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/clients/voucher/BosonVoucher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ contract BosonVoucherBase is IBosonVoucher, BeaconClientBase, OwnableUpgradeable
!isPreminted
);

royaltyAmount = (_salePrice * royaltyPercentage) / 10000;
royaltyAmount = (_salePrice * royaltyPercentage) / HUNDRED_PERCENT;
}

/**
Expand Down
6 changes: 6 additions & 0 deletions contracts/protocol/facets/BuyerHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ contract BuyerHandlerFacet is BuyerBase {
* @param _buyer - the fully populated struct with buyer id set to 0x0
*/
function createBuyer(Buyer memory _buyer) external buyersNotPaused nonReentrant {
//Check active is not set to false
if (!_buyer.active) revert MustBeActive();

//check that the wallet address is unique to one buyer id
if (protocolLookups().buyerIdByWallet[_buyer.wallet] != 0) revert BuyerAddressMustBeUnique();

createBuyerInternal(_buyer);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/facets/ConfigHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,6 @@ contract ConfigHandlerFacet is IBosonConfigHandler, ProtocolBase {
* Reverts if the value more than 10000
*/
function checkMaxPercententage(uint256 _percentage) internal pure {
if (_percentage > 10000) revert InvalidFeePercentage();
if (_percentage > HUNDRED_PERCENT) revert InvalidFeePercentage();
}
}
4 changes: 2 additions & 2 deletions contracts/protocol/facets/DisputeHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ contract DisputeHandlerFacet is DisputeBase, IBosonDisputeHandler {
uint8 _sigV
) external override nonReentrant {
// buyer should get at most 100%
if (_buyerPercent > 10000) revert InvalidBuyerPercent();
if (_buyerPercent > HUNDRED_PERCENT) revert InvalidBuyerPercent();

// Get the exchange, should be in disputed state
(Exchange storage exchange, ) = getValidExchange(_exchangeId, ExchangeState.Disputed);
Expand Down Expand Up @@ -340,7 +340,7 @@ contract DisputeHandlerFacet is DisputeBase, IBosonDisputeHandler {
*/
function decideDispute(uint256 _exchangeId, uint256 _buyerPercent) external override nonReentrant {
// Buyer should get at most 100%
if (_buyerPercent > 10000) revert InvalidBuyerPercent();
if (_buyerPercent > HUNDRED_PERCENT) revert InvalidBuyerPercent();

// Make sure the dispute is valid and the caller is the dispute resolver
(Exchange storage exchange, Dispute storage dispute, DisputeDates storage disputeDates) = disputeResolverChecks(
Expand Down
155 changes: 107 additions & 48 deletions contracts/protocol/facets/OfferHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,8 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
*
* @param _offerId - the id of the offer to void
*/
function voidOffer(uint256 _offerId) public override offersNotPaused nonReentrant {
// Get offer. Make sure caller is assistant
Offer storage offer = getValidOfferWithSellerCheck(_offerId);

// Void the offer
offer.voided = true;

// Notify listeners of state change
emit OfferVoided(_offerId, offer.sellerId, msgSender());
function voidOffer(uint256 _offerId) external override offersNotPaused nonReentrant {
voidOfferInternal(_offerId);
}

/**
Expand All @@ -212,9 +205,9 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
*
* @param _offerIds - list of ids of offers to void
*/
function voidOfferBatch(uint256[] calldata _offerIds) external override offersNotPaused {
function voidOfferBatch(uint256[] calldata _offerIds) external override offersNotPaused nonReentrant {
for (uint256 i = 0; i < _offerIds.length; ) {
voidOffer(_offerIds[i]);
voidOfferInternal(_offerIds[i]);

unchecked {
i++;
Expand All @@ -237,26 +230,8 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
* @param _offerId - the id of the offer to extend
* @param _validUntilDate - new valid until date
*/
function extendOffer(uint256 _offerId, uint256 _validUntilDate) public override offersNotPaused nonReentrant {
// Make sure the caller is the assistant, offer exists and is not voided
Offer storage offer = getValidOfferWithSellerCheck(_offerId);

// Fetch the offer dates
OfferDates storage offerDates = fetchOfferDates(_offerId);

// New valid until date must be greater than existing one
if (offerDates.validUntil >= _validUntilDate) revert InvalidOfferPeriod();

// If voucherRedeemableUntil is set, _validUntilDate must be less or equal than that
if (offerDates.voucherRedeemableUntil > 0) {
if (_validUntilDate > offerDates.voucherRedeemableUntil) revert InvalidOfferPeriod();
}

// Update the valid until property
offerDates.validUntil = _validUntilDate;

// Notify watchers of state change
emit OfferExtended(_offerId, offer.sellerId, _validUntilDate, msgSender());
function extendOffer(uint256 _offerId, uint256 _validUntilDate) external override offersNotPaused nonReentrant {
extendOfferInternal(_offerId, _validUntilDate);
}

/**
Expand All @@ -275,9 +250,12 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
* @param _offerIds - list of ids of the offers to extend
* @param _validUntilDate - new valid until date
*/
function extendOfferBatch(uint256[] calldata _offerIds, uint256 _validUntilDate) external override offersNotPaused {
function extendOfferBatch(
uint256[] calldata _offerIds,
uint256 _validUntilDate
) external override offersNotPaused nonReentrant {
for (uint256 i = 0; i < _offerIds.length; ) {
extendOffer(_offerIds[i], _validUntilDate);
extendOfferInternal(_offerIds[i], _validUntilDate);

unchecked {
i++;
Expand All @@ -302,17 +280,8 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
function updateOfferRoyaltyRecipients(
uint256 _offerId,
RoyaltyInfo calldata _royaltyInfo
) public override offersNotPaused nonReentrant {
// Make sure the caller is the assistant, offer exists and is not voided
Offer storage offer = getValidOfferWithSellerCheck(_offerId);

validateRoyaltyInfo(protocolLookups(), protocolLimits(), offer.sellerId, _royaltyInfo);

// Add new entry to the royaltyInfo array
offer.royaltyInfo.push(_royaltyInfo);

// Notify watchers of state change
emit OfferRoyaltyInfoUpdated(_offerId, offer.sellerId, _royaltyInfo, msgSender());
) external override offersNotPaused nonReentrant {
updateOfferRoyaltyRecipientsInternal(_offerId, _royaltyInfo);
}

/**
Expand All @@ -333,16 +302,106 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
function updateOfferRoyaltyRecipientsBatch(
uint256[] calldata _offerIds,
BosonTypes.RoyaltyInfo calldata _royaltyInfo
) external override offersNotPaused {
) external override offersNotPaused nonReentrant {
for (uint256 i = 0; i < _offerIds.length; ) {
updateOfferRoyaltyRecipients(_offerIds[i], _royaltyInfo);
updateOfferRoyaltyRecipientsInternal(_offerIds[i], _royaltyInfo);

unchecked {
i++;
}
}
}

/**
* @notice Internal function to void a given offer, used by both single and batch void functions.
* Existing exchanges are not affected.
* No further vouchers can be issued against a voided offer.
*
* Emits an OfferVoided event if successful.
*
* Reverts if:
* - The offers region of protocol is paused
* - Offer id is invalid
* - Caller is not the assistant of the offer
* - Offer has already been voided
*
* @param _offerId - the id of the offer to void
*/
function voidOfferInternal(uint256 _offerId) internal {
// Get offer. Make sure caller is assistant
Offer storage offer = getValidOfferWithSellerCheck(_offerId);

// Void the offer
offer.voided = true;

// Notify listeners of state change
emit OfferVoided(_offerId, offer.sellerId, msgSender());
}

/**
* @notice Internal function to set new valid until date, used by both single and batch extend functions.
*
* Emits an OfferExtended event if successful.
*
* Reverts if:
* - The offers region of protocol is paused
* - Offer does not exist
* - Caller is not the assistant of the offer
* - New valid until date is before existing valid until dates
* - Offer has voucherRedeemableUntil set and new valid until date is greater than that
*
* @param _offerId - the id of the offer to extend
* @param _validUntilDate - new valid until date
*/
function extendOfferInternal(uint256 _offerId, uint256 _validUntilDate) internal {
// Make sure the caller is the assistant, offer exists and is not voided
Offer storage offer = getValidOfferWithSellerCheck(_offerId);

// Fetch the offer dates
OfferDates storage offerDates = fetchOfferDates(_offerId);

// New valid until date must be greater than existing one
if (offerDates.validUntil >= _validUntilDate) revert InvalidOfferPeriod();

// If voucherRedeemableUntil is set, _validUntilDate must be less or equal than that
if (offerDates.voucherRedeemableUntil > 0) {
if (_validUntilDate > offerDates.voucherRedeemableUntil) revert InvalidOfferPeriod();
}

// Update the valid until property
offerDates.validUntil = _validUntilDate;

// Notify watchers of state change
emit OfferExtended(_offerId, offer.sellerId, _validUntilDate, msgSender());
}

/**
* @notice Internal function to update the royalty recipients, used by both single and batch update functions.
*
* Emits an OfferRoyaltyInfoUpdated event if successful.
*
* Reverts if:
* - The offers region of protocol is paused
* - Offer does not exist
* - Caller is not the assistant of the offer
* - New royalty info is invalid
*
* @param _offerId - the id of the offer to be updated
* @param _royaltyInfo - new royalty info
*/
function updateOfferRoyaltyRecipientsInternal(uint256 _offerId, RoyaltyInfo calldata _royaltyInfo) internal {
// Make sure the caller is the assistant, offer exists and is not voided
Offer storage offer = getValidOfferWithSellerCheck(_offerId);

validateRoyaltyInfo(protocolLookups(), protocolLimits(), offer.sellerId, _royaltyInfo);

// Add new entry to the royaltyInfo array
offer.royaltyInfo.push(_royaltyInfo);

// Notify watchers of state change
emit OfferRoyaltyInfoUpdated(_offerId, offer.sellerId, _royaltyInfo, msgSender());
}

/**
* @notice Gets the details about a given offer.
*
Expand Down Expand Up @@ -385,7 +444,7 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
*
* @return nextOfferId - the next offer id
*/
function getNextOfferId() public view override returns (uint256 nextOfferId) {
function getNextOfferId() external view override returns (uint256 nextOfferId) {
nextOfferId = protocolCounters().nextOfferId;
}

Expand All @@ -396,7 +455,7 @@ contract OfferHandlerFacet is IBosonOfferHandler, OfferBase {
* @return exists - the offer was found
* @return offerVoided - true if voided, false otherwise
*/
function isOfferVoided(uint256 _offerId) public view override returns (bool exists, bool offerVoided) {
function isOfferVoided(uint256 _offerId) external view override returns (bool exists, bool offerVoided) {
Offer storage offer;
(exists, offer) = fetchOffer(_offerId);
offerVoided = offer.voided;
Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/facets/PriceDiscoveryHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ contract PriceDiscoveryHandlerFacet is IBosonPriceDiscoveryHandler, PriceDiscove
{
// Calculate royalties
(RoyaltyInfo storage royaltyInfo, uint256 royaltyInfoIndex, ) = fetchRoyalties(offerId, false);
uint256 royaltyAmount = (getTotalRoyaltyPercentage(royaltyInfo.bps) * actualPrice) / 10000;
uint256 royaltyAmount = (getTotalRoyaltyPercentage(royaltyInfo.bps) * actualPrice) / HUNDRED_PERCENT;

// Verify that fees and royalties are not higher than the price.
if (protocolFeeAmount + royaltyAmount > actualPrice) revert FeeAmountTooHigh();
Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/facets/SequentialCommitHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ contract SequentialCommitHandlerFacet is IBosonSequentialCommitHandler, PriceDis
(royaltyInfo, exchangeCost.royaltyInfoIndex, ) = fetchRoyalties(offerId, false);
exchangeCost.royaltyAmount =
(getTotalRoyaltyPercentage(royaltyInfo.bps) * exchangeCost.price) /
10000;
HUNDRED_PERCENT;
}

// Verify that fees and royalties are not higher than the price.
Expand Down
Loading

0 comments on commit 851a236

Please sign in to comment.