feat(libraries): add byte slicing and multi-hop path encoding
This commit is contained in:
1 parent
25bb567003
commit
54b5377369
2 files changed
+90
No files matched your search
@@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity 0.8.36;
|
||||||
|
|
||||||
|
/// @title Slicing and word reads over tightly packed calldata paths.
|
||||||
|
library BytesLib {
|
||||||
|
function slice(bytes memory source, uint256 start, uint256 length) internal pure returns (bytes memory) {
|
||||||
|
require(length + 31 >= length, "BytesLib: SLICE_OVERFLOW");
|
||||||
|
require(source.length >= start + length, "BytesLib: SLICE_OOB");
|
||||||
|
|
||||||
|
bytes memory result;
|
||||||
|
assembly {
|
||||||
|
switch iszero(length)
|
||||||
|
case 0 {
|
||||||
|
result := mload(0x40)
|
||||||
|
let lengthmod := and(length, 31)
|
||||||
|
let mc := add(add(result, lengthmod), mul(0x20, iszero(lengthmod)))
|
||||||
|
let end := add(mc, length)
|
||||||
|
for {
|
||||||
|
let cc := add(add(add(source, lengthmod), mul(0x20, iszero(lengthmod))), start)
|
||||||
|
} lt(mc, end) {
|
||||||
|
mc := add(mc, 0x20)
|
||||||
|
cc := add(cc, 0x20)
|
||||||
|
} { mstore(mc, mload(cc)) }
|
||||||
|
mstore(result, length)
|
||||||
|
mstore(0x40, and(add(mc, 31), not(31)))
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
result := mload(0x40)
|
||||||
|
mstore(result, 0)
|
||||||
|
mstore(0x40, add(result, 0x20))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toAddress(bytes memory source, uint256 start) internal pure returns (address) {
|
||||||
|
require(source.length >= start + 20, "BytesLib: ADDRESS_OOB");
|
||||||
|
address result;
|
||||||
|
assembly {
|
||||||
|
result := div(mload(add(add(source, 0x20), start)), 0x1000000000000000000000000)
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toUint24(bytes memory source, uint256 start) internal pure returns (uint24) {
|
||||||
|
require(source.length >= start + 3, "BytesLib: UINT24_OOB");
|
||||||
|
uint24 result;
|
||||||
|
assembly {
|
||||||
|
result := mload(add(add(source, 0x3), start))
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity 0.8.36;
|
||||||
|
|
||||||
|
import {BytesLib} from "./BytesLib.sol";
|
||||||
|
|
||||||
|
/// @title Encoding of multi-hop swap paths as packed token/fee/token sequences.
|
||||||
|
library Path {
|
||||||
|
using BytesLib for bytes;
|
||||||
|
|
||||||
|
uint256 private constant addrSize = 20;
|
||||||
|
uint256 private constant feeSize = 3;
|
||||||
|
uint256 private constant nextOffset = addrSize + feeSize;
|
||||||
|
uint256 private constant popOffset = nextOffset + addrSize;
|
||||||
|
uint256 private constant multiplePoolsMinLength = popOffset + nextOffset;
|
||||||
|
|
||||||
|
function hasMultiplePools(bytes memory path) internal pure returns (bool) {
|
||||||
|
return path.length >= multiplePoolsMinLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
function numPools(bytes memory path) internal pure returns (uint256) {
|
||||||
|
return (path.length - addrSize) / nextOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodeFirstPool(bytes memory path) internal pure returns (address tokenA, address tokenB, uint24 fee) {
|
||||||
|
tokenA = path.toAddress(0);
|
||||||
|
fee = path.toUint24(addrSize);
|
||||||
|
tokenB = path.toAddress(nextOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFirstPool(bytes memory path) internal pure returns (bytes memory) {
|
||||||
|
return path.slice(0, popOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
function skipToken(bytes memory path) internal pure returns (bytes memory) {
|
||||||
|
return path.slice(nextOffset, path.length - nextOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user