Skip to content

Commit 79063aa

Browse files
ayobuenavistailanDoron
authored andcommitted
Fix a hint handler bug, where it doesn't allow empty hint for one side of T2T hint
* Add a new hint type: best-of-all which is actually like an empty hint. * New type enables one side in token to token trade to have an empty hint. * best-of-all hint type actually triggers the "default" Kyber algorithm which chooses the reserve with the best rate for the taker
1 parent 57c1143 commit 79063aa

8 files changed

+380
-50
lines changed

Diff for: contracts/sol6/IKyberHint.sol

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import "./IKyberReserve.sol";
44

55

66
interface IKyberHint {
7-
enum TradeType {MaskIn, MaskOut, Split}
7+
enum TradeType {BestOfAll, MaskIn, MaskOut, Split}
88
enum HintErrors {
99
NoError, // Hint is valid
10+
NonEmptyDataError, // reserveIDs and splits must be empty for BestOfAll hint
1011
ReserveIdDupError, // duplicate reserveID found
1112
ReserveIdEmptyError, // reserveIDs array is empty for MaskIn and Split trade type
1213
ReserveIdSplitsError, // reserveIDs and splitBpsValues arrays do not have the same length

Diff for: contracts/sol6/KyberHintHandler.sol

+5
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,10 @@ abstract contract KyberHintHandler is IKyberHint, Utils5 {
406406
bytes32[] memory reserveIds,
407407
uint256[] memory splits
408408
) internal pure returns (HintErrors) {
409+
if (tradeType == TradeType.BestOfAll) {
410+
if (reserveIds.length != 0 || splits.length != 0) return HintErrors.NonEmptyDataError;
411+
}
412+
409413
if (
410414
(tradeType == TradeType.MaskIn || tradeType == TradeType.Split) &&
411415
reserveIds.length == 0
@@ -430,6 +434,7 @@ abstract contract KyberHintHandler is IKyberHint, Utils5 {
430434
/// @notice Throws error message to user to indicate error on hint
431435
/// @param error Error type from HintErrors enum
432436
function throwHintError(HintErrors error) internal pure {
437+
if (error == HintErrors.NonEmptyDataError) revert("reserveIds and splits must be empty");
433438
if (error == HintErrors.ReserveIdDupError) revert("duplicate reserveId");
434439
if (error == HintErrors.ReserveIdEmptyError) revert("reserveIds cannot be empty");
435440
if (error == HintErrors.ReserveIdSplitsError) revert("reserveIds.length != splits.length");

Diff for: contracts/sol6/KyberMatchingEngine.sol

+6-3
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,16 @@ contract KyberMatchingEngine is KyberHintHandler, IKyberMatchingEngine, Withdraw
109109

110110
if (tradeType == TradeType.MaskIn) {
111111
splitValuesBps = populateSplitValuesBps(reserveIds.length);
112-
} else if (tradeType == TradeType.MaskOut) {
113-
// if mask out, apply masking out logic
112+
} else if (tradeType == TradeType.BestOfAll || tradeType == TradeType.MaskOut) {
114113
bytes32[] memory allReserves = (dest == ETH_TOKEN_ADDRESS)
115114
? kyberStorage.getReserveIdsPerTokenSrc(src)
116115
: kyberStorage.getReserveIdsPerTokenDest(dest);
117116

118-
reserveIds = maskOutReserves(allReserves, reserveIds);
117+
// if bestOfAll, reserveIds = allReserves
118+
// if mask out, apply masking out logic
119+
reserveIds = (tradeType == TradeType.BestOfAll) ?
120+
allReserves :
121+
maskOutReserves(allReserves, reserveIds);
119122
splitValuesBps = populateSplitValuesBps(reserveIds.length);
120123
}
121124

0 commit comments

Comments
 (0)