Skip to content

Conversation

@0xlucian
Copy link
Contributor

close #1006

@0xlucian 0xlucian self-assigned this Aug 21, 2025
@0xlucian 0xlucian marked this pull request as ready for review August 22, 2025 10:22
Comment on lines +106 to +136
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);
}
Comment on lines +106 to +136
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);
}
Comment on lines +106 to +136
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);
}
Comment on lines +158 to +183
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);
}
Comment on lines +158 to +183
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);
}
Comment on lines +332 to +342
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();
}
}
Comment on lines +359 to +398
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

Comment on lines +359 to +398
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
);
}
Comment on lines +359 to +398
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
);
}
Comment on lines +359 to +398
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

@coveralls
Copy link

Coverage Status

coverage: 98.65% (+0.03%) from 98.625%
when pulling 10c7867 on 1006-uma-dr-adapter
into 6a14c31 on main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UMA adapter

3 participants