-
Notifications
You must be signed in to change notification settings - Fork 8
UMA DR Adapter #1041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
UMA DR Adapter #1041
Conversation
| function registerDisputeResolver( | ||
| address payable _treasury, | ||
| string memory _metadataUri, | ||
| BosonTypes.DisputeResolverFee[] memory _disputeResolverFees, | ||
| uint256[] memory _sellerAllowList | ||
| ) external onlyOwner { | ||
| if (disputeResolverId != 0) revert AlreadyRegistered(); | ||
|
|
||
| BosonTypes.DisputeResolver memory disputeResolver = BosonTypes.DisputeResolver({ | ||
| id: 0, // Will be set by the protocol | ||
| escalationResponsePeriod: challengePeriod, | ||
| assistant: address(this), | ||
| admin: address(this), | ||
| clerk: address(0), // Deprecated field | ||
| treasury: _treasury, | ||
| metadataUri: _metadataUri, | ||
| active: true | ||
| }); | ||
|
|
||
| IBosonDisputeResolverHandler(BOSON_PROTOCOL).createDisputeResolver( | ||
| disputeResolver, | ||
| _disputeResolverFees, | ||
| _sellerAllowList | ||
| ); | ||
|
|
||
| (, BosonTypes.DisputeResolver memory registeredDR, , ) = IBosonDisputeResolverHandler(BOSON_PROTOCOL) | ||
| .getDisputeResolverByAddress(address(this)); | ||
|
|
||
| disputeResolverId = registeredDR.id; | ||
| emit DisputeResolverRegistered(disputeResolverId); | ||
| } |
Check warning
Code scanning / Slither
Reentrancy vulnerabilities Medium
External calls:
- IBosonDisputeResolverHandler(BOSON_PROTOCOL).createDisputeResolver(disputeResolver,_disputeResolverFees,_sellerAllowList)
State variables written after the call(s):
- disputeResolverId = registeredDR.id
UMADisputeResolverAdapter.disputeResolverId can be used in cross function reentrancies:
- UMADisputeResolverAdapter.addFeesToDisputeResolver(BosonTypes.DisputeResolverFee[])
- UMADisputeResolverAdapter.disputeResolverId
- UMADisputeResolverAdapter.getDisputeResolver()
- UMADisputeResolverAdapter.isRegistered()
- UMADisputeResolverAdapter.registerDisputeResolver(address,string,BosonTypes.DisputeResolverFee[],uint256[])
- UMADisputeResolverAdapter.removeFeesFromDisputeResolver(address[])
| function registerDisputeResolver( | ||
| address payable _treasury, | ||
| string memory _metadataUri, | ||
| BosonTypes.DisputeResolverFee[] memory _disputeResolverFees, | ||
| uint256[] memory _sellerAllowList | ||
| ) external onlyOwner { | ||
| if (disputeResolverId != 0) revert AlreadyRegistered(); | ||
|
|
||
| BosonTypes.DisputeResolver memory disputeResolver = BosonTypes.DisputeResolver({ | ||
| id: 0, // Will be set by the protocol | ||
| escalationResponsePeriod: challengePeriod, | ||
| assistant: address(this), | ||
| admin: address(this), | ||
| clerk: address(0), // Deprecated field | ||
| treasury: _treasury, | ||
| metadataUri: _metadataUri, | ||
| active: true | ||
| }); | ||
|
|
||
| IBosonDisputeResolverHandler(BOSON_PROTOCOL).createDisputeResolver( | ||
| disputeResolver, | ||
| _disputeResolverFees, | ||
| _sellerAllowList | ||
| ); | ||
|
|
||
| (, BosonTypes.DisputeResolver memory registeredDR, , ) = IBosonDisputeResolverHandler(BOSON_PROTOCOL) | ||
| .getDisputeResolverByAddress(address(this)); | ||
|
|
||
| disputeResolverId = registeredDR.id; | ||
| emit DisputeResolverRegistered(disputeResolverId); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function registerDisputeResolver( | ||
| address payable _treasury, | ||
| string memory _metadataUri, | ||
| BosonTypes.DisputeResolverFee[] memory _disputeResolverFees, | ||
| uint256[] memory _sellerAllowList | ||
| ) external onlyOwner { | ||
| if (disputeResolverId != 0) revert AlreadyRegistered(); | ||
|
|
||
| BosonTypes.DisputeResolver memory disputeResolver = BosonTypes.DisputeResolver({ | ||
| id: 0, // Will be set by the protocol | ||
| escalationResponsePeriod: challengePeriod, | ||
| assistant: address(this), | ||
| admin: address(this), | ||
| clerk: address(0), // Deprecated field | ||
| treasury: _treasury, | ||
| metadataUri: _metadataUri, | ||
| active: true | ||
| }); | ||
|
|
||
| IBosonDisputeResolverHandler(BOSON_PROTOCOL).createDisputeResolver( | ||
| disputeResolver, | ||
| _disputeResolverFees, | ||
| _sellerAllowList | ||
| ); | ||
|
|
||
| (, BosonTypes.DisputeResolver memory registeredDR, , ) = IBosonDisputeResolverHandler(BOSON_PROTOCOL) | ||
| .getDisputeResolverByAddress(address(this)); | ||
|
|
||
| disputeResolverId = registeredDR.id; | ||
| emit DisputeResolverRegistered(disputeResolverId); | ||
| } |
Check notice
Code scanning / Slither
Reentrancy vulnerabilities Low
External calls:
- IBosonDisputeResolverHandler(BOSON_PROTOCOL).createDisputeResolver(disputeResolver,_disputeResolverFees,_sellerAllowList)
Event emitted after the call(s):
- DisputeResolverRegistered(disputeResolverId)
| function assertTruthForDispute( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| string memory _additionalInfo | ||
| ) external nonReentrant { | ||
| if (_buyerPercent > 10000) revert InvalidBuyerPercent(); | ||
|
|
||
| // Verify the dispute is escalated in Boson Protocol | ||
| (bool exists, BosonTypes.DisputeState state) = IBosonDisputeHandler(BOSON_PROTOCOL).getDisputeState( | ||
| _exchangeId | ||
| ); | ||
| if (!exists) revert InvalidExchangeId(); | ||
| if (state != BosonTypes.DisputeState.Escalated) revert DisputeNotEscalated(); | ||
|
|
||
| _validateAssignedDisputeResolver(_exchangeId); | ||
|
|
||
| if (exchangeToAssertion[_exchangeId] != bytes32(0)) revert AssertionAlreadyExists(); | ||
|
|
||
| bytes32 assertionId = _createUMAAssertion(_exchangeId, _buyerPercent, _additionalInfo); | ||
|
|
||
| assertionToExchange[assertionId] = _exchangeId; | ||
| exchangeToAssertion[_exchangeId] = assertionId; | ||
| assertionToBuyerPercent[assertionId] = _buyerPercent; | ||
|
|
||
| emit DisputeEscalatedToUMA(_exchangeId, assertionId, msg.sender); | ||
| } |
Check warning
Code scanning / Slither
Reentrancy vulnerabilities Medium
External calls:
- assertionId = _createUMAAssertion(_exchangeId,_buyerPercent,_additionalInfo)
- exchangeToken.transferFrom(msg.sender,address(this),bond)
- exchangeToken.approve(address(UMA_ORACLE),bond)
- assertionId = UMA_ORACLE.assertTruth(claim,msg.sender,address(this),address(0),challengePeriod,exchangeToken,bond,UMA_ASSERTION_IDENTIFIER,domainId)
State variables written after the call(s):
- exchangeToAssertion[_exchangeId] = assertionId
UMADisputeResolverAdapter.exchangeToAssertion can be used in cross function reentrancies:
- UMADisputeResolverAdapter.assertionResolvedCallback(bytes32,bool)
- UMADisputeResolverAdapter.exchangeToAssertion
| function assertTruthForDispute( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| string memory _additionalInfo | ||
| ) external nonReentrant { | ||
| if (_buyerPercent > 10000) revert InvalidBuyerPercent(); | ||
|
|
||
| // Verify the dispute is escalated in Boson Protocol | ||
| (bool exists, BosonTypes.DisputeState state) = IBosonDisputeHandler(BOSON_PROTOCOL).getDisputeState( | ||
| _exchangeId | ||
| ); | ||
| if (!exists) revert InvalidExchangeId(); | ||
| if (state != BosonTypes.DisputeState.Escalated) revert DisputeNotEscalated(); | ||
|
|
||
| _validateAssignedDisputeResolver(_exchangeId); | ||
|
|
||
| if (exchangeToAssertion[_exchangeId] != bytes32(0)) revert AssertionAlreadyExists(); | ||
|
|
||
| bytes32 assertionId = _createUMAAssertion(_exchangeId, _buyerPercent, _additionalInfo); | ||
|
|
||
| assertionToExchange[assertionId] = _exchangeId; | ||
| exchangeToAssertion[_exchangeId] = assertionId; | ||
| assertionToBuyerPercent[assertionId] = _buyerPercent; | ||
|
|
||
| emit DisputeEscalatedToUMA(_exchangeId, assertionId, msg.sender); | ||
| } |
Check notice
Code scanning / Slither
Reentrancy vulnerabilities Low
External calls:
- assertionId = _createUMAAssertion(_exchangeId,_buyerPercent,_additionalInfo)
- exchangeToken.transferFrom(msg.sender,address(this),bond)
- exchangeToken.approve(address(UMA_ORACLE),bond)
- assertionId = UMA_ORACLE.assertTruth(claim,msg.sender,address(this),address(0),challengePeriod,exchangeToken,bond,UMA_ASSERTION_IDENTIFIER,domainId)
State variables written after the call(s):
- assertionToBuyerPercent[assertionId] = _buyerPercent
- assertionToExchange[assertionId] = _exchangeId
| function _validateAssignedDisputeResolver(uint256 _exchangeId) internal view { | ||
| // it is already validated that there is a valid dispute for this exchange, so we assume exchange and offer exist | ||
| (, BosonTypes.Exchange memory exchange, ) = IBosonExchangeHandler(BOSON_PROTOCOL).getExchange(_exchangeId); | ||
| (, BosonTypes.Offer memory offer, , , , ) = IBosonOfferHandler(BOSON_PROTOCOL).getOffer(exchange.offerId); | ||
| (, , , , BosonTypes.DisputeResolutionTerms memory disputeResolutionTerms, ) = IBosonOfferHandler(BOSON_PROTOCOL) | ||
| .getOffer(offer.id); | ||
|
|
||
| if (disputeResolutionTerms.disputeResolverId != disputeResolverId) { | ||
| revert NotAssignedDisputeResolver(); | ||
| } | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function _createUMAAssertion( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| string memory _additionalInfo | ||
| ) internal returns (bytes32 assertionId) { | ||
| // Get exchange and offer details | ||
| (, BosonTypes.Exchange memory exchange, ) = IBosonExchangeHandler(BOSON_PROTOCOL).getExchange(_exchangeId); | ||
| (, BosonTypes.Offer memory offer, , , , ) = IBosonOfferHandler(BOSON_PROTOCOL).getOffer(exchange.offerId); | ||
|
|
||
| // Create human-readable claim following UMA's example | ||
| bytes memory claim = abi.encodePacked( | ||
| "Boson Protocol dispute for exchange ", | ||
| Strings.toString(_exchangeId), | ||
| ": Buyer claims ", | ||
| Strings.toString(_buyerPercent), | ||
| "% of funds. ", | ||
| _additionalInfo, | ||
| " at timestamp ", | ||
| Strings.toString(block.timestamp) | ||
| ); | ||
|
|
||
| uint256 bond = UMA_ORACLE.getMinimumBond(offer.exchangeToken); | ||
| IERC20 exchangeToken = IERC20(offer.exchangeToken); | ||
|
|
||
| exchangeToken.transferFrom(msg.sender, address(this), bond); | ||
| exchangeToken.approve(address(UMA_ORACLE), bond); | ||
|
|
||
| bytes32 domainId = bytes32(_exchangeId); | ||
| assertionId = UMA_ORACLE.assertTruth( | ||
| claim, | ||
| msg.sender, | ||
| address(this), | ||
| address(0), // we don't use specific escalation manager, but use the default one (DVN). | ||
| challengePeriod, | ||
| exchangeToken, | ||
| bond, | ||
| UMA_ASSERTION_IDENTIFIER, | ||
| domainId | ||
| ); | ||
| } |
Check failure
Code scanning / Slither
Unchecked transfer High
| function _createUMAAssertion( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| string memory _additionalInfo | ||
| ) internal returns (bytes32 assertionId) { | ||
| // Get exchange and offer details | ||
| (, BosonTypes.Exchange memory exchange, ) = IBosonExchangeHandler(BOSON_PROTOCOL).getExchange(_exchangeId); | ||
| (, BosonTypes.Offer memory offer, , , , ) = IBosonOfferHandler(BOSON_PROTOCOL).getOffer(exchange.offerId); | ||
|
|
||
| // Create human-readable claim following UMA's example | ||
| bytes memory claim = abi.encodePacked( | ||
| "Boson Protocol dispute for exchange ", | ||
| Strings.toString(_exchangeId), | ||
| ": Buyer claims ", | ||
| Strings.toString(_buyerPercent), | ||
| "% of funds. ", | ||
| _additionalInfo, | ||
| " at timestamp ", | ||
| Strings.toString(block.timestamp) | ||
| ); | ||
|
|
||
| uint256 bond = UMA_ORACLE.getMinimumBond(offer.exchangeToken); | ||
| IERC20 exchangeToken = IERC20(offer.exchangeToken); | ||
|
|
||
| exchangeToken.transferFrom(msg.sender, address(this), bond); | ||
| exchangeToken.approve(address(UMA_ORACLE), bond); | ||
|
|
||
| bytes32 domainId = bytes32(_exchangeId); | ||
| assertionId = UMA_ORACLE.assertTruth( | ||
| claim, | ||
| msg.sender, | ||
| address(this), | ||
| address(0), // we don't use specific escalation manager, but use the default one (DVN). | ||
| challengePeriod, | ||
| exchangeToken, | ||
| bond, | ||
| UMA_ASSERTION_IDENTIFIER, | ||
| domainId | ||
| ); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function _createUMAAssertion( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| string memory _additionalInfo | ||
| ) internal returns (bytes32 assertionId) { | ||
| // Get exchange and offer details | ||
| (, BosonTypes.Exchange memory exchange, ) = IBosonExchangeHandler(BOSON_PROTOCOL).getExchange(_exchangeId); | ||
| (, BosonTypes.Offer memory offer, , , , ) = IBosonOfferHandler(BOSON_PROTOCOL).getOffer(exchange.offerId); | ||
|
|
||
| // Create human-readable claim following UMA's example | ||
| bytes memory claim = abi.encodePacked( | ||
| "Boson Protocol dispute for exchange ", | ||
| Strings.toString(_exchangeId), | ||
| ": Buyer claims ", | ||
| Strings.toString(_buyerPercent), | ||
| "% of funds. ", | ||
| _additionalInfo, | ||
| " at timestamp ", | ||
| Strings.toString(block.timestamp) | ||
| ); | ||
|
|
||
| uint256 bond = UMA_ORACLE.getMinimumBond(offer.exchangeToken); | ||
| IERC20 exchangeToken = IERC20(offer.exchangeToken); | ||
|
|
||
| exchangeToken.transferFrom(msg.sender, address(this), bond); | ||
| exchangeToken.approve(address(UMA_ORACLE), bond); | ||
|
|
||
| bytes32 domainId = bytes32(_exchangeId); | ||
| assertionId = UMA_ORACLE.assertTruth( | ||
| claim, | ||
| msg.sender, | ||
| address(this), | ||
| address(0), // we don't use specific escalation manager, but use the default one (DVN). | ||
| challengePeriod, | ||
| exchangeToken, | ||
| bond, | ||
| UMA_ASSERTION_IDENTIFIER, | ||
| domainId | ||
| ); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function _createUMAAssertion( | ||
| uint256 _exchangeId, | ||
| uint256 _buyerPercent, | ||
| string memory _additionalInfo | ||
| ) internal returns (bytes32 assertionId) { | ||
| // Get exchange and offer details | ||
| (, BosonTypes.Exchange memory exchange, ) = IBosonExchangeHandler(BOSON_PROTOCOL).getExchange(_exchangeId); | ||
| (, BosonTypes.Offer memory offer, , , , ) = IBosonOfferHandler(BOSON_PROTOCOL).getOffer(exchange.offerId); | ||
|
|
||
| // Create human-readable claim following UMA's example | ||
| bytes memory claim = abi.encodePacked( | ||
| "Boson Protocol dispute for exchange ", | ||
| Strings.toString(_exchangeId), | ||
| ": Buyer claims ", | ||
| Strings.toString(_buyerPercent), | ||
| "% of funds. ", | ||
| _additionalInfo, | ||
| " at timestamp ", | ||
| Strings.toString(block.timestamp) | ||
| ); | ||
|
|
||
| uint256 bond = UMA_ORACLE.getMinimumBond(offer.exchangeToken); | ||
| IERC20 exchangeToken = IERC20(offer.exchangeToken); | ||
|
|
||
| exchangeToken.transferFrom(msg.sender, address(this), bond); | ||
| exchangeToken.approve(address(UMA_ORACLE), bond); | ||
|
|
||
| bytes32 domainId = bytes32(_exchangeId); | ||
| assertionId = UMA_ORACLE.assertTruth( | ||
| claim, | ||
| msg.sender, | ||
| address(this), | ||
| address(0), // we don't use specific escalation manager, but use the default one (DVN). | ||
| challengePeriod, | ||
| exchangeToken, | ||
| bond, | ||
| UMA_ASSERTION_IDENTIFIER, | ||
| domainId | ||
| ); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
close #1006