Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}
"
},
"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165Upgradeable is Initializable, IERC165 {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
"
},
"@openzeppelin/contracts/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
"
},
"@openzeppelin/contracts/utils/Address.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
"
},
"@openzeppelin/contracts/utils/introspection/IERC165.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
"
},
"contracts/compiler/JitCompiler.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {
IDecreasePositionEvaluator,
IExchangeEvaluator,
IIncreasePositionEvaluator,
IJitCompiler
} from "contracts/interfaces/compiler/IJitCompiler.sol";
import {
ProtocolsEvaluatorsRepository
} from "contracts/compiler/libraries/ProtocolsEvaluatorsRepository.sol";
import {Address} from "contracts/libraries/Address.sol";
import {Command, CommandLibrary, SafeCall} from "contracts/libraries/CommandLibrary.sol";
import {Path} from "./libraries/Path.sol";
import {Script, ScriptCompiler} from "./libraries/ScriptCompiler.sol";
contract JitCompiler is IJitCompiler {
using ProtocolsEvaluatorsRepository for string;
using Address for address;
using SafeCall for address;
using CommandLibrary for Command[];
using Path for bytes;
using ScriptCompiler for Script;
function compile(Script calldata script) external override returns (Command[] memory result) {
result = new Command[](0);
for (uint256 index; index < script.sequence.length; index++) {
Command[] memory cmds = script.compileAt(
index,
compileIncreasePositionInstruction,
compileDecreasePositionInstruction,
compileExchangeInstruction,
compileExchangeAllInstruction
);
result = result.append(cmds);
}
}
function compileIncreasePositionInstruction(
IncreasePositionInstruction calldata _instruction
) public virtual override returns (Command[] memory) {
address adapter = _instruction.protocol.getProtocolEvaluator();
bytes memory result = adapter.safeDelegateCall(
abi.encodeCall(IIncreasePositionEvaluator.evaluate, (msg.sender, _instruction.request))
);
return abi.decode(result, (Command[]));
}
function compileDecreasePositionInstruction(
DecreasePositionInstruction calldata _instruction
) public virtual override returns (Command[] memory) {
address adapter = _instruction.protocol.getProtocolEvaluator();
bytes memory result = adapter.safeDelegateCall(
abi.encodeCall(IDecreasePositionEvaluator.evaluate, (msg.sender, _instruction.request))
);
return abi.decode(result, (Command[]));
}
function compileExchangeInstruction(
ExchangeInstruction calldata _instruction
) public virtual override returns (Command[] memory) {
address adapter = _instruction.protocol.getProtocolEvaluator();
bytes memory result = adapter.safeDelegateCall(
abi.encodeCall(IExchangeEvaluator.evaluate, (msg.sender, _instruction.request))
);
return abi.decode(result, (Command[]));
}
function compileExchangeAllInstruction(
ExchangeAllInstruction calldata _instruction
) public virtual override returns (Command[] memory) {
address adapter = _instruction.protocol.getProtocolEvaluator();
IExchangeEvaluator.ExchangeRequest memory req = _instruction.request;
address tokenIn = _instruction.request.path.extractTokenIn();
req.amountIn = tokenIn.isEth() ? msg.sender.balance : IERC20(tokenIn).balanceOf(msg.sender);
bytes memory result = adapter.safeDelegateCall(
abi.encodeCall(IExchangeEvaluator.evaluate, (msg.sender, req))
);
return abi.decode(result, (Command[]));
}
/* solhint-disable ordering */
function supportsInterfaceExtended(bytes4 interfaceId) external pure override returns (bool) {
return interfaceId == type(IJitCompiler).interfaceId;
}
/* solhint-enable ordering */
}
"
},
"contracts/compiler/libraries/Path.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
library Path {
using Path for bytes;
uint256 internal constant ADDRESS_LEN = 20;
uint256 internal constant POOL_ID_LEN = 4;
uint256 internal constant NEXT_OFFSET = ADDRESS_LEN + POOL_ID_LEN;
error InvalidPathLength(uint256);
function extractTokenIn(bytes calldata _path) internal pure returns (address tokenIn_) {
_path.ensureValid();
tokenIn_ = _path.extractTokenInUnsafe();
}
function extractTokenInUnsafe(bytes calldata _path) internal pure returns (address tokenIn_) {
tokenIn_ = address(bytes20(_path[0:ADDRESS_LEN]));
}
function extractTokenOut(bytes calldata _path) internal pure returns (address tokenOut_) {
_path.ensureValid();
tokenOut_ = _path.extractTokenOutUnsafe();
}
function extractTokenOutUnsafe(bytes calldata _path) internal pure returns (address tokenOut_) {
uint256 len = _path.length;
tokenOut_ = address(bytes20(_path[len - ADDRESS_LEN:len]));
}
/* solhint-disable var-name-mixedcase */
function extractPool(
bytes calldata _path,
uint256 _poolNumber
) internal pure returns (address tokenIn__, address tokenOut_, uint32 poolId_____) {
/* solhint-enable var-name-mixedcase */
_path.ensureValid();
uint256 ptr = _poolNumber * NEXT_OFFSET;
tokenIn__ = address(bytes20(_path[ptr:(ptr = ptr + ADDRESS_LEN)]));
poolId_____ = uint32(bytes4(_path[ptr:(ptr = ptr + POOL_ID_LEN)]));
tokenOut_ = address(bytes20(_path[ptr:(ptr = ptr + ADDRESS_LEN)]));
}
function getNumberOfPools(bytes calldata _path) internal pure returns (uint256) {
_path.ensureValid();
return (_path.length - ADDRESS_LEN) / NEXT_OFFSET;
}
function ensureValid(bytes calldata _path) internal pure {
if (!isValid(_path)) revert InvalidPathLength(_path.length);
}
function isValid(bytes calldata _path) private pure returns (bool) {
if (_path.length < ADDRESS_LEN) return false;
return (_path.length - ADDRESS_LEN) % NEXT_OFFSET == 0;
}
}
"
},
"contracts/compiler/libraries/ProtocolsEvaluatorsRepository.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
/* solhint-disable no-unused-import */
import {
IWhitelistingController,
ProtocolIsNotSupported,
ProtocolIsSuspended,
Status
} from "contracts/interfaces/compliance/IWhitelistingController.sol";
/* solhint-enable no-unused-import */
import {StringTruncatedHash} from "contracts/libraries/StringTruncatedHash.sol";
library ProtocolsEvaluatorsRepository {
using StringTruncatedHash for string;
struct Storage {
mapping(bytes31 protocolHash => address) evaluators;
}
// keccak256("Protocols Evaluators repository slot V1");
bytes32 private constant STORAGE_SLOT =
0x987bb3e6406b3909b0e08782298b4489c75b0d6678d6b023fe9f94ceaae0d14a;
error EvaluatorAddressMustNotBeZero(string protocol);
function updateEvaluator(
string calldata protocol,
address evaluator
) internal returns (bool storageModified) {
if (evaluator == address(0)) revert EvaluatorAddressMustNotBeZero(protocol);
Storage storage $ = _storage();
bytes31 protocolHash = protocol.truncatedHash();
if ($.evaluators[protocolHash] != evaluator) {
$.evaluators[protocolHash] = evaluator;
storageModified = true;
}
}
function getProtocolEvaluator(
string calldata protocol
) internal view returns (address evaluator) {
evaluator = _storage().evaluators[protocol.truncatedHash()];
if (evaluator == address(0)) revert EvaluatorAddressMustNotBeZero(protocol);
}
function _storage() private pure returns (Storage storage $) {
assembly {
$.slot := STORAGE_SLOT
}
}
}
"
},
"contracts/compiler/libraries/ScriptCompiler.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {Command, IJitCompiler, Script} from "contracts/interfaces/compiler/IJitCompiler.sol";
library ScriptCompiler {
error InvalidSequenceAtIndex(uint256 index);
// TODO: refactor this as soon as https://github.com/ethereum/solidity/issues/13776 closed
function compileAt(
Script calldata self,
uint256 index,
function(IJitCompiler.IncreasePositionInstruction calldata)
returns (Command[] memory) evalIPI,
function(IJitCompiler.DecreasePositionInstruction calldata)
returns (Command[] memory) evalDPI,
function(IJitCompiler.ExchangeInstruction calldata) returns (Command[] memory) evalEI,
function(IJitCompiler.ExchangeAllInstruction calldata) returns (Command[] memory) evalEAI
) internal returns (Command[] memory) {
uint256 ipLen = self.increasePositionInstructions.length;
uint256 dpLen = self.decreasePositionInstructions.length;
uint256 exLen = self.exchangeInstructions.length;
uint256 eaLen = self.exchangeAllInstructions.length;
uint256 idx = self.sequence[index];
uint256 maxIdx;
if (idx < (maxIdx = ipLen)) {
return evalIPI(self.increasePositionInstructions[idx]);
} else if (idx < (maxIdx += dpLen)) {
return evalDPI(self.decreasePositionInstructions[idx - (maxIdx - dpLen)]);
} else if (idx < (maxIdx += exLen)) {
return evalEI(self.exchangeInstructions[idx - (maxIdx - exLen)]);
} else if (idx < (maxIdx += eaLen)) {
return evalEAI(self.exchangeAllInstructions[idx - (maxIdx - eaLen)]);
} else {
revert InvalidSequenceAtIndex(index);
}
}
}
"
},
"contracts/interfaces/base/CommonErrors.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
/**
* @notice An error indicating that the amount for the specified token is zero.
* @param token The address of the token with a zero amount.
*/
error AmountMustNotBeZero(address token);
/**
* @notice An error indicating that an address must not be zero.
*/
error AddressMustNotBeZero();
/**
* @notice An error indicating that an array must not be empty.
*/
error ArrayMustNotBeEmpty();
/**
* @notice An error indicating that an string must not be empty.
*/
error StringMustNotBeEmpty();
/**
* @notice An error indicating storage is already up to date and doesn't need further processing.
* @dev This error is thrown when attempting to update an entity(s) that is(are) already up to date.
*/
error AlreadyUpToDate();
/**
* @notice An error indicating that an action is unauthorized for the specified account.
* @param account The address of the unauthorized account.
*/
error UnauthorizedAccount(address account);
/**
* @notice An error indicating that the min amount out must not be zero.
*/
error MinAmountOutMustNotBeZero();
"
},
"contracts/interfaces/base/IERC165Extended.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
/* solhint-disable no-unused-import */
import {
IERC165
} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
/* solhint-enable no-unused-import */
/**
* @notice An error indicating that an address does not support the expected interface
* @param implementation The address that does not implement the required interface
*/
error UnsupportedInterface(address implementation);
/**
* @dev Extended interface of the ERC165 standard to ensure compatibility
* with Diamond facets as defined in EIP-2535.
*
* This interface extends the basic ERC165 mechanism to provide additional
* flexibility for querying supported interfaces, which can then be
* dynamically resolved by one of facets in a Diamond.
*/
interface IERC165Extended {
/**
* @notice Checks if the given interface ID is supported by the contract.
* @param interfaceId The ID of the interface to query.
* @return isSupported Boolean value indicating whether the interface is supported.
*/
function supportsInterfaceExtended(bytes4 interfaceId) external pure returns (bool isSupported);
}
"
},
"contracts/interfaces/compiler/adapters/IDecreasePositionEvaluator.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {Asset} from "contracts/libraries/AssetLibrary.sol";
import {Command} from "../Command.sol";
import {PositionDescriptor} from "./PositionDescriptor.sol";
interface IDecreasePositionEvaluator {
/**
* @notice Request structure for decreasing a position.
* @dev `descriptor`: The [`PositionDescriptor`](/interfaces/compiler/adapters/PositionDescriptor.sol/struct.PositionDescriptor.html)
* struct.
* @dev `liquidity`: Abstract amount that can be interpreted differently in different protocols (e.g., amount of LP tokens to burn).
* @dev `minOutput`: [`Asset`](/interfaces/compliance/Asset.sol/struct.Asset.html) array with minimum amounts that must be retrieved from the position.
*/
struct DecreasePositionRequest {
PositionDescriptor descriptor;
uint256 liquidity;
Asset[] minOutput;
}
/**
* @notice Evaluate a decrease position request.
* @param _operator Address which initiated the request
* @param _request The [`DecreasePositionRequest`](#decreasepositionrequest) struct containing decrease position details.
* @return cmds_ An array of [`Command`](../../Command.sol/struct.Command.html) to execute the request.
*/
function evaluate(
address _operator,
DecreasePositionRequest calldata _request
) external returns (Command[] memory cmds_);
}
"
},
"contracts/interfaces/compiler/adapters/IExchangeEvaluator.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {Command} from "../Command.sol";
/**
* @title IExchangeEvaluator
* @notice Interface for compiling commands for token exchanges for different protocols.
*/
interface IExchangeEvaluator {
/**
* @notice Structure for an exchange token request.
* @dev `path`: Encoded path of tokens to follow in the exchange, including pool identifiers.
* 20 bytes(tokenA) + 4 byte(poolId_A_B) + 20 bytes(tokenB) + ...
* ... + 4 byte(poolId_N-1_N) + 20 bytes(tokenN).
* @dev `extraData`: Additional data specific to a particular protocol, such as the response from a 1Inch Exchange API.
* @dev `amountIn`: The amount of tokenA to spend.
* @dev `minAmountOut`: The minimum amount of tokenN to receive.
* @dev `recipient`: The recipient of tokenN.
*/
struct ExchangeRequest {
bytes path;
bytes extraData;
uint256 amountIn;
uint256 minAmountOut;
address recipient;
}
/**
* @notice Constructs an exchange token request.
* @param _operator Address which initiated the request
* @param _request The [`ExchangeRequest`](#exchangerequest) struct containing exchange token details.
* @return cmds_ An array of [`Command`](../../Command.sol/struct.Command.html) to execute the request.
*/
function evaluate(
address _operator,
ExchangeRequest calldata _request
) external view returns (Command[] memory cmds_);
}
"
},
"contracts/interfaces/compiler/adapters/IIncreasePositionEvaluator.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {Asset} from "contracts/libraries/AssetLibrary.sol";
import {Command} from "../Command.sol";
import {PositionDescriptor} from "./PositionDescriptor.sol";
interface IIncreasePositionEvaluator {
/**
* @notice Structure for an increase position request.
* @dev `descriptor`: The [`PositionDescriptor`](/interfaces/compiler/adapters/PositionDescriptor.sol/struct.PositionDescriptor.html)
* struct.
* @dev `input`: An array of [`Asset`](/interfaces/compliance/Asset.sol/struct.Asset.html) representing the token-amounts that will be added to the position.
* @dev `minLiquidityOut`: An abstract amount that can be interpreted differently in different protocols (e.g., minimum amount of LP tokens to receive).
*/
struct IncreasePositionRequest {
PositionDescriptor descriptor;
Asset[] input;
uint256 minLiquidityOut;
}
/**
* @notice Evaluate a increase position request.
* @param _operator Address which initiated the request
* @param _request The [`IncreasePositionRequest`](#increasepositionrequest) struct containing increase position details.
* @return cmds_ An array of [`Command`](../../Command.sol/struct.Command.html) to execute the request.
*/
function evaluate(
address _operator,
IncreasePositionRequest calldata _request
) external returns (Command[] memory cmds_);
}
"
},
"contracts/interfaces/compiler/adapters/PositionDescriptor.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
// TODO CRYPTO-145: Possibly move into appropriate interface?
/**
* @notice Used to determine the required position for an operation.
* @dev `poolId`: An identifier that is unique within a single protocol.
* @dev `extraData`: Additional data used to specify the position, for example
* this is used in OneInchV5Evaluator to pass swap tx generated via 1inch API.
*/
struct PositionDescriptor {
uint256 poolId;
bytes extraData;
}
"
},
"contracts/interfaces/compiler/Command.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {CommandLibrary} from "contracts/libraries/CommandLibrary.sol";
/**
* @title Command
* @notice Contains arguments for a low-level call.
* @dev This struct allows deferring the call's execution, suspending it by passing it to another function or contract.
* @dev `target` The address to be called.
* @dev `value` Value to send in the call.
* @dev `payload` Encoded call with function selector and arguments.
*/
struct Command {
address target;
uint256 value;
bytes payload;
}
using CommandLibrary for Command global;
"
},
"contracts/interfaces/compiler/IJitCompiler.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {IERC165Extended} from "contracts/interfaces/base/IERC165Extended.sol";
import {IDecreasePositionEvaluator} from "./adapters/IDecreasePositionEvaluator.sol";
import {IExchangeEvaluator} from "./adapters/IExchangeEvaluator.sol";
import {IIncreasePositionEvaluator} from "./adapters/IIncreasePositionEvaluator.sol";
import {Command} from "./Command.sol";
import {Script} from "./Script.sol";
/**
* @title IJitCompiler
* @notice Compiles a script or an instruction into an array of [Commands](/interfaces/compiler/Command.sol/struct.Command.html) using protocol evaluator matching `protocol` field in the underlying instruction.
*/
interface IJitCompiler is IERC165Extended {
/**
* @notice Instruction designed to increase:
* 1. Caller's magnitude of the position determined by the [PositionDescriptor](../adapters/PositionDescriptor.sol/struct.PositionDescriptor.html).
* 2. Callee's balance of token(s).
* @notice and decrease:
* 1. Caller's balance of token(s).
* 2. (*Optional*) callee's supply of the position determined by the [PositionDescriptor](../adapters/PositionDescriptor.sol/struct.PositionDescriptor.html).
* @dev This instruction will be evaluated in [IncreasePositionEvaluator](../adapters/IIncreasePositionEvaluator.sol/interface.IIncreasePositionEvaluator.html).
* @dev `protocol` The name of the underlying protocol where instruction should be evaluated. For example: `curvefi`, `oneinchv5`
* @dev `request` The [`IncreasePositionRequest`](../adapters/IIncreasePositionEvaluator.sol/interface.IIncreasePositionEvaluator.html#increasepositionrequest) containing all information required for instruction evaluation.
*/
struct IncreasePositionInstruction {
string protocol;
IIncreasePositionEvaluator.IncreasePositionRequest request;
}
/**
* @notice Instruction designed to increase:
* 1. Caller's balance of token(s).
* 2. (*Optional*) callee's supply of the position determined by the [PositionDescriptor](../adapters/PositionDescriptor.sol/struct.PositionDescriptor.html).
* @notice and decrease:
* 1. Caller's magnitude of the position determined by the [PositionDescriptor](../adapters/PositionDescriptor.sol/struct.PositionDescriptor.html).
* 2. Callee's balance of token(s).
* @dev This instruction will be evaluated in [DecreasePositionEvaluator](../adapters/IDecreasePositionEvaluator.sol/interface.IDecreasePositionEvaluator.html).
* @dev `protocol` The name of the underlying protocol where instruction should be evaluated. For example: `curvefi`, `oneinchv5`
* @dev `request` The [`DecreasePositionRequest`](../adapters/IDecreasePositionEvaluator.sol/interface.IDecreasePositionEvaluator.html#decreasepositionrequest) containing all information required for instruction evaluation.
*/
struct DecreasePositionInstruction {
string protocol;
IDecreasePositionEvaluator.DecreasePositionRequest request;
}
/**
* @notice Instruction designed to increase:
* 1. (*Optional*) caller's balance of output token.
* 2. Callee's balance of input token.
* @notice and decrease:
* 1. Caller's balance of input token.
* 2. (*Optional*) callee's balance of output token.
* @dev This instruction will be evaluated in [ExchangeEvaluator](../adapters/IExchangeEvaluator.sol/interface.IExchangeEvaluator.html).
* @dev `protocol` The name of the underlying protocol where instruction should be evaluated. For example: `curvefi`, `oneinchv5`
* @dev `request` The [`ExchangeRequest`](../adapters/IExchangeEvaluator.sol/interface.IExchangeEvaluator.html#exchangerequest) containing all information required for instruction evaluation.
*/
struct ExchangeInstruction {
string protocol;
IExchangeEvaluator.ExchangeRequest request;
}
/**
* @notice Instruction designed to increase:
* 1. (*Optional*) caller's balance of output token.
* 2. Callee's balance of input token.
* @notice and decrease:
* 1. Caller's balance of input token.
* 2. (*Optional*) callee's balance of output token.
* @dev This instruction will be evaluated in [ExchangeEvaluator](../adapters/IExchangeEvaluator.sol/interface.IExchangeEvaluator.html).
* @dev **Important note:** this instruction has an identical structure to [ExchangeInstruction](#exchangeinstruction), but differs from it in that [ExchangeInstruction](#exchangeinstruction) is static and [ExchangeAllInstruction](#exchangeallinstruction) is dynamic. This means that the `amountIn` field will be set at runtime by the compiler to the caller's balance by the input token.
* @dev `protocol` The name of the underlying protocol where instruction should be evaluated. For example: `curvefi`, `oneinchv5`
* @dev `request` The [`ExchangeRequest`](../adapters/IExchangeEvaluator.sol/interface.IExchangeEvaluator.html#exchangerequest) containing all information required for instruction evaluation. The `amountIn` field will be set at runtime by the compiler to the caller's balance by the input token.
*/
struct ExchangeAllInstruction {
string protocol;
IExchangeEvaluator.ExchangeRequest request;
}
/**
* @notice Compiles a [Script](../Script.sol/struct.Script.html).
* @dev **Important note:** don't put two instructions to the same script if one depend on the other because content of the script will be compiled at once meaning that balance changes will be applied only after the compilation of the entire script. If you have two instructions and one depends on the other, put them into different scripts.
* @param script Script to compile
* @return An array of [`Commands`](../Command.sol/struct.Command.html) to execute the instruction.
*/
function compile(Script calldata script) external returns (Command[] memory);
/**
* @notice Compiles an increase position instruction.
* @param instruction The [`IncreasePositionInstruction`](#increasepositioninstruction) struct.
* @return An array of [`Commands`](../Command.sol/struct.Command.html) to execute the instruction.
*/
function compileIncreasePositionInstruction(
IncreasePositionInstruction calldata instruction
) external returns (Command[] memory);
/**
* @notice Compiles a decrease position instruction.
* @param instruction The [`DecreasePositionInstruction`](#decreasepositioninstruction) struct.
* @return An array of [`Commands`](../Command.sol/struct.Command.html) to execute the instruction.
*/
function compileDecreasePositionInstruction(
DecreasePositionInstruction calldata instruction
) external returns (Command[] memory);
/**
* @notice Compiles an exchange instruction.
* @param instruction The [`ExchangeInstruction`](#exchangeinstruction) struct.
* @return An array of [`Commands`](../Command.sol/struct.Command.html) to execute the instruction.
*/
function compileExchangeInstruction(
ExchangeInstruction calldata instruction
) external returns (Command[] memory);
/**
* @notice Sets the `amountIn` field to the balance of the caller by the input token and compiles an underlying exchange instruction.
* @dev `amountIn` will be overridden with the balance of the caller by the input token.
* @param instruction The [`ExchangeAllInstruction`](#exchangeallinstruction) struct.
* @return An array of [`Commands`](../Command.sol/struct.Command.html) to execute the instruction.
*/
function compileExchangeAllInstruction(
ExchangeAllInstruction calldata instruction
) external returns (Command[] memory);
}
"
},
"contracts/interfaces/compiler/Script.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {IJitCompiler} from "./IJitCompiler.sol";
/**
* @title Script
* @notice A structure defining a script with various instructions for a JIT compiler.
* @notice The [JIT compiler](../IJitCompiler.sol/interface.IJitCompiler.html)
* will compile it the following way:
* 1. Flatten content's instructions arrays into a single-dimensional array: `flattened =
* [...increasePositionInstructions, ...decreasePositionInstructions,
...exchangeInstructions, ...exchangeAllInstructions]`.
* 2. Execute `flattened[PC]` where `PC = sequence[i]` where `i` is the
* index of current loop iteration, starting from `i = 0`.
* 3. Increment current loop iteration index: `i = i + 1`.
* 4. If `i < length(flattened)` go to step 2.
*
* @dev `canFail` Determines whether the script can silently fail. If true
* transaction will not be reverted but execution will be terminated.
* @dev `sequence` Auto-incrementing read-only program counter. Determines the
* order of execution of the instruction within the script.
* @dev `increasePositionInstructions` An array of
* [`IncreasePositionInstructions`](../IJitCompiler.sol/interface.IJitCompiler.html#increasepositioninstruction).
* @dev `decreasePositionInstructions` An array of
* [`DecreasePositionInstructions`](../IJitCompiler.sol/interface.IJitCompiler.html#decreasepositioninstruction).
* @dev `exchangeInstructions` An array of
* [`ExchangeInstructions`](../IJitCompiler.sol/interface.IJitCompiler.html#exchangeinstruction).
* @dev `exchangeAllInstructions` An array of
* [`ExchangeAllInstructions`](../IJitCompiler.sol/interface.IJitCompiler.html#exchangeallinstruction).
*/
struct Script {
bool canFail;
uint256[] sequence;
IJitCompiler.IncreasePositionInstruction[] increasePositionInstructions;
IJitCompiler.DecreasePositionInstruction[] decreasePositionInstructions;
IJitCompiler.ExchangeInstruction[] exchangeInstructions;
IJitCompiler.ExchangeAllInstruction[] exchangeAllInstructions;
}
"
},
"contracts/interfaces/compliance/Asset.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {AssetLibrary} from "contracts/libraries/AssetLibrary.sol";
/**
* @title Asset
* @dev Represents an asset with its token address and the amount.
* @param token The address of the asset's token.
* @param amount The amount of the asset.
*/
struct Asset {
address token;
uint256 amount;
}
using AssetLibrary for Asset global;
"
},
"contracts/interfaces/compliance/IWhitelistingController.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
import {IERC165Extended} from "../base/IERC165Extended.sol";
import {IWhitelistingControllerAgreement} from "./IWhitelistingControllerAgreement.sol";
/**
* @title Status
* @notice Enum representing status of a record (e.g., token, protocol, operator)
* used for operation validation.
* @notice Validators must adhere to the following rules for different operations and contexts:
* 1) For exchanges: `operator`, `pool`, and `input token` *MAY* be either supported or suspended, but the `output token` *MUST* be supported.
* 2) For deposits: `operator`, `pool`, and every `token` in the `pool` *MUST* be supported.
* 3) For withdrawals: `operator`, `pool`, and each `token` *MAY* be either supported or suspended.
*
* @dev **Note** that deposit denotes **all** ways of acquiring liquidity such
* as token deposit, LP tokens stake, NFT mint etc.
*/
enum Status {
Undefined,
Supported,
Suspended
}
/**
* @title WhitelistingAddressRecord
* @notice A struct to store an address and its support status.
* @dev This struct stores an address and its support status.
* @dev `source`: The address to be stored.
* @dev `supported`: Indicates whether the address is supported or not.
*/
struct WhitelistingAddressRecord {
address source;
bool supported;
}
/**
* @title WhitelistingTokenRecord
* @notice This struct stores an address and its support status for whitelisting, collateral and leverage.
* @dev `source`: The address of the token.
* @dev `supported`: Whether the token can be received from a protocol trades.
*/
struct WhitelistingTokenRecord {
address source;
bool supported;
}
/**
* @notice An error indicating that a token is not supported by the whitelisting controller.
* @dev This error is thrown when an unsupported token is used.
* @dev `token`: The address of the unsupported token.
*/
error TokenIsNotSupported(address token);
/**
* @notice An error indicating that a token is suspended by the whitelisting controller.
* @dev This error is thrown when a suspended token is used.
* @dev `token`: The address of the suspended token.
*/
error TokenIsSuspended(address token);
/**
* @notice An error indicating that an operator is not supported by the whitelisting controller.
* @dev This error is thrown when an unsupported operator is used.
* @dev `operator`: The address of the unsupported operator.
*/
error OperatorIsNotSupported(address operator);
/**
* @notice An error indicating that an operator is suspended by the whitelisting controller.
* @dev This error is thrown when a suspended operator is used.
* @dev `operator`: The address of the suspended operator.
*/
error OperatorIsSuspended(address operator);
/**
* @notice An error indicating that a protocol is not supported by the whitelisting controller.
* @dev This error is thrown when an unsupported protocol is used.
* @dev `protocol`: The identification string of the unsupported protocol.
*/
error ProtocolIsNotSupported(bytes31 protocolNameHash);
/**
* @notice An error indicating that a protocol is suspended by the whitelisting controller.
* @dev This error is thrown when a suspended protocol is used.
* @dev `protocol`: The identification string of the unsupported protocol.
*/
error ProtocolIsSuspended(bytes31 protocolNameHash);
interface ITenant {
function factory() external view returns (address);
}
/**
* @title IWhitelistingController
* @notice Interface for managing whitelisting of tokens, protocols, and operators.
*/
interface IWhitelistingController is IWhitelistingControllerAgreement, IERC165Extended {
/**
* @dev Emitted when the support status of a protocol changes.
* @dev `protocol`: The identification string of the protocol.
* @dev `supported`: Whether the protocol is supported or not.
*/
event ProtocolSupportChanged(string indexed protocol, bool supported);
/**
* @dev Emitted when the support status of a token changes.
* @dev `token`: The address of the token.
* @dev `supported`: Whether the token is supported or not.
*/
event TokenSupportChanged(address indexed token, bool supported);
/**
* @dev Emitted when the support status of an operator changes for a specific protocol.
* @dev `protocol`: The identification string of the protocol.
* @dev `operator`: The address of the operator.
* @dev `supported`: Whether the operator is supported or not.
*/
event OperatorSupportChanged(string indexed protocol, address indexed operator, bool supported);
/**
* @notice Reverts when the agreement was deployed by a different factory version.
* @dev This error is used by the `onlyAgreementFactory` modifier to prevent
* `addTokens` and `addOperators` calls from wrong factory.
* @param factory The address of the factory attempting to interact.
* @param agreement The agreement contract whose associated factory version did not match the caller.
*/
error AgreementFactoryVersionMismatch(address factory, address agreement);
/**
* @notice Reverts when the caller contract supports a prohibited interface.
* @dev This error is used by the `notMarginAccount` modifier to prevent
* function calls from contracts that implement the `IAccount` interface.
* @param caller The address of the caller contract
*/
error CallerSupportsForbiddenInterface(address caller);
/**
* @notice An error indicating that the provided address is not a valid token address.
* @dev This error is thrown when the address does not conform to the expected token interface.
* @param token The address that failed the token validation check.
*/
error InvalidTokenAddress(address token);
/**
* @notice Update the support status of multiple tokens.
* @dev Emits a [`TokenSupportChanged()`](#tokensupportchanged) event for each token whose status changed.
* @dev Reverts with an [`AlreadyUpToDate()`](/interfaces/base/CommonErrors.sol/error.AlreadyUpToDate.html)
* error if no token status changed.
* @param _tokens An array of [`WhitelistingTokenRecord`](./struct.WhitelistingTokenRecord.html)
* structs containing token addresses and support.
*/
function updateTokensSupport(WhitelistingTokenRecord[] calldata _tokens) external;
/**
* @notice Update the support status of a protocol.
* @dev Emits a [`ProtocolSupportChanged()`](#protocolsupportchanged) event.
* @dev Reverts with an [`AlreadyUpToDate()`](/interfaces/base/CommonErrors.sol/error.AlreadyUpToDate.html)
* error if protocol status is up to date.
* @param _protocol The identification string of the protocol.
* @param _supported Whether the protocol is supported or not.
*/
function updateProtocolSupport(string calldata _protocol, bool _supported) external;
/**
* @notice Update the support status of multiple operators for a specific protocol.
* @dev Emits a [`OperatorSupportChanged()`](#operatorsupportchanged) event for each token whose status changed.
* @dev Reverts with an [`AlreadyUpToDate()`](/interfaces/base/CommonErrors.sol/error.AlreadyUpToDate.html)
* error if no operator status changed.
* @param _protocol The identification string of the protocol.
* @param _operators An array of `WhitelistingAddressRecord` structs containing operator addresses and support statuses.
*/
function updateOperatorsSupport(
string calldata _protocol,
WhitelistingAddressRecord[] calldata _operators
) external;
/**
* @notice Returns the support status of a token.
* @param _token The address of the token.
* @return The [`Status`](./enum.Status.html) of the token.
*/
function getTokenStatus(address _token) external view returns (Status);
/**
* @notice Checks whether a specific token is supported by a tenant.
* @dev This function returns a boolean indicating if the given token is supported by the specified tenant.
* @param tenant The address of the tenant to check.
* @param token The address of the token to check for support.
* @return A boolean value indicating whether the token is supported by the tenant.
*/
function getTokenSupport(address tenant, address token) external view returns (bool);
/**
* @notice Retrieves the list of tokens supported by a specific tenant.
* @dev This function returns an array of token addresses that are supported by the specified tenant.
* @param tenant The address of the tenant whose supported tokens are to be retrieved.
* @return An array of addresses representing the tokens supported by the tenant.
*/
function getTokens(address tenant) external view returns (address[] memory);
/**
* @notice Returns the support status of a protocol.
* @param protocol The identification string of the protocol.
* @return The [`Status`](./enum.Status.html)
* of the protocol.
*/
function getProtocolStatus(string calldata protocol) external view returns (Status);
/**
* @notice Returns the support status of an operator for a specific protocol.
* @param _operator The address of the operator.
* @return operatorStatus_ The [`Status`](./enum.Status.html)
* of the operator.
* @return protocolStatus_ The [`Status`](./enum.Status.html)
* of the protocol.
*/
function getOperatorStatus(
address _operator
) external view returns (Status operatorStatus_, Status protocolStatus_);
}
"
},
"contracts/interfaces/compliance/IWhitelistingControllerAgreement.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
/**
* @title IWhitelistingControllerAgreement
* @notice Interface for managing whitelisting of tokens and operators for Agreements.
*/
interface IWhitelistingControllerAgreement {
/**
* @notice Emitted when a new token is added for a specific tenant.
* @param tenant The address of the tenant to whom the token is added.
* @param token The address of the token that has been added.
*/
event TokenAdded(address tenant, address token);
/**
* @notice Emitted when a new operator is added for a specific tenant.
* @param tenant The address of the tenant to whom the operator is added.
* @param operator The address of the operator that has been added.
*/
event OperatorAdded(address tenant, address operator);
/**
* @notice Adds a list of tokens to the specified tenant.
* @param tenant The address of the tenant to which the tokens will be added.
* @param tokens An array of addresses representing the tokens to be added.
* @dev This function can be used to update the list of supported tokens for a given tenant.
*/
function addTokens(address tenant, address[] calldata tokens) external;
/**
* @notice Adds a list of operators to the specified tenant.
* @param tenant The address of the tenant to which the operators will be added.
* @param operators An array of addresses representing the operators to be added.
* @dev This function updates the list of authorized operators for a given tenant.
*/
function addOperators(address tenant, address[] calldata operators) external;
/**
* @notice Returns the address of the agreement factory contract.
* @return The address of the agreement factory.
* @dev The agreement factory is used to create and manage agreements.
*/
function agreementFactory() external view returns (address);
/**
* @notice Returns the address of the agreement V2 factory contract.
* @return The address of the agreement V2 factory.
* @dev The agreement V2 factory is used to create and manage agreements V2.
*/
function agreementV2Factory() external view returns (address);
/**
* @notice Checks if a specific token is supported for a given tenant.
* @param tenant The address of the tenant whose supported tokens are being queried.
* @param token The address of the token to check for support.
* @return A boolean indicating whether the token is supported by the tenant.
* @dev This function will return `true` if the token is supported, and `false` otherwise.
*/
function getTokenSupport(address tenant, address token) external view returns (bool);
/**
* @notice Retrieves a list of tokens supported by a specific tenant.
* @param tenant The address of the tenant whose supported tokens are being queried.
* @return An array of token addresses supported by the specified tenant.
* @dev This function returns an array containing the addresses of tokens that the tenant supports.
* It is a view function and does not modify the contract state.
*/
function getTokens(address tenant) external view returns (address[] memory);
/**
* @notice Checks if a specific operator is supported by a given tenant.
* @param tenant The address of the tenant whose supported operators are being queried.
* @param operator The address of the operator to check for support.
* @return A boolean value indicating whether the operator is supported by the tenant.
* @dev This function returns `true` if the operator is supported by the specified tenant, and `false` otherwise.
* It is a view function and does not modify the contract state.
*/
function getOperatorSupport(address tenant, address operator) external view returns (bool);
/**
* @notice Retrieves the list of operators associated with a specific tenant.
* @param tenant The address of the tenant whose operators are being queried.
* @return A dynamically-sized array of addresses representing the operators associated with the tenant.
* @dev This function is a view function and does not modify the contract state.
*/
function getOperators(address tenant) external view returns (address[] memory);
}
"
},
"contracts/libraries/Address.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.22;
library Address {
address internal constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
function set(bytes32 _slot, address _value) internal {
assembly {
sstore(_slot, _value)
}
}
function get(bytes32 _slot) internal view returns (address result_) {
assembly {
result_ := sload(
Submitted on: 2025-10-14 12:21:04
Comments
Log in to comment.
No comments yet.