Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/oracles/providers/RedStonePullOracle.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { PrimaryProdDataServiceConsumerBase } from
"redstone-finance/data-services/PrimaryProdDataServiceConsumerBase.sol";
import { SystemComponent } from "src/SystemComponent.sol";
import { SecurityBase } from "src/security/SecurityBase.sol";
import { ISystemRegistry } from "src/interfaces/ISystemRegistry.sol";
import { ISystemComponent } from "src/interfaces/ISystemComponent.sol";
import { ICustomSetOracle } from "src/interfaces/oracles/ICustomSetOracle.sol";
import { BaseOracleDenominations } from "src/oracles/providers/base/BaseOracleDenominations.sol";
import { Errors } from "src/utils/Errors.sol";
import { Roles } from "src/libs/Roles.sol";
/**
* @notice This contract is used to adapt the Redstone oracle payloads sent by our backend for the CustomSetOracle
* updates.
* The main logic is implemented in the updatePriceWithFeedId function.
* The rest of the functions are used to register and manage the feedId to token address mapping and authorized signers
* who we trust to sign the Redstone payload.
* @dev This contract extends a hierarchy of Redstone contracts that are able to fetch the Redstone payload from the
* transactions calldata.
* ref: https://docs.redstone.finance/docs/get-started/models/redstone-pull/#manual-payload
*/
contract RedStonePullOracle is PrimaryProdDataServiceConsumerBase, SystemComponent, SecurityBase {
event FeedIdRegistered(bytes32 indexed feedId, address indexed tokenAddress, bool ethQuoted, uint256 feedDecimals);
event FeedIdRemoved(bytes32 indexed feedId);
error TokenNotRegistered(bytes32 feedId, address tokenAddress);
/// @dev Constant referenced from BaseOracleDenominations contract
address public constant ETH_IN_USD = address(bytes20("ETH_IN_USD"));
ICustomSetOracle public immutable customOracle;
uint8 public uniqueSignersThreshold;
struct FeedId {
address tokenAddress;
bool ethQuoted;
uint8 feedDecimals;
}
/// @notice Mapping between a Redstone feedId and token address and if the price is quoted in ETH
mapping(bytes32 => FeedId) public registeredFeedIds;
/// @notice Mapping between an authorized signer address and its index for faster lookup
mapping(address => uint8) internal signerAddressToIndex;
/// @notice Array of authorized signers
address[] private _authorizedSigners;
constructor(
ISystemRegistry _systemRegistry,
address _customOracle,
uint8 _uniqueSignersThreshold,
address[] memory initAuthorizedSigners
) SystemComponent(_systemRegistry) SecurityBase(address(_systemRegistry.accessController())) {
Errors.verifyNotZero(_customOracle, "customOracle");
customOracle = ICustomSetOracle(_customOracle);
// Verify that the custom oracle is from the same system registry as the adapter
address customOracleSystemRegistry = ISystemComponent(_customOracle).getSystemRegistry();
if (address(_systemRegistry) != customOracleSystemRegistry) {
revert Errors.SystemMismatch(address(_systemRegistry), customOracleSystemRegistry);
}
uniqueSignersThreshold = _uniqueSignersThreshold;
_initializeSignerAddressToIndex(initAuthorizedSigners);
}
/// @notice Returns array of authorized signer addresses
/// @return Array of authorized signer addresses
function authorizedSigners() external view returns (address[] memory) {
return _authorizedSigners;
}
///@notice Sets the price from extracted and validated Redstone payload
function updatePriceWithFeedId(
bytes32[] memory feedIds
) public hasRole(Roles.CUSTOM_ORACLE_EXECUTOR) {
uint256 len = feedIds.length;
Errors.verifyNotZero(len, "len");
BaseOracleDenominations.Denomination[] memory denominations = new BaseOracleDenominations.Denomination[](len);
// Extract and validate the prices from the Redstone payload
(uint256[] memory values, uint256 timestamp) = getOracleNumericValuesAndTimestampFromTxMsg(feedIds);
// Call of RedstoneConsumerBase implementation of validateTimestamp
validateTimestamp(timestamp);
// Prepare the base tokens array
address[] memory baseTokens = new address[](len);
// Prepare the timestamps array and validate prices
uint256[] memory queriedTimestamps = new uint256[](len);
for (uint256 i = 0; i < len; ++i) {
// Save token address from the registered mapping
FeedId memory feedId = registeredFeedIds[feedIds[i]];
if (feedId.tokenAddress == address(0)) {
revert TokenNotRegistered(feedIds[i], feedId.tokenAddress);
}
baseTokens[i] = feedId.tokenAddress;
// Validate the price
Errors.verifyNotZero(values[i], "baseToken price");
// Adjust the price to the correct denomination
uint8 feedDecimals = feedId.feedDecimals;
if (feedId.ethQuoted) {
denominations[i] = BaseOracleDenominations.Denomination.ETH;
values[i] = _adjustDecimals(values[i], 18, feedDecimals);
} else {
denominations[i] = BaseOracleDenominations.Denomination.USD;
values[i] = _adjustDecimals(values[i], 8, feedDecimals);
}
// Set the same timestamp from the Redstone payload for all base tokens
queriedTimestamps[i] = timestamp / 1000; // adapted to seconds
// Redstone allows, but validates are within tolerance, future timestamps.
// We'll allow them as well, their validity will just be slightly shortened
// slither-disable-next-line timestamp
if (queriedTimestamps[i] > block.timestamp) {
queriedTimestamps[i] = block.timestamp;
}
}
// Set the price in the custom oracle
customOracle.setPrices(baseTokens, values, queriedTimestamps, denominations);
}
///@dev This is a default implementation as referenced in the RedstoneConsumerNumericMock contract
function getUniqueSignersThreshold() public view virtual override returns (uint8) {
return uniqueSignersThreshold;
}
/// @notice Sets the unique signers threshold
/// @param _uniqueSignersThreshold The unique signers threshold to set
function setUniqueSignersThreshold(
uint8 _uniqueSignersThreshold
) external hasRole(Roles.ORACLE_MANAGER) {
uniqueSignersThreshold = _uniqueSignersThreshold;
}
/// @notice Registers a mapping between a Redstone feedId and token address
/// @param feedId The Redstone feedId to register
/// @param tokenAddress The token address to map to
function registerFeedId(
bytes32 feedId,
address tokenAddress,
bool ethQuoted,
uint8 feedDecimals
) external hasRole(Roles.ORACLE_MANAGER) {
Errors.verifyNotZero(feedId, "feedId");
Errors.verifyNotZero(address(tokenAddress), "tokenAddress");
registeredFeedIds[feedId] = FeedId(tokenAddress, ethQuoted, feedDecimals);
emit FeedIdRegistered(feedId, tokenAddress, ethQuoted, feedDecimals);
}
/// @notice Removes a mapping between a Redstone feedId and token address
/// @param feedId The Redstone feedId to remove mapping for
function removeFeedId(
bytes32 feedId
) external hasRole(Roles.ORACLE_MANAGER) {
delete registeredFeedIds[feedId];
emit FeedIdRemoved(feedId);
}
/// @notice Registers authorized signers overriding the existing ones
/// @param signerAddresses The signers to register
function registerAuthorizedSigners(
address[] memory signerAddresses
) public hasRole(Roles.ORACLE_MANAGER) {
// Clear the existing authorized signers
uint256 len = _authorizedSigners.length;
for (uint256 i = 0; i < len; ++i) {
//slither-disable-next-line costly-loop
delete signerAddressToIndex[_authorizedSigners[i]];
}
// Register the new authorized signers
_initializeSignerAddressToIndex(signerAddresses);
}
/// @notice Returns the index of an authorized signer
/// @param signerAddress The signer address to get the index for
/// @return The index of the signer
function getAuthorisedSignerIndex(
address signerAddress
) public view virtual override returns (uint8) {
uint8 signerIndex = signerAddressToIndex[signerAddress];
if (signerIndex == 0) {
revert SignerNotAuthorised(signerAddress);
}
return signerIndex - 1; // We subtract 1 to avoid 0 index as a flag
}
function _initializeSignerAddressToIndex(
address[] memory signerAddresses
) private {
for (uint256 i = 0; i < signerAddresses.length; ++i) {
address signerAddress = signerAddresses[i];
Errors.verifyNotZero(signerAddress, "signerAddress");
// We save the index + 1 to avoid 0 index
// as it is used as a flag to check if the signer is authorized in getter function
signerAddressToIndex[signerAddress] = uint8(i + 1);
}
// Set the new authorized signers array
_authorizedSigners = signerAddresses;
}
function _adjustDecimals(
uint256 price,
uint8 targetDecimals,
uint8 currentDecimals
) internal pure returns (uint256 adjustedPrice) {
adjustedPrice = price;
if (currentDecimals < targetDecimals) {
adjustedPrice = price * 10 ** (targetDecimals - currentDecimals);
} else if (currentDecimals > targetDecimals) {
adjustedPrice = price / 10 ** (currentDecimals - targetDecimals);
}
}
}
"
},
"lib/redstone-evm-connector/packages/evm-connector/contracts/data-services/PrimaryProdDataServiceConsumerBase.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
import "../core/RedstoneConsumerNumericBase.sol";
contract PrimaryProdDataServiceConsumerBase is RedstoneConsumerNumericBase {
function getDataServiceId() public view virtual override returns (string memory) {
return "redstone-primary-prod";
}
function getUniqueSignersThreshold() public view virtual override returns (uint8) {
return 3;
}
function getAuthorisedSignerIndex(
address signerAddress
) public view virtual override returns (uint8) {
if (signerAddress == 0x8BB8F32Df04c8b654987DAaeD53D6B6091e3B774) {
return 0;
} else if (signerAddress == 0xdEB22f54738d54976C4c0fe5ce6d408E40d88499) {
return 1;
} else if (signerAddress == 0x51Ce04Be4b3E32572C4Ec9135221d0691Ba7d202) {
return 2;
} else if (signerAddress == 0xDD682daEC5A90dD295d14DA4b0bec9281017b5bE) {
return 3;
} else if (signerAddress == 0x9c5AE89C4Af6aA32cE58588DBaF90d18a855B6de) {
return 4;
} else {
revert SignerNotAuthorised(signerAddress);
}
}
}
"
},
"src/SystemComponent.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { ISystemComponent } from "src/interfaces/ISystemComponent.sol";
import { ISystemRegistry } from "src/interfaces/ISystemRegistry.sol";
import { Errors } from "src/utils/Errors.sol";
contract SystemComponent is ISystemComponent {
ISystemRegistry internal immutable systemRegistry;
constructor(
ISystemRegistry _systemRegistry
) {
Errors.verifyNotZero(address(_systemRegistry), "_systemRegistry");
systemRegistry = _systemRegistry;
}
/// @inheritdoc ISystemComponent
function getSystemRegistry() external view returns (address) {
return address(systemRegistry);
}
}
"
},
"src/security/SecurityBase.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IAccessController } from "src/interfaces/security/IAccessController.sol";
import { Errors } from "src/utils/Errors.sol";
contract SecurityBase {
IAccessController public immutable accessController;
error UndefinedAddress();
constructor(
address _accessController
) {
if (_accessController == address(0)) revert UndefinedAddress();
accessController = IAccessController(_accessController);
}
modifier onlyOwner() {
accessController.verifyOwner(msg.sender);
_;
}
modifier hasRole(
bytes32 role
) {
if (!accessController.hasRole(role, msg.sender)) revert Errors.AccessDenied();
_;
}
///////////////////////////////////////////////////////////////////
//
// Forward all the regular methods to central security module
//
///////////////////////////////////////////////////////////////////
function _hasRole(bytes32 role, address account) internal view returns (bool) {
return accessController.hasRole(role, account);
}
}
"
},
"src/interfaces/ISystemRegistry.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IWETH9 } from "src/interfaces/utils/IWETH9.sol";
import { IAccToke } from "src/interfaces/staking/IAccToke.sol";
import { IAutopoolRegistry } from "src/interfaces/vault/IAutopoolRegistry.sol";
import { IAccessController } from "src/interfaces/security/IAccessController.sol";
import { ISwapRouter } from "src/interfaces/swapper/ISwapRouter.sol";
import { ICurveResolver } from "src/interfaces/utils/ICurveResolver.sol";
import { IAutopilotRouter } from "src/interfaces/vault/IAutopilotRouter.sol";
import { IAutopoolFactory } from "src/interfaces/vault/IAutopoolFactory.sol";
import { ISystemSecurity } from "src/interfaces/security/ISystemSecurity.sol";
import { IDestinationRegistry } from "src/interfaces/destinations/IDestinationRegistry.sol";
import { IRootPriceOracle } from "src/interfaces/oracles/IRootPriceOracle.sol";
import { IDestinationVaultRegistry } from "src/interfaces/vault/IDestinationVaultRegistry.sol";
import { IAccessController } from "src/interfaces/security/IAccessController.sol";
import { IStatsCalculatorRegistry } from "src/interfaces/stats/IStatsCalculatorRegistry.sol";
import { IAsyncSwapperRegistry } from "src/interfaces/liquidation/IAsyncSwapperRegistry.sol";
import { IERC20Metadata } from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { IIncentivesPricingStats } from "src/interfaces/stats/IIncentivesPricingStats.sol";
import { IMessageProxy } from "src/interfaces/messageProxy/IMessageProxy.sol";
/// @notice Root most registry contract for the system
interface ISystemRegistry {
/// @notice Get the TOKE contract for the system
/// @return toke instance of TOKE used in the system
function toke() external view returns (IERC20Metadata);
/// @notice Get the referenced WETH contract for the system
/// @return weth contract pointer
function weth() external view returns (IWETH9);
/// @notice Get the AccToke staking contract
/// @return accToke instance of the accToke contract for the system
function accToke() external view returns (IAccToke);
/// @notice Get the AutopoolRegistry for this system
/// @return registry instance of the registry for this system
function autoPoolRegistry() external view returns (IAutopoolRegistry registry);
/// @notice Get the destination Vault registry for this system
/// @return registry instance of the registry for this system
function destinationVaultRegistry() external view returns (IDestinationVaultRegistry registry);
/// @notice Get the access Controller for this system
/// @return controller instance of the access controller for this system
function accessController() external view returns (IAccessController controller);
/// @notice Get the destination template registry for this system
/// @return registry instance of the registry for this system
function destinationTemplateRegistry() external view returns (IDestinationRegistry registry);
/// @notice Auto Pilot Router
/// @return router instance of the system
function autoPoolRouter() external view returns (IAutopilotRouter router);
/// @notice Vault factory lookup by type
/// @return vaultFactory instance of the vault factory for this vault type
function getAutopoolFactoryByType(
bytes32 vaultType
) external view returns (IAutopoolFactory vaultFactory);
/// @notice Get the stats calculator registry for this system
/// @return registry instance of the registry for this system
function statsCalculatorRegistry() external view returns (IStatsCalculatorRegistry registry);
/// @notice Get the root price oracle for this system
/// @return oracle instance of the root price oracle for this system
function rootPriceOracle() external view returns (IRootPriceOracle oracle);
/// @notice Get the async swapper registry for this system
/// @return registry instance of the registry for this system
function asyncSwapperRegistry() external view returns (IAsyncSwapperRegistry registry);
/// @notice Get the swap router for this system
/// @return router instance of the swap router for this system
function swapRouter() external view returns (ISwapRouter router);
/// @notice Get the curve resolver for this system
/// @return resolver instance of the curve resolver for this system
function curveResolver() external view returns (ICurveResolver resolver);
/// @notice Verify if given address is registered as Reward Token
/// @param rewardToken token address to verify
/// @return bool that indicates true if token is registered and false if not
function isRewardToken(
address rewardToken
) external view returns (bool);
/// @notice Get the system security instance for this system
/// @return security instance of system security for this system
function systemSecurity() external view returns (ISystemSecurity security);
/// @notice Get the Incentive Pricing Stats
/// @return incentivePricing the incentive pricing contract
function incentivePricing() external view returns (IIncentivesPricingStats);
/// @notice Get the Message Proxy
/// @return Message proxy contract
function messageProxy() external view returns (IMessageProxy);
/// @notice Get the receiving router contract.
/// @return Receiving router contract
function receivingRouter() external view returns (address);
/// @notice Check if an additional contract of type is valid in the system
/// @return True if the contract is a valid for the given type
function isValidContract(bytes32 contractType, address contractAddress) external view returns (bool);
/// @notice Returns the additional contract of the given type
/// @dev Revert if not set
function getUniqueContract(
bytes32 contractType
) external view returns (address);
/// @notice Returns all unique contracts configured
function listUniqueContracts() external view returns (bytes32[] memory contractTypes, address[] memory addresses);
/// @notice Returns all additional contract types configured
function listAdditionalContractTypes() external view returns (bytes32[] memory);
/// @notice Returns configured additional contracts by type
/// @param contractType Type of contract to list
function listAdditionalContracts(
bytes32 contractType
) external view returns (address[] memory);
}
"
},
"src/interfaces/ISystemComponent.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
/// @notice Stores a reference to the registry for this system
interface ISystemComponent {
/// @notice The system instance this contract is tied to
function getSystemRegistry() external view returns (address registry);
}
"
},
"src/interfaces/oracles/ICustomSetOracle.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { BaseOracleDenominations } from "src/oracles/providers/base/BaseOracleDenominations.sol";
/// @notice Interface for a deployed CustomSetOracle to access its functions and state variables
interface ICustomSetOracle {
/// @notice Struct to hold the price, max age, and timestamp of a token in the prices mapping
struct Price {
uint184 price;
uint32 maxAge;
uint32 timestamp;
BaseOracleDenominations.Denomination denom;
}
/// STATE VARIABLES
/// @notice Maximum age a price can be from when it was originally queried
function maxAge() external view returns (uint256);
/// @notice All current prices for registered tokens
function prices(
address token
)
external
view
returns (uint184 price, uint32 priceMaxAge, uint32 timestamp, BaseOracleDenominations.Denomination denom);
/// FUNCTIONS
/// @notice Register tokens that should be resolvable through this oracle
/// @param tokens addresses of tokens to register
/// @param maxAges the max allowed age of a tokens price before it will revert on retrieval
function registerTokens(address[] memory tokens, uint256[] memory maxAges) external;
/// @notice Update the price of one or more registered tokens
/// @param tokens address of the tokens price we are setting
/// @param updatePrices prices of the tokens we're setting
/// @param queriedTimestamps the timestamps of when each price was queried
/// @param denominations the denominations of the prices (ETH, USD, etc.)
function setPrices(
address[] memory tokens,
uint256[] memory updatePrices,
uint256[] memory queriedTimestamps,
BaseOracleDenominations.Denomination[] memory denominations
) external;
/// @notice Returns true for a token that is registered with this oracle
/// @param token address to check
function isRegistered(
address token
) external view returns (bool);
}
"
},
"src/oracles/providers/base/BaseOracleDenominations.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IPriceOracle } from "src/interfaces/oracles/IPriceOracle.sol";
import { Errors } from "src/utils/Errors.sol";
import { ISystemRegistry } from "src/interfaces/ISystemRegistry.sol";
import { SecurityBase } from "src/security/SecurityBase.sol";
import { SystemComponent } from "src/SystemComponent.sol";
/// @title Base functionalities for Chainlink and Tellor Oracle contracts.
abstract contract BaseOracleDenominations is SystemComponent, IPriceOracle, SecurityBase {
/// @notice Used to denote what denomination a token is in.
enum Denomination {
ETH,
USD
}
/// @notice Amount of time that can pass until a price is considered stale.
uint256 public constant DEFAULT_PRICING_TIMEOUT = 2 hours;
/**
* @dev Address for unique use case where asset does not have price feed with ETh as
* quote asset. This address must be registered with the Chainlink oracle contract
* using the ETH / USD feed for the corresponding chain.
*/
address public constant ETH_IN_USD = address(bytes20("ETH_IN_USD"));
constructor(
ISystemRegistry _systemRegistry
) SystemComponent(_systemRegistry) SecurityBase(address(_systemRegistry.accessController())) {
Errors.verifyNotZero(address(_systemRegistry.rootPriceOracle()), "rootPriceOracle");
}
// Handles non-Eth denomination if necessary.
function _denominationPricing(
Denomination denomination,
uint256 normalizedPrice,
address tokenToPrice
) internal returns (uint256) {
if (tokenToPrice != ETH_IN_USD && denomination == Denomination.USD) {
return _getPriceDenominationUSD(normalizedPrice);
}
return normalizedPrice;
}
/**
* @notice Necessary due to of USD / Eth price feed. Price of both assets in USD make it possible
* to get `normalizedPrice` in terms of Eth. Many assets are priced in USD as opposed to Eth
* on Chainlink price feeds.
*
* @param normalizedPrice Normalized price of asset in USD
*/
function _getPriceDenominationUSD(
uint256 normalizedPrice
) private returns (uint256) {
uint256 ethInUsd = systemRegistry.rootPriceOracle().getPriceInEth(ETH_IN_USD);
return (normalizedPrice * (10 ** 18) / ethInUsd);
}
}
"
},
"src/utils/Errors.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { Address } from "openzeppelin-contracts/utils/Address.sol";
import { ISystemComponent } from "src/interfaces/ISystemComponent.sol";
// solhint-disable max-line-length
library Errors {
using Address for address;
///////////////////////////////////////////////////////////////////
// Set errors
///////////////////////////////////////////////////////////////////
error AccessDenied();
error ZeroAddress(string paramName);
error ZeroAmount();
error InsufficientBalance(address token);
error AssetNotAllowed(address token);
error NotImplemented();
error InvalidAddress(address addr);
error InvalidParam(string paramName);
error InvalidParams();
error Exception(string desc);
error UnsafePrice(address token, uint256 spotPrice, uint256 safePrice);
error AlreadySet(string param);
error AlreadyRegistered(address param);
error SlippageExceeded(uint256 expected, uint256 actual);
error ArrayLengthMismatch(uint256 length1, uint256 length2, string details);
error ItemNotFound();
error ItemExists();
error MissingRole(bytes32 role, address user);
error RegistryItemMissing(string item);
error NotRegistered();
// Used to check storage slot is empty before setting.
error MustBeZero();
// Used to check storage slot set before deleting.
error MustBeSet();
error ApprovalFailed(address token);
error FlashLoanFailed(address token, uint256 amount);
error SystemMismatch(address source1, address source2);
error InvalidToken(address token);
error UnreachableError();
error InvalidSigner(address signer);
error InvalidChainId(uint256 chainId);
error SenderMismatch(address recipient, address sender);
error UnsupportedMessage(bytes32 messageType, bytes message);
error NotSupported();
error InvalidConfiguration();
error InvalidDataReturned();
function verifyNotZero(address addr, string memory paramName) internal pure {
if (addr == address(0)) {
revert ZeroAddress(paramName);
}
}
function verifyNotZero(bytes32 key, string memory paramName) internal pure {
if (key == bytes32(0)) {
revert InvalidParam(paramName);
}
}
function verifyNotEmpty(string memory val, string memory paramName) internal pure {
if (bytes(val).length == 0) {
revert InvalidParam(paramName);
}
}
function verifyNotZero(uint256 num, string memory paramName) internal pure {
if (num == 0) {
revert InvalidParam(paramName);
}
}
function verifySystemsMatch(address component1, address component2) internal view {
address registry1 =
abi.decode(component1.functionStaticCall(abi.encodeCall(ISystemComponent.getSystemRegistry, ())), (address));
address registry2 =
abi.decode(component2.functionStaticCall(abi.encodeCall(ISystemComponent.getSystemRegistry, ())), (address));
if (registry1 != registry2) {
revert SystemMismatch(component1, component2);
}
}
function verifyArrayLengths(uint256 length1, uint256 length2, string memory details) internal pure {
if (length1 != length2) {
revert ArrayLengthMismatch(length1, length2, details);
}
}
}
"
},
"src/libs/Roles.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
library Roles {
// Naming Conventions:
// - Use MANAGER, CREATOR, UPDATER, ..., for roles primarily managing on-chain activities.
// - Use EXECUTOR for roles that trigger off-chain initiated actions.
// - Group roles by functional area for clarity.
// Destination Vault Management
bytes32 public constant DESTINATION_VAULT_FACTORY_MANAGER = keccak256("CREATE_DESTINATION_VAULT_ROLE");
bytes32 public constant DESTINATION_VAULT_REGISTRY_MANAGER = keccak256("DESTINATION_VAULT_REGISTRY_MANAGER");
bytes32 public constant DESTINATION_VAULT_MANAGER = keccak256("DESTINATION_VAULT_MANAGER");
bytes32 public constant DESTINATION_VAULT_REWARD_MANAGER = keccak256("DESTINATION_VAULT_REWARD_MANAGER");
bytes32 public constant FLUID_DESTINATION_VAULT_MANAGER = keccak256("FLUID_DESTINATION_VAULT_MANAGER");
bytes32 public constant DESTINATION_MERKLE_CLAIM_MANAGER = keccak256("DESTINATION_MERKLE_CLAIM_MANAGER");
bytes32 public constant EULER_REWARD_MANAGER = keccak256("EULER_REWARD_MANAGER");
bytes32 public constant EULER_REWARD_EXECUTOR = keccak256("EULER_REWARD_EXECUTOR");
// Auto Pool Factory and Registry Management
bytes32 public constant AUTO_POOL_REGISTRY_UPDATER = keccak256("REGISTRY_UPDATER");
bytes32 public constant AUTO_POOL_FACTORY_MANAGER = keccak256("AUTO_POOL_FACTORY_MANAGER");
bytes32 public constant AUTO_POOL_FACTORY_VAULT_CREATOR = keccak256("CREATE_POOL_ROLE");
// Auto Pool Management
bytes32 public constant AUTO_POOL_DESTINATION_UPDATER = keccak256("DESTINATION_VAULTS_UPDATER");
bytes32 public constant AUTO_POOL_FEE_UPDATER = keccak256("AUTO_POOL_FEE_SETTER_ROLE");
bytes32 public constant AUTO_POOL_PERIODIC_FEE_UPDATER = keccak256("AUTO_POOL_PERIODIC_FEE_SETTER_ROLE");
bytes32 public constant AUTO_POOL_REWARD_MANAGER = keccak256("AUTO_POOL_REWARD_MANAGER_ROLE");
bytes32 public constant AUTO_POOL_MANAGER = keccak256("AUTO_POOL_ADMIN");
bytes32 public constant REBALANCER = keccak256("REBALANCER_ROLE");
bytes32 public constant STATS_HOOK_POINTS_ADMIN = keccak256("STATS_HOOK_POINTS_ADMIN");
// Reward Management
bytes32 public constant LIQUIDATOR_MANAGER = keccak256("LIQUIDATOR_ROLE");
bytes32 public constant DV_REWARD_MANAGER = keccak256("DV_REWARD_MANAGER_ROLE");
bytes32 public constant REWARD_LIQUIDATION_MANAGER = keccak256("REWARD_LIQUIDATION_MANAGER");
bytes32 public constant EXTRA_REWARD_MANAGER = keccak256("EXTRA_REWARD_MANAGER_ROLE");
bytes32 public constant REWARD_LIQUIDATION_EXECUTOR = keccak256("REWARD_LIQUIDATION_EXECUTOR");
bytes32 public constant BANK_SWAP_MANAGER = keccak256("BANK_SWAP_MANAGER");
// Statistics and Reporting
bytes32 public constant STATS_CALC_REGISTRY_MANAGER = keccak256("STATS_CALC_REGISTRY_MANAGER");
bytes32 public constant STATS_CALC_FACTORY_MANAGER = keccak256("CREATE_STATS_CALC_ROLE");
bytes32 public constant STATS_CALC_FACTORY_TEMPLATE_MANAGER = keccak256("STATS_CALC_TEMPLATE_MGMT_ROLE");
bytes32 public constant STATS_SNAPSHOT_EXECUTOR = keccak256("STATS_SNAPSHOT_ROLE");
bytes32 public constant STATS_INCENTIVE_TOKEN_UPDATER = keccak256("STATS_INCENTIVE_TOKEN_UPDATER");
bytes32 public constant STATS_GENERAL_MANAGER = keccak256("STATS_GENERAL_MANAGER");
bytes32 public constant STATS_LST_ETH_TOKEN_EXECUTOR = keccak256("STATS_LST_ETH_TOKEN_EXECUTOR");
bytes32 public constant STATS_CACHE_SET_TRANSIENT_EXECUTOR = keccak256("STATS_CACHE_SET_TRANSIENT_EXECUTOR");
// Emergency Management
bytes32 public constant EMERGENCY_PAUSER = keccak256("EMERGENCY_PAUSER");
bytes32 public constant SEQUENCER_OVERRIDE_MANAGER = keccak256("SEQUENCER_OVERRIDE_MANAGER");
// Miscellaneous Roles
bytes32 public constant SOLVER = keccak256("SOLVER_ROLE");
bytes32 public constant AUTO_POOL_REPORTING_EXECUTOR = keccak256("AUTO_POOL_UPDATE_DEBT_REPORTING_ROLE");
bytes32 public constant STRATEGY_HOOK_CONFIGURATION = keccak256("STRATEGY_HOOK_CONFIGURATION");
// Swapper Roles
bytes32 public constant SWAP_ROUTER_MANAGER = keccak256("SWAP_ROUTER_MANAGER");
// Price Oracles Roles
bytes32 public constant ORACLE_MANAGER = keccak256("ORACLE_MANAGER_ROLE");
bytes32 public constant CUSTOM_ORACLE_EXECUTOR = keccak256("CUSTOM_ORACLE_EXECUTOR");
bytes32 public constant MAVERICK_FEE_ORACLE_EXECUTOR = keccak256("MAVERICK_FEE_ORACLE_MANAGER");
// AccToke Roles
bytes32 public constant ACC_TOKE_MANAGER = keccak256("ACC_TOKE_MANAGER");
// Admin Roles
bytes32 public constant TOKEN_RECOVERY_MANAGER = keccak256("TOKEN_RECOVERY_ROLE");
bytes32 public constant INFRASTRUCTURE_MANAGER = keccak256("INFRASTRUCTURE_MANAGER");
// Cross chain communications roles
bytes32 public constant MESSAGE_PROXY_MANAGER = keccak256("MESSAGE_PROXY_MANAGER");
bytes32 public constant MESSAGE_PROXY_EXECUTOR = keccak256("MESSAGE_PROXY_EXECUTOR");
bytes32 public constant RECEIVING_ROUTER_MANAGER = keccak256("RECEIVING_ROUTER_MANAGER");
bytes32 public constant RECEIVING_ROUTER_EXECUTOR = keccak256("RECEIVING_ROUTER_EXECUTOR");
// Backing Oracle
bytes32 public constant BACKING_ORACLE_MANAGER = keccak256("BACKING_ORACLE_MANAGER");
// Silo Vault Reward Manager
bytes32 public constant DESTINATION_VAULT_SILO_MANAGER = keccak256("DESTINATION_VAULT_SILO_MANAGER");
}
"
},
"lib/redstone-evm-connector/packages/evm-connector/contracts/core/RedstoneConsumerNumericBase.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
import "./RedstoneConsumerBase.sol";
/**
* @title The base contract for Redstone consumers' contracts that allows to
* securely calculate numeric redstone oracle values
* @author The Redstone Oracles team
* @dev This contract can extend other contracts to allow them
* securely fetch Redstone oracle data from transactions calldata
*/
abstract contract RedstoneConsumerNumericBase is RedstoneConsumerBase {
/**
* @dev This function can be used in a consumer contract to securely extract an
* oracle value for a given data feed id. Security is achieved by
* signatures verification, timestamp validation, and aggregating values
* from different authorised signers into a single numeric value. If any of the
* required conditions do not match, the function will revert.
* Note! This function expects that tx calldata contains redstone payload in the end
* Learn more about redstone payload here: https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/evm-connector#readme
* @param dataFeedId bytes32 value that uniquely identifies the data feed
* @return Extracted and verified numeric oracle value for the given data feed id
*/
function getOracleNumericValueFromTxMsg(bytes32 dataFeedId)
internal
view
virtual
returns (uint256)
{
bytes32[] memory dataFeedIds = new bytes32[](1);
dataFeedIds[0] = dataFeedId;
return getOracleNumericValuesFromTxMsg(dataFeedIds)[0];
}
/**
* @dev This function can be used in a consumer contract to securely extract several
* numeric oracle values for a given array of data feed ids. Security is achieved by
* signatures verification, timestamp validation, and aggregating values
* from different authorised signers into a single numeric value. If any of the
* required conditions do not match, the function will revert.
* Note! This function expects that tx calldata contains redstone payload in the end
* Learn more about redstone payload here: https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/evm-connector#readme
* @param dataFeedIds An array of unique data feed identifiers
* @return An array of the extracted and verified oracle values in the same order
* as they are requested in the dataFeedIds array
*/
function getOracleNumericValuesFromTxMsg(bytes32[] memory dataFeedIds)
internal
view
virtual
returns (uint256[] memory)
{
(uint256[] memory values, uint256 timestamp) = _securelyExtractOracleValuesAndTimestampFromTxMsg(dataFeedIds);
validateTimestamp(timestamp);
return values;
}
/**
* @dev This function can be used in a consumer contract to securely extract several
* numeric oracle values for a given array of data feed ids. Security is achieved by
* signatures verification and aggregating values from different authorised signers
* into a single numeric value. If any of the required conditions do not match,
* the function will revert.
* Note! This function returns the timestamp of the packages (it requires it to be
* the same for all), but does not validate this timestamp.
* Note! This function expects that tx calldata contains redstone payload in the end
* Learn more about redstone payload here: https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/evm-connector#readme
* @param dataFeedIds An array of unique data feed identifiers
* @return An array of the extracted and verified oracle values in the same order
* as they are requested in the dataFeedIds array and data packages timestamp
*/
function getOracleNumericValuesAndTimestampFromTxMsg(bytes32[] memory dataFeedIds)
internal
view
virtual
returns (uint256[] memory, uint256)
{
return _securelyExtractOracleValuesAndTimestampFromTxMsg(dataFeedIds);
}
/**
* @dev This function works similarly to the `getOracleNumericValuesFromTxMsg` with the
* only difference that it allows to request oracle data for an array of data feeds
* that may contain duplicates
*
* @param dataFeedIdsWithDuplicates An array of data feed identifiers (duplicates are allowed)
* @return An array of the extracted and verified oracle values in the same order
* as they are requested in the dataFeedIdsWithDuplicates array
*/
function getOracleNumericValuesWithDuplicatesFromTxMsg(bytes32[] memory dataFeedIdsWithDuplicates) internal view returns (uint256[] memory) {
// Building an array without duplicates
bytes32[] memory dataFeedIdsWithoutDuplicates = new bytes32[](dataFeedIdsWithDuplicates.length);
bool alreadyIncluded;
uint256 uniqueDataFeedIdsCount = 0;
for (uint256 indexWithDup = 0; indexWithDup < dataFeedIdsWithDuplicates.length; indexWithDup++) {
// Checking if current element is already included in `dataFeedIdsWithoutDuplicates`
alreadyIncluded = false;
for (uint256 indexWithoutDup = 0; indexWithoutDup < uniqueDataFeedIdsCount; indexWithoutDup++) {
if (dataFeedIdsWithoutDuplicates[indexWithoutDup] == dataFeedIdsWithDuplicates[indexWithDup]) {
alreadyIncluded = true;
break;
}
}
// Adding if not included
if (!alreadyIncluded) {
dataFeedIdsWithoutDuplicates[uniqueDataFeedIdsCount] = dataFeedIdsWithDuplicates[indexWithDup];
uniqueDataFeedIdsCount++;
}
}
// Overriding dataFeedIdsWithoutDuplicates.length
// Equivalent to: dataFeedIdsWithoutDuplicates.length = uniqueDataFeedIdsCount;
assembly {
mstore(dataFeedIdsWithoutDuplicates, uniqueDataFeedIdsCount)
}
// Requesting oracle values (without duplicates)
(uint256[] memory valuesWithoutDuplicates, uint256 timestamp) = _securelyExtractOracleValuesAndTimestampFromTxMsg(dataFeedIdsWithoutDuplicates);
validateTimestamp(timestamp);
// Preparing result values array
uint256[] memory valuesWithDuplicates = new uint256[](dataFeedIdsWithDuplicates.length);
for (uint256 indexWithDup = 0; indexWithDup < dataFeedIdsWithDuplicates.length; indexWithDup++) {
for (uint256 indexWithoutDup = 0; indexWithoutDup < dataFeedIdsWithoutDuplicates.length; indexWithoutDup++) {
if (dataFeedIdsWithDuplicates[indexWithDup] == dataFeedIdsWithoutDuplicates[indexWithoutDup]) {
valuesWithDuplicates[indexWithDup] = valuesWithoutDuplicates[indexWithoutDup];
break;
}
}
}
return valuesWithDuplicates;
}
}
"
},
"src/interfaces/security/IAccessController.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IAccessControlEnumerable } from "openzeppelin-contracts/access/IAccessControlEnumerable.sol";
interface IAccessController is IAccessControlEnumerable {
error AccessDenied();
/**
* @notice Setup a role for an account
* @param role The role to setup
* @param account The account to setup the role for
*/
function setupRole(bytes32 role, address account) external;
/**
* @notice Verify if an account is an owner. Reverts if not
* @param account The account to verify
*/
function verifyOwner(
address account
) external view;
}
"
},
"src/interfaces/utils/IWETH9.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol";
interface IWETH9 is IERC20 {
function symbol() external view returns (string memory);
function deposit() external payable;
function withdraw(
uint256 amount
) external;
}
"
},
"src/interfaces/staking/IAccToke.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IERC20Metadata } from "openzeppelin-contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IAccToke {
///////////////////////////////////////////////////////////////////
// Variables
///////////////////////////////////////////////////////////////////
function startEpoch() external view returns (uint256);
function minStakeDuration() external view returns (uint256);
struct Lockup {
uint128 amount;
uint128 end;
uint256 points;
}
function getLockups(
address user
) external view returns (Lockup[] memory);
function toke() external view returns (IERC20Metadata);
///////////////////////////////////////////////////////////////////
// Errors
///////////////////////////////////////////////////////////////////
error ZeroAddress();
error StakingDurationTooShort();
error StakingDurationTooLong();
error StakingPointsExceeded();
error IncorrectStakingAmount();
error InsufficientFunds();
error LockupDoesNotExist();
error NotUnlockableYet();
error AlreadyUnlocked();
error ExtendDurationTooShort();
error TransfersDisabled();
error TransferFailed();
error NoRewardsToClaim();
error InsufficientAmount();
error InvalidLockupIds();
error InvalidDurationLength();
error InvalidMinStakeDuration();
error AdminUnlockActive();
///////////////////////////////////////////////////////////////////
// Events
///////////////////////////////////////////////////////////////////
event SetMaxStakeDuration(uint256 oldDuration, uint256 newDuration);
event Stake(address indexed user, uint256 lockupId, uint256 amount, uint256 end, uint256 points);
event Unstake(address indexed user, uint256 lockupId, uint256 amount, uint256 end, uint256 points);
event Extend(
address indexed user,
uint256 lockupId,
uint256 amount,
uint256 oldEnd,
uint256 newEnd,
uint256 oldPoints,
uint256 newPoints
);
event RewardsAdded(uint256 amount, uint256 accRewardPerShare);
event RewardsCollected(address indexed user, uint256 amount);
event RewardsClaimed(address indexed user, address indexed recipient, uint256 amount);
event AdminUnlockSet(bool newUnlockState);
///////////////////////////////////////////////////////////////////
//
// Staking Methods
//
///////////////////////////////////////////////////////////////////
/**
* @notice Stake TOKE to an address that may not be the same as the sender of the funds. This can be used to give
* staked funds to someone else.
*
* If staking before the start of staking (epoch), then the lockup start and end dates are shifted forward so that
* the lockup starts at the epoch.
*
* @param amount TOKE to lockup in the stake
* @param duration in seconds for the stake
* @param to address to receive ownership of the stake
*/
function stake(uint256 amount, uint256 duration, address to) external;
/**
* @notice Stake TOKE
*
* If staking before the start of staking (epoch), then the lockup start and end dates are shifted forward so that
* the lockup starts at the epoch.
*
* @notice Stake TOKE for myself.
* @param amount TOKE to lockup in the stake
* @param duration in seconds for the stake
*/
function stake(uint256 amount, uint256 duration) external;
/**
* @notice Collect staked TOKE for a lockup and any earned rewards.
* @param lockupIds the id of the lockup to unstake
*/
function unstake(
uint256[] memory lockupIds
) external;
/**
* @notice Collect staked TOKE for a lockup and any earned rewards.
* @param lockupIds the id of the lockup to unstake
* @param user address of the user to unstake for
* @param to address to receive the unstaked TOKE
*/
function unstake(uint256[] memory lockupIds, address user, address to) external;
/**
* @notice Extend a stake lockup for additional points.
*
* The stake end time is computed from the current time + duration, just like it is for new stakes. So a new stake
* for seven days duration and an old stake extended with a seven days duration would have the same end.
*
* If an extend is made before the start of staking, the start time for the new stake is shifted forwards to the
* start of staking, which also shifts forward the end date.
*
* @param lockupIds the id of the old lockup to extend
* @param durations number of seconds from now to stake for
*/
function extend(uint256[] memory lockupIds, uint256[] memory durations) external;
///////////////////////////////////////////////////////////////////
//
// Rewards
//
///////////////////////////////////////////////////////////////////
/// @notice The total amount of rewards earned for all stakes
function totalRewardsEarned() external returns (uint256);
/// @notice Total rewards claimed by all stakers
function totalRewardsClaimed() external returns (uint256);
/// @notice Rewards claimed by a specific wallet
/// @param user Address of the wallet to check
function rewardsClaimed(
address user
) external returns (uint256);
/**
* @notice Calculate points based on duration from the staking system's start epoch to the user's staking end date
*
* @param amount TOKE to be staked
* @param duration number of seconds to stake for
* @return points staking points that would be returned
* @return end staking period end date
*/
function previewPoints(uint256 amount, uint256 duration) external view returns (uint256, uint256);
/// @notice Preview the reward amount a caller can claim
function previewRewards() external view returns (uint256);
/// @notice Preview the reward amount a specified wallet can claim
function previewRewards(
address user
) external view returns (uint256);
/// @notice Claim rewards for the caller
function collectRewards() external returns (uint256);
/// @notice Claim rewards for the user and send to recipient
function collectRewards(address user, address recipient) external returns (uint256);
/// @notice Check if amount can be staked
function isStakeableAmount(
uint256 amount
) external pure returns (bool);
}
"
},
"src/interfaces/vault/IAutopoolRegistry.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
/// @title Keep track of Vaults created through the Vault Factory
interface IAutopoolRegistry {
///////////////////////////////////////////////////////////////////
// Errors
///////////////////////////////////////////////////////////////////
error VaultNotFound(address vaultAddress);
error VaultAlreadyExists(address vaultAddress);
///////////////////////////////////////////////////////////////////
// Events
///////////////////////////////////////////////////////////////////
event VaultAdded(address indexed asset, address indexed vault);
event VaultRemoved(address indexed asset, address indexed vault);
///////////////////////////////////////////////////////////////////
// Functions
///////////////////////////////////////////////////////////////////
/// @notice Checks if an address is a valid vault
/// @param vaultAddress Vault address to be added
function isVault(
address vaultAddress
) external view returns (bool);
/// @notice Registers a vault
/// @param vaultAddress Vault address to be added
function addVault(
address vaultAddress
) external;
/// @notice Removes vault registration
/// @param vaultAddress Vault address to be removed
function removeVault(
address vaultAddress
) external;
/// @notice Returns a list of all registered vaults
function listVaults() external view returns (address[] memory);
/// @notice Returns a list of all registered vaults for a given asset
/// @param asset Asset address
function listVaultsForAsset(
address asset
) external view returns (address[] memory);
/// @notice Returns a list of all registered vaults for a given type
/// @param _vaultType Vault type
function listVaultsForType(
bytes32 _vaultType
) external view returns (address[] memory);
}
"
},
"src/interfaces/swapper/ISwapRouter.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { ISyncSwapper } from "src/interfaces/swapper/ISyncSwapper.sol";
interface ISwapRouter {
struct SwapData {
address token;
address pool;
ISyncSwapper swapper;
bytes data;
}
error MaxSlippageExceeded();
error SwapRouteLookupFailed(address from, address to);
error SwapFailed();
event SwapRouteSet(address indexed token, SwapData[] routes);
event SwapForQuoteSuccessful(
address indexed assetToken,
uint256 sellAmount,
address indexed quoteToken,
uint256 minBuyAmount,
uint256 buyAmount
);
/**
* @notice Sets a new swap route for a given asset token.
* @param assetToken The asset token for which the swap route is being set.
* @param _swapRoute The new swap route as an array of SwapData. The last element represents the quoteToken.
* @dev Each 'hop' in the swap route is validated using the respective swapper's validate function. The validate
* function ensures that the encoded data contains the correct 'fromAddress' and 'toAddress' (swapData.token), and
* verifies that these tokens are in the pool.
*/
function setSwapRoute(address assetToken, SwapData[] calldata _swapRoute) external;
/**
* @notice Swaps the asset token for the quote token.
* @dev We're adopting an "exact in, variable out" model for all our swaps. This ensures that the entire sellAmount
* is used, eliminating the need for additional balance checks and refunds. This model is expected to be followed by
* all swapper implementations to maintain consistency and to optimize for gas efficiency.
* @param assetToken The address of the asset token to swap.
* @param sellAmount The exact amount of the asset token to swap.
* @param quoteToken The address of the quote token.
* @param minBuyAmount The minimum amount of the quote token expected to be received from the swap.
* @return The amount received from the swap.
*/
function swapForQuote(
address assetToken,
uint256 sellAmount,
address quoteToken,
uint256 minBuyAmount
) external returns (uint256);
}
"
},
"src/interfaces/utils/ICurveResolver.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
interface ICurveResolver {
/// @notice Resolve details of a Curve pool regardless of type or version
/// @dev This resolves tokens without unwrapping to underlying in the case of meta pools.
/// @param poolAddress pool address to lookup
/// @return tokens tokens that make up the pool
/// @return numTokens the number of tokens. tokens are not unwrapped.
/// @return isStableSwap is this a StableSwap pool. false = CryptoSwap
function resolve(
address poolAddress
) external view returns (address[8] memory tokens, uint256 numTokens, bool isStableSwap);
/// @notice Resolve details of a Curve pool regardless of type or version
/// @dev This resolves tokens without unwrapping to underlying in the case of meta pools.
/// @dev Use the isStableSwap value to differentiate between StableSwap (V1) and CryptoSwap (V2) pools.
/// @param poolAddress pool address to lookup
/// @return tokens tokens that make up the pool
/// @return numTokens the number of tokens. tokens are not unwrapped
/// @return lpToken lp token of the pool
/// @return isStableSwap is this a StableSwap pool. false = CryptoSwap
function resolveWithLpToken(
address poolAddress
) external view returns (address[8] memory tokens, uint256 numTokens, address lpToken, bool isStableSwap);
/// @notice Get the lp token of a Curve pool
/// @param poolAddress pool address to lookup
function getLpToken(
address poolAddress
) external view returns (address);
/// @notice Get the reserves of a Curve pools' tokens
/// @dev Actual balances length might differ from 8 and should be verified by the caller
/// @param poolAddress pool address to lookup
/// @return balances reserves of the pool tokens
function getReservesInfo(
address poolAddress
) external view returns (uint256[8] memory balances);
}
"
},
"src/interfaces/vault/IAutopilotRouter.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IAutopool } from "src/interfaces/vault/IAutopool.sol";
import { IAutopilotRouterBase } from "src/interfaces/vault/IAutopilotRouterBase.sol";
import { IRewards } from "src/interfaces/rewarders/IRewards.sol";
import { SwapParams } from "src/interfaces/liquidation/IAsyncSwapper.sol";
import { ISwapRouterV2 } from "src/interfaces/swapper/ISwapRouterV2.sol";
/**
* @title IAutopilotRouter Interface
* @notice Extends the IAutopilotRouterBase with specific flows to save gas
*/
interface IAutopilotRouter is IAutopilotRouterBase {
error PreviewRedeemWithRoutesResult(uint256);
/**
* *************************** Deposit ********************************
*/
/**
* @notice deposit available asset balance to a AutopoolETH.
* @param vault The AutopoolETH to deposit assets to.
* @param to The destination of ownership shares.
* @param minSharesOut The min amount of `vault` shares received by `to`.
* @return sharesOut the amount of shares received by `to`.
* @dev throws MinSharesError
*/
function depositBalance(
IAutopool vault,
address to,
uint256 minSharesOut
) external payable returns (uint256 sharesOut);
/**
* @notice deposit max assets to a AutopoolETH.
* @param vault The AutopoolETH to deposit assets to.
* @param to The destination of ownership shares.
* @param minSharesOut The min amount of `vault` shares received by `to`.
* @return sharesOut the amount of shares received by `to`.
* @dev throws MinSharesError
*/
function depositMax(
IAutopool vault,
address to,
uint256 minSharesOut
) external payable returns (uint256 sharesOut);
/**
* ************************* Withdraw **********************************
*/
/**
* @notice withdraw `amount` to a AutopoolETH.
* @param fromVault The AutopoolETH to withdraw assets from.
* @param toVault The AutopoolETH to deposit assets to.
* @param to The destination of ownership shares.
* @param amount The amount of assets to withdraw from fromVault.
* @param maxSharesIn The max amount of fromVault shares withdrawn by caller.
* @param minSharesOut The min amount of toVault shares received by `to`.
* @return sharesOut the amount of shares received by `to`.
* @dev throws MaxSharesError, MinSharesError
*/
function withdrawToDeposit(
IAutopool fromVault,
IAutopool toVault,
address to,
uint256 amount,
uint256 maxSharesIn,
uint256 minSharesOut
) external payable returns (uint256 sharesOut);
/**
* ************************* Redeem ********************************
*/
/**
* @notice redeem `shares` to a AutopoolETH.
* @param fromVault The AutopoolETH to redeem shares from.
* @param toVault The AutopoolETH to deposit assets to.
* @param to The destination of ownership shares.
* @param shares The amount of shares to redeem from fromVault.
* @param minSharesOut The min amount of toVault shares received by `to`.
* @return sharesOut the amount of shares received by `to`.
* @dev throws MinAmountError, MinSharesError
*/
function redeemToDeposit(
IAutopool fromVault,
IAutopool toVault,
address to,
uint256 shares,
uint256 minSharesOut
) external payable returns (uint256 sharesOut);
/**
* @notice redeem max shares to a AutopoolETH.
* @param vault The AutopoolETH to redeem shares from.
* @param to The destination of assets.
* @param minAmountOut The min amount of assets received by `to`.
* @return amountOut the amount of assets received by `to`.
* @dev throws MinAmountError
*/
function redeemMax(
IAutopool vault,
address to,
uint256 minAmountOut
) external payable returns (uint256 amountOut);
/**
* @notice previewRedeem `shares` shares from a AutopoolETH with a custom route
* @param vault The AutopoolETH to redeem shares from.
* @param shares The amount of shares to redeem from vault.
* @param customRoute The custom route to use for the swap.
* @dev throws PreviewRedeemWithRoutesResult on all executions
*/
function previewRedeemWithRoutes(
IAutopool vault,
uint256 shares,
ISwapRouterV2.UserSwapData[] calldata customRoute
) external payable;
/**
* @notice redeem `shares` shares from a AutopoolETH with a custom route
* @param vault The AutopoolETH to redeem shares from.
* @param to The destination of assets.
* @param shares The amount of shares to redeem from vault.
* @param minAmountOut The min amount of assets received by `to`.
* @param customRoute The custom route to use for the swap.
* @return amountOut the amount of assets received by `to`.
* @dev throws MinAmountError
*/
function redeemWithRoutes(
IAutopool vault,
address to,
uint256 shares,
uint256 minAmountOut,
ISwapRouterV2.UserSwapData[] calldata customRoute
) external payable returns (uint256 amountOut);
/**
* @notice swaps token
* @param swapper Address of the swapper to use
* @param swapParams Parameters for the swap
* @return amountReceived Swap output amount
*/
function swapToken(
address swapper,
SwapParams memory swapParams
) external payable returns (uint256 amountReceived);
/**
* @notice claims vault token rewards
* @param rewarder Address of the rewarder to claim from
* @param recipient Struct containing recipient details
* @return amountReceived Swap output amount
*/
function claimRewards(
IRewards rewarder,
IRewards.Recipient calldata recipient,
uint8 v,
bytes32 r,
bytes32 s
) external payable returns (uint256);
/**
* @notice swaps Exact token balance in the contract
* @param swapper Address of the swapper to use
* @param swapParams Parameters for the swap
* @return amountReceived Swap output amount
* @dev sets the sellAmount to the balance of the contract
*/
function swapTokenBalance(
address swapper,
SwapParams memory swapParams
) external payable returns (uint256 amountReceived);
/**
* @notice stake Acc token balance
* @param duration The duration of the stake
* @param accToke contract address of the AccToke
* @param to The destination of ownership shares.
*/
function stakeAccBalance(address accToke, uint256 duration, address to) external payable;
/**
* @notice stake Acc token for specified amount
* @param amount Amount of TOKE to stake
* @param accToke contract address of the AccToke
* @param duration The duration of the stake
* @param to The destination of ownership shares.
*/
function stakeAcc(address accToke, uint256 amount, uint256 duration, address to) external payable;
/**
* @notice unstake Acc token balance
* @param accToke contract address of the AccToke
* @param lockupIds The lockup ids to unstake
* @param to The destination of staked TOKE.
*/
function unstakeAcc(address accToke, uint256[] memory lockupIds, address to) external payable;
/**
* @notice Collect staking rewards
* @dev rewards can only be sent to user or router
* @param accToke contract address of the AccToke
* @param recipient The recipient of the rewards
* @return amountReceived Swap output amount
*/
function collectAccTokeRewards(address accToke, address recipient) external payable returns (uint256);
/**
* @notice AccTokeV1 function to lock TOKE for `numOfCycles` cycles
* @param amou
Submitted on: 2025-10-12 11:18:03
Comments
Log in to comment.
No comments yet.