Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Swap Exact Input | 19582703 | 706 days ago | IN | 0 ETH | 0.01719036 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Rebalancer
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.19;
import { IERC20 } from "oz/interfaces/IERC20.sol";
import { IERC20Metadata } from "oz/interfaces/IERC20Metadata.sol";
import { SafeERC20 } from "oz/token/ERC20/utils/SafeERC20.sol";
import { SafeCast } from "oz/utils/math/SafeCast.sol";
import { ITransmuter } from "interfaces/ITransmuter.sol";
import { Order, IRebalancer } from "interfaces/IRebalancer.sol";
import { AccessControl, IAccessControlManager } from "../utils/AccessControl.sol";
import "../utils/Constants.sol";
import "../utils/Errors.sol";
/// @title Rebalancer
/// @author Angle Labs, Inc.
/// @notice Contract built to subsidize rebalances between collateral tokens
/// @dev This contract is meant to "wrap" the Transmuter contract and provide a way for governance to
/// subsidize rebalances between collateral tokens. Rebalances are done through 2 swaps collateral <> agToken.
/// @dev This contract is not meant to hold any transient funds aside from the rebalancing budget
contract Rebalancer is IRebalancer, AccessControl {
event OrderSet(address indexed tokenIn, address indexed tokenOut, uint256 subsidyBudget, uint256 guaranteedRate);
event SubsidyPaid(address indexed tokenIn, address indexed tokenOut, uint256 subsidy);
using SafeERC20 for IERC20;
using SafeCast for uint256;
/// @notice Reference to the `transmuter` implementation this contract aims at rebalancing
ITransmuter public immutable TRANSMUTER;
/// @notice AgToken handled by the `transmuter` of interest
address public immutable AGTOKEN;
/// @notice Maps a `(tokenIn,tokenOut)` pair to details about the subsidy potentially provided on
/// `tokenIn` to `tokenOut` rebalances
mapping(address tokenIn => mapping(address tokenOut => Order)) public orders;
/// @notice Gives the total subsidy budget
uint256 public budget;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @notice Initializes the immutable variables of the contract: `accessControlManager`, `transmuter` and `agToken`
constructor(IAccessControlManager _accessControlManager, ITransmuter _transmuter) {
if (address(_accessControlManager) == address(0)) revert ZeroAddress();
accessControlManager = _accessControlManager;
TRANSMUTER = _transmuter;
AGTOKEN = address(_transmuter.agToken());
}
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
REBALANCING FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @inheritdoc IRebalancer
/// @dev Contrarily to what is done in the Transmuter contract, here neither of `tokenIn` or `tokenOut`
/// should be an `agToken`
/// @dev Can be used even if the subsidy budget is 0, in which case it'll just do 2 Transmuter swaps
/// @dev The invariant should be that `msg.sender` injects `amountIn` in the transmuter and either the
/// subsidy is 0 either they receive a subsidy from this contract on top of the output Transmuter up to
/// the guaranteed amount out
function swapExactInput(
uint256 amountIn,
uint256 amountOutMin,
address tokenIn,
address tokenOut,
address to,
uint256 deadline
) external returns (uint256 amountOut) {
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
// First, dealing with the allowance of the rebalancer to the Transmuter: this allowance is made infinite
// by default
uint256 allowance = IERC20(tokenIn).allowance(address(this), address(TRANSMUTER));
if (allowance < amountIn)
IERC20(tokenIn).safeIncreaseAllowance(address(TRANSMUTER), type(uint256).max - allowance);
// Mint agToken from `tokenIn`
uint256 amountAgToken = TRANSMUTER.swapExactInput(
amountIn,
0,
tokenIn,
AGTOKEN,
address(this),
block.timestamp
);
// Computing if a potential subsidy must be included in the agToken amount to burn
uint256 subsidy = _getSubsidyAmount(tokenIn, tokenOut, amountAgToken, amountIn);
if (subsidy > 0) {
orders[tokenIn][tokenOut].subsidyBudget -= subsidy.toUint112();
budget -= subsidy;
amountAgToken += subsidy;
emit SubsidyPaid(tokenIn, tokenOut, subsidy);
}
amountOut = TRANSMUTER.swapExactInput(amountAgToken, amountOutMin, AGTOKEN, tokenOut, to, deadline);
}
/// @inheritdoc IRebalancer
/// @dev This function returns an approximation and not an exact value as the first mint to compute `amountAgToken`
/// might change the state of the fees slope within the Transmuter that will then be taken into account when
/// burning the minted agToken.
function quoteIn(uint256 amountIn, address tokenIn, address tokenOut) external view returns (uint256 amountOut) {
uint256 amountAgToken = TRANSMUTER.quoteIn(amountIn, tokenIn, AGTOKEN);
amountAgToken += _getSubsidyAmount(tokenIn, tokenOut, amountAgToken, amountIn);
amountOut = TRANSMUTER.quoteIn(amountAgToken, AGTOKEN, tokenOut);
}
/// @inheritdoc IRebalancer
/// @dev Note that this minimum amount is guaranteed up to the subsidy budget, and if for a swap the subsidy budget
/// is not big enough to provide this guaranteed amount out, then less will actually be obtained
function getGuaranteedAmountOut(
address tokenIn,
address tokenOut,
uint256 amountIn
) external view returns (uint256) {
Order storage order = orders[tokenIn][tokenOut];
return _getGuaranteedAmountOut(amountIn, order.guaranteedRate, order.decimalsIn, order.decimalsOut);
}
/// @notice Internal version of `_getGuaranteedAmountOut`
function _getGuaranteedAmountOut(
uint256 amountIn,
uint256 guaranteedRate,
uint8 decimalsIn,
uint8 decimalsOut
) internal pure returns (uint256 amountOut) {
return (amountIn * guaranteedRate * (10 ** decimalsOut)) / (BASE_18 * (10 ** decimalsIn));
}
/// @notice Computes the additional subsidy amount in agToken that must be added during the process of a swap
/// of `amountIn` of `tokenIn` to `tokenOut`
function _getSubsidyAmount(
address tokenIn,
address tokenOut,
uint256 amountAgToken,
uint256 amountIn
) internal view returns (uint256 subsidy) {
Order storage order = orders[tokenIn][tokenOut];
uint256 guaranteedAmountOut = _getGuaranteedAmountOut(
amountIn,
order.guaranteedRate,
order.decimalsIn,
order.decimalsOut
);
// Computing the amount of agToken that must be burnt to get the amountOut guaranteed
if (guaranteedAmountOut > 0) {
uint256 amountAgTokenNeeded = TRANSMUTER.quoteOut(guaranteedAmountOut, AGTOKEN, tokenOut);
// If more agTokens than what has been obtained through the first mint must be burnt to get to the
// guaranteed amountOut, we're taking it from the subsidy budget set
if (amountAgToken < amountAgTokenNeeded) {
subsidy = amountAgTokenNeeded - amountAgToken;
// In the case where the subsidy budget is too small, we may not be able to provide the guaranteed
// amountOut to the user
if (subsidy > order.subsidyBudget) subsidy = order.subsidyBudget;
}
}
}
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
GOVERNANCE
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @inheritdoc IRebalancer
/// @dev Before calling this function, governance must make sure that there are enough `agToken` idle
/// in the contract to sponsor the swaps
/// @dev This function can be used to decrease an order by overriding it
function setOrder(
address tokenIn,
address tokenOut,
uint256 subsidyBudget,
uint256 guaranteedRate
) external onlyGuardian {
Order storage order = orders[tokenIn][tokenOut];
uint8 decimalsIn = order.decimalsIn;
uint8 decimalsOut = order.decimalsOut;
if (decimalsIn == 0) {
decimalsIn = TRANSMUTER.getCollateralDecimals(tokenIn);
order.decimalsIn = decimalsIn;
}
if (decimalsOut == 0) {
decimalsOut = TRANSMUTER.getCollateralDecimals(tokenOut);
order.decimalsOut = decimalsOut;
}
// If a token has 0 decimals on the Transmuter, then it's not an actual collateral of the Transmuter
if (decimalsIn == 0 || decimalsOut == 0) revert NotCollateral();
uint256 newBudget = budget + subsidyBudget - order.subsidyBudget;
if (IERC20(AGTOKEN).balanceOf(address(this)) < newBudget) revert InvalidParam();
budget = newBudget;
order.subsidyBudget = subsidyBudget.toUint112();
order.guaranteedRate = guaranteedRate.toUint128();
emit OrderSet(tokenIn, tokenOut, subsidyBudget, guaranteedRate);
}
/// @inheritdoc IRebalancer
/// @dev This function checks if too much is not being recovered with respect to currently available budgets
function recover(address token, uint256 amount, address to) external onlyGuardian {
if (token == address(AGTOKEN) && IERC20(token).balanceOf(address(this)) < budget + amount)
revert InvalidParam();
IERC20(token).safeTransfer(to, amount);
}
}// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../token/ERC20/extensions/IERC20Metadata.sol";
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol)
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.2._
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v2.5._
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.2._
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v2.5._
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v2.5._
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v2.5._
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v2.5._
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*
* _Available since v3.0._
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*
* _Available since v4.7._
*/
function toInt248(int256 value) internal pure returns (int248) {
require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits");
return int248(value);
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*
* _Available since v4.7._
*/
function toInt240(int256 value) internal pure returns (int240) {
require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits");
return int240(value);
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*
* _Available since v4.7._
*/
function toInt232(int256 value) internal pure returns (int232) {
require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits");
return int232(value);
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*
* _Available since v4.7._
*/
function toInt224(int256 value) internal pure returns (int224) {
require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits");
return int224(value);
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*
* _Available since v4.7._
*/
function toInt216(int256 value) internal pure returns (int216) {
require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits");
return int216(value);
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*
* _Available since v4.7._
*/
function toInt208(int256 value) internal pure returns (int208) {
require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits");
return int208(value);
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*
* _Available since v4.7._
*/
function toInt200(int256 value) internal pure returns (int200) {
require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits");
return int200(value);
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*
* _Available since v4.7._
*/
function toInt192(int256 value) internal pure returns (int192) {
require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits");
return int192(value);
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*
* _Available since v4.7._
*/
function toInt184(int256 value) internal pure returns (int184) {
require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits");
return int184(value);
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*
* _Available since v4.7._
*/
function toInt176(int256 value) internal pure returns (int176) {
require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits");
return int176(value);
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*
* _Available since v4.7._
*/
function toInt168(int256 value) internal pure returns (int168) {
require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits");
return int168(value);
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*
* _Available since v4.7._
*/
function toInt160(int256 value) internal pure returns (int160) {
require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits");
return int160(value);
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*
* _Available since v4.7._
*/
function toInt152(int256 value) internal pure returns (int152) {
require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits");
return int152(value);
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*
* _Available since v4.7._
*/
function toInt144(int256 value) internal pure returns (int144) {
require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits");
return int144(value);
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*
* _Available since v4.7._
*/
function toInt136(int256 value) internal pure returns (int136) {
require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits");
return int136(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*
* _Available since v4.7._
*/
function toInt120(int256 value) internal pure returns (int120) {
require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits");
return int120(value);
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*
* _Available since v4.7._
*/
function toInt112(int256 value) internal pure returns (int112) {
require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits");
return int112(value);
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*
* _Available since v4.7._
*/
function toInt104(int256 value) internal pure returns (int104) {
require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits");
return int104(value);
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*
* _Available since v4.7._
*/
function toInt96(int256 value) internal pure returns (int96) {
require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits");
return int96(value);
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*
* _Available since v4.7._
*/
function toInt88(int256 value) internal pure returns (int88) {
require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits");
return int88(value);
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*
* _Available since v4.7._
*/
function toInt80(int256 value) internal pure returns (int80) {
require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits");
return int80(value);
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*
* _Available since v4.7._
*/
function toInt72(int256 value) internal pure returns (int72) {
require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits");
return int72(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*
* _Available since v4.7._
*/
function toInt56(int256 value) internal pure returns (int56) {
require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits");
return int56(value);
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*
* _Available since v4.7._
*/
function toInt48(int256 value) internal pure returns (int48) {
require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits");
return int48(value);
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*
* _Available since v4.7._
*/
function toInt40(int256 value) internal pure returns (int40) {
require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits");
return int40(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*
* _Available since v4.7._
*/
function toInt24(int256 value) internal pure returns (int24) {
require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits");
return int24(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*
* _Available since v3.0._
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: GPL-3.0
/*
* █
***** ▓▓▓
* ▓▓▓▓▓▓▓
* ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓
***** //////// ▓▓▓▓▓▓▓
* ///////////// ▓▓▓
▓▓ ////////////////// █ ▓▓
▓▓ ▓▓ /////////////////////// ▓▓ ▓▓
▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓
▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓
▓▓ ,////////////////////////////////////// ▓▓ ▓▓
▓▓ ////////////////////////////////////////// ▓▓
▓▓ //////////////////////▓▓▓▓/////////////////////
,////////////////////////////////////////////////////
.//////////////////////////////////////////////////////////
.//////////////////////////██.,//////////////////////////█
.//////////////////////████..,./////////////////////██
...////////////////███████.....,.////////////////███
,.,////////////████████ ........,///////////████
.,.,//////█████████ ,.......///////████
,..//████████ ........./████
..,██████ .....,███
.██ ,.,█
▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓
▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓
▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓
*/
pragma solidity >=0.5.0;
import { IDiamondCut } from "./IDiamondCut.sol";
import { IDiamondEtherscan } from "./IDiamondEtherscan.sol";
import { IDiamondLoupe } from "./IDiamondLoupe.sol";
import { IGetters } from "./IGetters.sol";
import { IRedeemer } from "./IRedeemer.sol";
import { IRewardHandler } from "./IRewardHandler.sol";
import { ISettersGovernor, ISettersGuardian } from "./ISetters.sol";
import { ISwapper } from "./ISwapper.sol";
/// @title ITransmuter
/// @author Angle Labs, Inc.
interface ITransmuter is
IDiamondCut,
IDiamondEtherscan,
IDiamondLoupe,
IGetters,
IRedeemer,
IRewardHandler,
ISettersGovernor,
ISettersGuardian,
ISwapper
{
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
struct Order {
// Total agToken budget allocated to subsidize the swaps between the tokens associated to the order
uint112 subsidyBudget;
// Decimals of the `tokenIn` associated to the order
uint8 decimalsIn;
// Decimals of the `tokenOut` associated to the order
uint8 decimalsOut;
// Guaranteed exchange rate in `BASE_18` for the swaps between the `tokenIn` and `tokenOut` associated to
// the order. This rate is a minimum rate guaranteed up to when the `subsidyBudget` is fully consumed
uint128 guaranteedRate;
}
/// @title IRebalancer
/// @author Angle Labs, Inc.
interface IRebalancer {
/// @notice Swaps `tokenIn` for `tokenOut` through an intermediary agToken mint from `tokenIn` and
/// burn to `tokenOut`. Eventually, this transaction may be sponsored and yield an amount of `tokenOut`
/// higher than what would be obtained through a mint and burn directly on the `transmuter`
/// @param amountIn Amount of `tokenIn` to bring for the rebalancing
/// @param amountOutMin Minimum amount of `tokenOut` that must be obtained from the swap
/// @param to Address to which `tokenOut` must be sent
/// @param deadline Timestamp before which this transaction must be included
/// @return amountOut Amount of outToken obtained
function swapExactInput(
uint256 amountIn,
uint256 amountOutMin,
address tokenIn,
address tokenOut,
address to,
uint256 deadline
) external returns (uint256 amountOut);
/// @notice Approximates how much a call to `swapExactInput` with the same parameters would yield in terms
/// of `amountOut`
function quoteIn(uint256 amountIn, address tokenIn, address tokenOut) external view returns (uint256 amountOut);
/// @notice Helper to compute the minimum guaranteed amount out that would be obtained from a swap of `amountIn`
/// of `tokenIn` to `tokenOut`
function getGuaranteedAmountOut(
address tokenIn,
address tokenOut,
uint256 amountIn
) external view returns (uint256);
/// @notice Lets governance set an order to subsidize rebalances between `tokenIn` and `tokenOut`
function setOrder(address tokenIn, address tokenOut, uint256 subsidyBudget, uint256 guaranteedRate) external;
/// @notice Recovers `amount` of `token` to the `to` address
/// @dev This function checks if too much is not being recovered with respect to currently available budgets
function recover(address token, uint256 amount, address to) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.19;
import { IAccessControlManager } from "interfaces/IAccessControlManager.sol";
import "../utils/Errors.sol";
/// @title AccessControl
/// @author Angle Labs, Inc.
contract AccessControl {
/// @notice `accessControlManager` used to check roles
IAccessControlManager public accessControlManager;
uint256[49] private __gapAccessControl;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MODIFIERS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @notice Checks whether the `msg.sender` has the governor role
modifier onlyGovernor() {
if (!accessControlManager.isGovernor(msg.sender)) revert NotGovernor();
_;
}
/// @notice Checks whether the `msg.sender` has the guardian role
modifier onlyGuardian() {
if (!accessControlManager.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();
_;
}
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @notice Checks whether `admin` has the governor role
function isGovernor(address admin) external view returns (bool) {
return accessControlManager.isGovernor(admin);
}
/// @notice Checks whether `admin` has the guardian role
function isGovernorOrGuardian(address admin) external view returns (bool) {
return accessControlManager.isGovernorOrGuardian(admin);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;
import { ICbETH } from "interfaces/external/coinbase/ICbETH.sol";
import { ISfrxETH } from "interfaces/external/frax/ISfrxETH.sol";
import { IStETH } from "interfaces/external/lido/IStETH.sol";
import { IRETH } from "interfaces/external/rocketPool/IRETH.sol";
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
STORAGE SLOTS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @dev Storage position of `DiamondStorage` structure
/// @dev Equals `keccak256("diamond.standard.diamond.storage") - 1`
bytes32 constant DIAMOND_STORAGE_POSITION = 0xc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131b;
/// @dev Storage position of `TransmuterStorage` structure
/// @dev Equals `keccak256("diamond.standard.transmuter.storage") - 1`
bytes32 constant TRANSMUTER_STORAGE_POSITION = 0xc1f2f38dde3351ac0a64934139e816326caa800303a1235dc53707d0de05d8bd;
/// @dev Storage position of `ImplementationStorage` structure
/// @dev Equals `keccak256("eip1967.proxy.implementation") - 1`
bytes32 constant IMPLEMENTATION_STORAGE_POSITION = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MATHS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
uint256 constant BASE_6 = 1e6;
uint256 constant BASE_8 = 1e8;
uint256 constant BASE_9 = 1e9;
uint256 constant BASE_12 = 1e12;
uint256 constant BASE_18 = 1e18;
uint256 constant HALF_BASE_27 = 1e27 / 2;
uint256 constant BASE_27 = 1e27;
uint256 constant BASE_36 = 1e36;
uint256 constant MAX_BURN_FEE = 999_000_000;
uint256 constant MAX_MINT_FEE = BASE_12 - 1;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
REENTRANT
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint8 constant NOT_ENTERED = 1;
uint8 constant ENTERED = 2;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
COMMON ADDRESSES
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
address constant PERMIT_2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
address constant ONE_INCH_ROUTER = 0x1111111254EEB25477B68fb85Ed929f73A960582;
address constant AGEUR = 0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8;
ICbETH constant CBETH = ICbETH(0xBe9895146f7AF43049ca1c1AE358B0541Ea49704);
IRETH constant RETH = IRETH(0xae78736Cd615f374D3085123A210448E74Fc6393);
IStETH constant STETH = IStETH(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84);
ISfrxETH constant SFRXETH = ISfrxETH(0xac3E018457B222d93114458476f3E3416Abbe38F);// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.19; error AlreadyAdded(); error CannotAddFunctionToDiamondThatAlreadyExists(bytes4 _selector); error CannotAddSelectorsToZeroAddress(bytes4[] _selectors); error CannotRemoveFunctionThatDoesNotExist(bytes4 _selector); error CannotRemoveImmutableFunction(bytes4 _selector); error CannotReplaceFunctionsFromFacetWithZeroAddress(bytes4[] _selectors); error CannotReplaceFunctionThatDoesNotExists(bytes4 _selector); error CannotReplaceFunctionWithTheSameFunctionFromTheSameFacet(bytes4 _selector); error CannotReplaceImmutableFunction(bytes4 _selector); error ContractHasNoCode(); error FunctionNotFound(bytes4 _functionSelector); error IncorrectFacetCutAction(uint8 _action); error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata); error InvalidChainlinkRate(); error InvalidLengths(); error InvalidNegativeFees(); error InvalidOracleType(); error InvalidParam(); error InvalidParams(); error InvalidRate(); error InvalidSwap(); error InvalidTokens(); error ManagerHasAssets(); error NoSelectorsProvidedForFacetForCut(address _facetAddress); error NotAllowed(); error NotCollateral(); error NotGovernor(); error NotGovernorOrGuardian(); error NotTrusted(); error NotWhitelisted(); error OneInchSwapFailed(); error Paused(); error ReentrantCall(); error RemoveFacetAddressMustBeZeroAddress(address _facetAddress); error TooBigAmountIn(); error TooLate(); error TooSmallAmountOut(); error ZeroAddress(); error ZeroAmount();
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @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 amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` 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 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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, it is bubbled up by this
* function (like regular Solidity function calls).
*
* 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.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @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`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// 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(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
import "../transmuter/Storage.sol";
/// @title IDiamondCut
/// @author Angle Labs, Inc.
/// @dev Reference: EIP-2535 Diamonds
/// @dev Forked from https://github.com/mudgen/diamond-3/blob/master/contracts/interfaces/IDiamondCut.sol by mudgen
interface IDiamondCut {
/// @notice Add/replace/remove any number of functions and optionally execute a function with delegatecall
/// @param _diamondCut Contains the facet addresses and function selectors
/// @param _init The address of the contract or facet to execute _calldata
/// @param _calldata A function call, including function selector and arguments, executed with delegatecall on _init
function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
/// @title IDiamondEtherscan
/// @author Angle Labs, Inc.
interface IDiamondEtherscan {
/// @notice Sets a dummy implementation with the same layout at the diamond proxy contract with all its facets
function setDummyImplementation(address _implementation) external;
/// @notice Address of the dummy implementation used to make the DiamondProxy contract interpretable by Etherscan
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
import "../transmuter/Storage.sol";
/// @notice IDiamondLoupe
/// @author Angle Labs, Inc.
/// @dev Reference: EIP-2535 Diamonds
/// @dev Forked from https://github.com/mudgen/diamond-3/blob/master/contracts/interfaces/IDiamondLoupe.sol by mudgen
interface IDiamondLoupe {
/// @notice Gets all facet addresses and their four byte function selectors.
/// @return facets_ Facet
function facets() external view returns (Facet[] memory facets_);
/// @notice Gets all the function selectors supported by a specific facet.
/// @param _facet The facet address.
/// @return facetFunctionSelectors_
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
/// @notice Get all the facet addresses used by a diamond.
/// @return facetAddresses_
function facetAddresses() external view returns (address[] memory facetAddresses_);
/// @notice Gets the facet that supports the given selector.
/// @dev If facet is not found return address(0).
/// @param _functionSelector The function selector.
/// @return facetAddress_ The facet address.
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
import { IAccessControlManager } from "interfaces/IAccessControlManager.sol";
import { IAgToken } from "interfaces/IAgToken.sol";
import "../transmuter/Storage.sol";
/// @title IGetters
/// @author Angle Labs, Inc.
interface IGetters {
/// @notice Checks whether a given `selector` is actually a valid selector corresponding to a function in one of the
/// facets of the proxy
function isValidSelector(bytes4 selector) external view returns (bool);
/// @notice Reference to the `accessControlManager` contract of the system
function accessControlManager() external view returns (IAccessControlManager);
/// @notice Stablecoin minted by transmuter
function agToken() external view returns (IAgToken);
/// @notice Returns the list of collateral assets supported by the system
function getCollateralList() external view returns (address[] memory);
/// @notice Returns all the info in storage associated to a `collateral`
function getCollateralInfo(address collateral) external view returns (Collateral memory);
/// @notice Returns the decimals of a given `collateral`
function getCollateralDecimals(address collateral) external view returns (uint8);
/// @notice Returns the `xFee` and `yFee` arrays from which fees are computed when coming to mint
/// with `collateral`
function getCollateralMintFees(address collateral) external view returns (uint64[] memory, int64[] memory);
/// @notice Returns the `xFee` and `yFee` arrays from which fees are computed when coming to burn
/// for `collateral`
function getCollateralBurnFees(address collateral) external view returns (uint64[] memory, int64[] memory);
/// @notice Returns the `xFee` and `yFee` arrays used to compute the penalty factor depending on the collateral
/// ratio when users come to redeem
function getRedemptionFees() external view returns (uint64[] memory, int64[] memory);
/// @notice Returns the collateral ratio of Transmuter in base `10**9` and a rounded version of the total amount
/// of stablecoins issued
function getCollateralRatio() external view returns (uint64 collatRatio, uint256 stablecoinsIssued);
/// @notice Returns the total amount of stablecoins issued through Transmuter
function getTotalIssued() external view returns (uint256 stablecoinsIssued);
/// @notice Returns the amount of stablecoins issued from `collateral` and the total amount of stablecoins issued
/// through Transmuter
function getIssuedByCollateral(
address collateral
) external view returns (uint256 stablecoinsFromCollateral, uint256 stablecoinsIssued);
/// @notice Returns if a collateral is "managed" and the associated manager configuration
function getManagerData(
address collateral
) external view returns (bool isManaged, IERC20[] memory subCollaterals, bytes memory config);
/// @notice Returns the oracle values associated to `collateral`
/// @return mint Oracle value to be used for a mint transaction with `collateral`
/// @return burn Oracle value that will be used for `collateral` for a burn transaction. This value
/// is then used along with oracle values for all other collateral assets to get a global burn value for the oracle
/// @return ratio Ratio, in base `10**18` between the oracle value of the `collateral` and its target price.
/// This value is 10**18 if the oracle is greater than the collateral price
/// @return minRatio Minimum ratio across all collateral assets between a collateral burn price and its target
/// price. This value is independent of `collateral` and is used to normalize the burn oracle value for burn
/// transactions.
/// @return redemption Oracle value that would be used to price `collateral` when computing the collateral ratio
/// during a redemption
function getOracleValues(
address collateral
) external view returns (uint256 mint, uint256 burn, uint256 ratio, uint256 minRatio, uint256 redemption);
/// @notice Returns the data used to compute oracle values for `collateral`
/// @return oracleType Type of oracle (Chainlink, external smart contract, ...)
/// @return targetType Type passed to read the value of the target price
/// @return oracleData Extra data needed to read the oracle. For Chainlink oracles, this data is supposed to give
/// the addresses of the Chainlink feeds to read, the stale periods for each feed, ...
/// @return targetData Extra data needed to read the target price of the asset
function getOracle(
address collateral
)
external
view
returns (
OracleReadType oracleType,
OracleReadType targetType,
bytes memory oracleData,
bytes memory targetData
);
/// @notice Returns if the associated functionality is paused or not
function isPaused(address collateral, ActionType action) external view returns (bool);
/// @notice Returns if `sender` is trusted to update normalizers
function isTrusted(address sender) external view returns (bool);
/// @notice Returns if `sender` is trusted to update sell rewards
function isTrustedSeller(address sender) external view returns (bool);
/// @notice Checks whether `sender` has a non null entry in the `isWhitelistedForType` storage mapping
/// @dev Note that ultimately whitelisting may depend as well on external providers
function isWhitelistedForType(WhitelistType whitelistType, address sender) external view returns (bool);
/// @notice Checks whether `sender` can deal with `collateral` during burns and redemptions
function isWhitelistedForCollateral(address collateral, address sender) external returns (bool);
/// @notice Checks whether only whitelisted address can deal with `collateral` during burns and redemptions
function isWhitelistedCollateral(address collateral) external view returns (bool);
/// @notice Gets the data needed to deal with whitelists for `collateral`
function getCollateralWhitelistData(address collateral) external view returns (bytes memory);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title IRedeemer
/// @author Angle Labs, Inc.
interface IRedeemer {
/// @notice Redeems `amount` of stablecoins from the system
/// @param receiver Address which should be receiving the output tokens
/// @param deadline Timestamp before which the redemption should have occured
/// @param minAmountOuts Minimum amount of each token given back in the redemption to obtain
/// @return tokens List of tokens returned
/// @return amounts Amount given for each token in the `tokens` array
function redeem(
uint256 amount,
address receiver,
uint256 deadline,
uint256[] memory minAmountOuts
) external returns (address[] memory tokens, uint256[] memory amounts);
/// @notice Same as the redeem function above with the additional feature to specify a list of `forfeitTokens` for
/// which the Transmuter system will not try to do a transfer to `receiver`.
function redeemWithForfeit(
uint256 amount,
address receiver,
uint256 deadline,
uint256[] memory minAmountOuts,
address[] memory forfeitTokens
) external returns (address[] memory tokens, uint256[] memory amounts);
/// @notice Simulate the exact output that a redemption of `amount` of stablecoins would give at a given block
/// @return tokens List of tokens that would be given
/// @return amounts Amount that would be obtained for each token in the `tokens` array
function quoteRedemptionCurve(
uint256 amount
) external view returns (address[] memory tokens, uint256[] memory amounts);
/// @notice Updates the normalizer variable by `amount`
function updateNormalizer(uint256 amount, bool increase) external returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title IRewardHandler
/// @author Angle Labs, Inc.
interface IRewardHandler {
/// @notice Sells some external tokens through a 1inch call
/// @param minAmountOut Minimum amount of the outToken to get
/// @param payload Payload to pass to 1inch
/// @return amountOut Amount obtained of the outToken
function sellRewards(uint256 minAmountOut, bytes memory payload) external returns (uint256 amountOut);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
import { IERC20 } from "oz/interfaces/IERC20.sol";
import "../transmuter/Storage.sol";
/// @title ISettersGovernor
/// @author Angle Labs, Inc.
interface ISettersGovernor {
/// @notice Recovers `amount` of `token` from the Transmuter contract
function recoverERC20(address collateral, IERC20 token, address to, uint256 amount) external;
/// @notice Sets a new access control manager address
function setAccessControlManager(address _newAccessControlManager) external;
/// @notice Sets (or unsets) a collateral manager `collateral`
function setCollateralManager(address collateral, ManagerStorage memory managerData) external;
/// @notice Sets the allowance of the contract on `token` for `spender` to `amount`
function changeAllowance(IERC20 token, address spender, uint256 amount) external;
/// @notice Changes the trusted status for `sender` when for selling rewards or updating the normalizer
function toggleTrusted(address sender, TrustedType t) external;
/// @notice Changes whether a `collateral` can only be handled during burns and redemptions by whitelisted addresses
/// and sets the data used to read into the whitelist
function setWhitelistStatus(address collateral, uint8 whitelistStatus, bytes memory whitelistData) external;
/// @notice Add `collateral` as a supported collateral in the system
function addCollateral(address collateral) external;
/// @notice Adjusts the amount of stablecoins issued from `collateral` by `amount`
function adjustStablecoins(address collateral, uint128 amount, bool increase) external;
/// @notice Revokes `collateral` from the system
function revokeCollateral(address collateral) external;
/// @notice Sets the `oracleConfig` used to read the value of `collateral` for the mint, burn and redemption
/// operations
function setOracle(address collateral, bytes memory oracleConfig) external;
}
/// @title ISettersGovernor
/// @author Angle Labs, Inc.
interface ISettersGuardian {
/// @notice Changes the pause status for mint or burn transactions for `collateral`
function togglePause(address collateral, ActionType action) external;
/// @notice Sets the mint or burn fees for `collateral`
function setFees(address collateral, uint64[] memory xFee, int64[] memory yFee, bool mint) external;
/// @notice Sets the parameters for the redemption curve
function setRedemptionCurveParams(uint64[] memory xFee, int64[] memory yFee) external;
/// @notice Changes the whitelist status for a collateral with `whitelistType` for an address `who`
function toggleWhitelist(WhitelistType whitelistType, address who) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title ISwapper
/// @author Angle Labs, Inc.
interface ISwapper {
/// @notice Swaps (that is to say mints or burns) an exact amount of `tokenIn` for an amount of `tokenOut`
/// @param amountIn Amount of `tokenIn` to bring
/// @param amountOutMin Minimum amount of `tokenOut` to get: if `amountOut` is inferior to this amount, the
/// function will revert
/// @param tokenIn Token to bring for the swap
/// @param tokenOut Token to get out of the swap
/// @param to Address to which `tokenOut` must be sent
/// @param deadline Timestamp before which the transaction must be executed
/// @return amountOut Amount of `tokenOut` obtained through the swap
function swapExactInput(
uint256 amountIn,
uint256 amountOutMin,
address tokenIn,
address tokenOut,
address to,
uint256 deadline
) external returns (uint256 amountOut);
/// @notice Same as `swapExactInput`, but using Permit2 signatures for `tokenIn`
/// @dev Can only be used to mint, hence `tokenOut` is not needed
function swapExactInputWithPermit(
uint256 amountIn,
uint256 amountOutMin,
address tokenIn,
address to,
uint256 deadline,
bytes calldata permitData
) external returns (uint256 amountOut);
/// @notice Swaps (that is to say mints or burns) an amount of `tokenIn` for an exact amount of `tokenOut`
/// @param amountOut Amount of `tokenOut` to obtain from the swap
/// @param amountInMax Maximum amount of `tokenIn` to bring in order to get `amountOut` of `tokenOut`
/// @param tokenIn Token to bring for the swap
/// @param tokenOut Token to get out of the swap
/// @param to Address to which `tokenOut` must be sent
/// @param deadline Timestamp before which the transaction must be executed
/// @return amountIn Amount of `tokenIn` used to perform the swap
function swapExactOutput(
uint256 amountOut,
uint256 amountInMax,
address tokenIn,
address tokenOut,
address to,
uint256 deadline
) external returns (uint256 amountIn);
/// @notice Same as `swapExactOutput`, but using Permit2 signatures for `tokenIn`
/// @dev Can only be used to mint, hence `tokenOut` is not needed
function swapExactOutputWithPermit(
uint256 amountOut,
uint256 amountInMax,
address tokenIn,
address to,
uint256 deadline,
bytes calldata permitData
) external returns (uint256 amountIn);
/// @notice Simulates what a call to `swapExactInput` with `amountIn` of `tokenIn` for `tokenOut` would give.
/// If called right before and at the same block, the `amountOut` outputted by this function is exactly the
/// amount that will be obtained with `swapExactInput`
function quoteIn(uint256 amountIn, address tokenIn, address tokenOut) external view returns (uint256 amountOut);
/// @notice Simulates what a call to `swapExactOutput` for `amountOut` of `tokenOut` with `tokenIn` would give.
/// If called right before and at the same block, the `amountIn` outputted by this function is exactly the
/// amount that will be obtained with `swapExactOutput`
function quoteOut(uint256 amountOut, address tokenIn, address tokenOut) external view returns (uint256 amountIn);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title IAccessControlManager
/// @author Angle Labs, Inc.
interface IAccessControlManager {
/// @notice Checks whether an address is governor of the Angle Protocol or not
/// @param admin Address to check
/// @return Whether the address has the `GOVERNOR_ROLE` or not
function isGovernor(address admin) external view returns (bool);
/// @notice Checks whether an address is governor or a guardian of the Angle Protocol or not
/// @param admin Address to check
/// @return Whether the address has the `GUARDIAN_ROLE` or not
/// @dev Governance should make sure when adding a governor to also give this governor the guardian
/// role by calling the `addGovernor` function
function isGovernorOrGuardian(address admin) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title ICbETH
/// @notice Interface for the `cbETH` contract
interface ICbETH {
function exchangeRate() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title ISfrxETH
/// @notice Interface for the `sfrxETH` contract
interface ISfrxETH {
function pricePerShare() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title IStETH
/// @notice Interface for the `StETH` contract
interface IStETH {
function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256);
function submit(address) external payable returns (uint256);
function getSharesByPooledEth(uint256 _ethAmount) external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
/// @title IRETH
/// @notice Interface for the `rETH` contract
interface IRETH {
function getExchangeRate() external view returns (uint256);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.19;
import { IERC20 } from "oz/token/ERC20/IERC20.sol";
import { IAccessControlManager } from "interfaces/IAccessControlManager.sol";
import { IAgToken } from "interfaces/IAgToken.sol";
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ENUMS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
enum FacetCutAction {
Add,
Replace,
Remove
}
enum ManagerType {
EXTERNAL
}
enum ActionType {
Mint,
Burn,
Redeem
}
enum TrustedType {
Updater,
Seller
}
enum QuoteType {
MintExactInput,
MintExactOutput,
BurnExactInput,
BurnExactOutput
}
enum OracleReadType {
CHAINLINK_FEEDS,
EXTERNAL,
NO_ORACLE,
STABLE,
WSTETH,
CBETH,
RETH,
SFRXETH,
PYTH
}
enum OracleQuoteType {
UNIT,
TARGET
}
enum WhitelistType {
BACKED
}
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
struct Permit2Details {
address to; // Address that will receive the funds
uint256 nonce; // Nonce of the transaction
bytes signature; // Permit signature of the user
}
struct FacetCut {
address facetAddress; // Facet contract address
FacetCutAction action; // Can be add, remove or replace
bytes4[] functionSelectors; // Ex. bytes4(keccak256("transfer(address,uint256)"))
}
struct Facet {
address facetAddress; // Facet contract address
bytes4[] functionSelectors; // Ex. bytes4(keccak256("transfer(address,uint256)"))
}
struct FacetInfo {
address facetAddress; // Facet contract address
uint16 selectorPosition; // Position in the list of all selectors
}
struct DiamondStorage {
bytes4[] selectors; // List of all available selectors
mapping(bytes4 => FacetInfo) selectorInfo; // Selector to (address, position in list)
IAccessControlManager accessControlManager; // Contract handling access control
}
struct ImplementationStorage {
address implementation; // Dummy implementation address for Etherscan usability
}
struct ManagerStorage {
IERC20[] subCollaterals; // Subtokens handled by the manager or strategies
bytes config; // Additional configuration data
}
struct Collateral {
uint8 isManaged; // If the collateral is managed through external strategies
uint8 isMintLive; // If minting from this asset is unpaused
uint8 isBurnLive; // If burning to this asset is unpaused
uint8 decimals; // IERC20Metadata(collateral).decimals()
uint8 onlyWhitelisted; // If only whitelisted addresses can burn or redeem for this token
uint216 normalizedStables; // Normalized amount of stablecoins issued from this collateral
uint64[] xFeeMint; // Increasing exposures in [0,BASE_9[
int64[] yFeeMint; // Mint fees at the exposures specified in `xFeeMint`
uint64[] xFeeBurn; // Decreasing exposures in ]0,BASE_9]
int64[] yFeeBurn; // Burn fees at the exposures specified in `xFeeBurn`
bytes oracleConfig; // Data about the oracle used for the collateral
bytes whitelistData; // For whitelisted collateral, data used to verify whitelists
ManagerStorage managerData; // For managed collateral, data used to handle the strategies
}
struct TransmuterStorage {
IAgToken agToken; // agToken handled by the system
uint8 isRedemptionLive; // If redemption is unpaused
uint8 statusReentrant; // If call is reentrant or not
uint128 normalizedStables; // Normalized amount of stablecoins issued by the system
uint128 normalizer; // To reconcile `normalizedStables` values with the actual amount
address[] collateralList; // List of collateral assets supported by the system
uint64[] xRedemptionCurve; // Increasing collateral ratios > 0
int64[] yRedemptionCurve; // Value of the redemption fees at `xRedemptionCurve`
mapping(address => Collateral) collaterals; // Maps a collateral asset to its parameters
mapping(address => uint256) isTrusted; // If an address is trusted to update the normalizer value
mapping(address => uint256) isSellerTrusted; // If an address is trusted to sell accruing reward tokens
mapping(WhitelistType => mapping(address => uint256)) isWhitelistedForType;
// Whether an address is whitelisted for a specific whitelist type
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
import { IERC20 } from "oz/token/ERC20/IERC20.sol";
/// @title IAgToken
/// @author Angle Labs, Inc.
/// @notice Interface for the stablecoins `AgToken` contracts
interface IAgToken is IERC20 {
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MINTER ROLE ONLY FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @notice Lets a whitelisted contract mint agTokens
/// @param account Address to mint to
/// @param amount Amount to mint
function mint(address account, uint256 amount) external;
/// @notice Burns `amount` tokens from a `burner` address after being asked to by `sender`
/// @param amount Amount of tokens to burn
/// @param burner Address to burn from
/// @param sender Address which requested the burn from `burner`
/// @dev This method is to be called by a contract with the minter right after being requested
/// to do so by a `sender` address willing to burn tokens from another `burner` address
/// @dev The method checks the allowance between the `sender` and the `burner`
function burnFrom(uint256 amount, address burner, address sender) external;
/// @notice Burns `amount` tokens from a `burner` address
/// @param amount Amount of tokens to burn
/// @param burner Address to burn from
/// @dev This method is to be called by a contract with a minter right on the AgToken after being
/// requested to do so by an address willing to burn tokens from its address
function burnSelf(uint256 amount, address burner) external;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TREASURY ONLY FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @notice Adds a minter in the contract
/// @param minter Minter address to add
/// @dev Zero address checks are performed directly in the `Treasury` contract
function addMinter(address minter) external;
/// @notice Removes a minter from the contract
/// @param minter Minter address to remove
/// @dev This function can also be called by a minter wishing to revoke itself
function removeMinter(address minter) external;
/// @notice Sets a new treasury contract
/// @param _treasury New treasury address
function setTreasury(address _treasury) external;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
/// @notice Checks whether an address has the right to mint agTokens
/// @param minter Address for which the minting right should be checked
/// @return Whether the address has the right to mint agTokens or not
function isMinter(address minter) external view returns (bool);
/// @notice Amount of decimals of the stablecoin
function decimals() external view returns (uint8);
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"stringutils/=lib/solidity-stringutils/",
"contracts/=contracts/",
"test/=test/",
"interfaces/=contracts/interfaces/",
"oz/=lib/openzeppelin-contracts/contracts/",
"oz-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"mock/=test/mock/",
"prb/math/=lib/prb-math/src/",
"borrow/=lib/borrow-contracts/contracts/",
"@chainlink/=lib/borrow-contracts/node_modules/@chainlink/",
"@ensdomains/=node_modules/@ensdomains/",
"@prb/test/=lib/prb-math/lib/prb-test/src/",
"@uniswap/=lib/borrow-contracts/node_modules/@uniswap/",
"borrow-contracts/=lib/borrow-contracts/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"prb-math/=lib/prb-math/src/",
"prb-test/=lib/prb-math/lib/prb-test/src/",
"solidity-stringutils/=lib/solidity-stringutils/",
"src/=lib/prb-math/src/"
],
"optimizer": {
"enabled": true,
"runs": 1000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IAccessControlManager","name":"_accessControlManager","type":"address"},{"internalType":"contract ITransmuter","name":"_transmuter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidParam","type":"error"},{"inputs":[],"name":"NotCollateral","type":"error"},{"inputs":[],"name":"NotGovernorOrGuardian","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"subsidyBudget","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"guaranteedRate","type":"uint256"}],"name":"OrderSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"subsidy","type":"uint256"}],"name":"SubsidyPaid","type":"event"},{"inputs":[],"name":"AGTOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSMUTER","outputs":[{"internalType":"contract ITransmuter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accessControlManager","outputs":[{"internalType":"contract IAccessControlManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"budget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"getGuaranteedAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isGovernorOrGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"orders","outputs":[{"internalType":"uint112","name":"subsidyBudget","type":"uint112"},{"internalType":"uint8","name":"decimalsIn","type":"uint8"},{"internalType":"uint8","name":"decimalsOut","type":"uint8"},{"internalType":"uint128","name":"guaranteedRate","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"quoteIn","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"recover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"subsidyBudget","type":"uint256"},{"internalType":"uint256","name":"guaranteedRate","type":"uint256"}],"name":"setOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactInput","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c06040908082523462000195578181620017ba80380380916200002482856200019a565b833981010312620001955780516001600160a01b03918282169182900362000195576020015182811690818103620001955782156200018457600080546001600160a01b0319169093178355608052835163ee565a6360e01b81529190602090839060049082905afa918215620001785781926200012c575b50501660a052516115e59081620001d5823960805181818161019901528181610506015281816107510152818161080a015281816108c001528181610a5601528181610ae801528181610e7e01528181610f430152611225015260a051818181610251015281816103e301528181610528015281816107ce0152818161088101528181610cbf01526111ed0152f35b9091506020813d82116200016f575b816200014a602093836200019a565b810103126200016b575190828216820362000168575038806200009d565b80fd5b5080fd5b3d91506200013b565b508351903d90823e3d90fd5b845163d92e233d60e01b8152600490fd5b600080fd5b601f909101601f19168101906001600160401b03821190821017620001be57604052565b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c9081630ba8508114610fe25750806334eb265514610bbc5780633b6a1fe01461067f5780634583aea6146104d75780634c11fc6614610467578063521d4de91461040757806376ca0ba7146103c35780638e5116bc146101e4578063b4a0bdf3146101bd578063d0fbd71c14610179578063e43581b8146100c65763ed01bf29146100a357600080fd5b346100c15760003660031901126100c1576020603354604051908152f35b600080fd5b346100c15760203660031901126100c1576100df611061565b60206001600160a01b03602481600054169360405194859384927fe43581b80000000000000000000000000000000000000000000000000000000084521660048301525afa801561016d57602091600091610140575b506040519015158152f35b6101609150823d8111610166575b61015881836110a3565b8101906112df565b82610135565b503d61014e565b6040513d6000823e3d90fd5b346100c15760003660031901126100c15760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100c15760003660031901126100c15760206001600160a01b0360005416604051908152f35b346100c15760603660031901126100c1576101fd611061565b60243561020861108d565b906001600160a01b0390816000541693604051809563521d4de960e01b825233600483015281602460209889935afa90811561016d576000916103a6575b501561037c578216917f000000000000000000000000000000000000000000000000000000000000000016821480610311575b6102e7576102e5936102d26102e0927fa9059cbb000000000000000000000000000000000000000000000000000000009560405196879485015260248401602090939291936001600160a01b0360408201951681520152565b03601f1981018452836110a3565b611310565b005b60046040517fd2529034000000000000000000000000000000000000000000000000000000008152fd5b506040516370a0823160e01b81523060048201528481602481865afa90811561016d5760009161034f575b50610349826033546110d2565b11610279565b90508481813d8311610375575b61036681836110a3565b810103126100c157518561033c565b503d61035c565b60046040517f99e120bc000000000000000000000000000000000000000000000000000000008152fd5b6103bd9150863d88116101665761015881836110a3565b86610246565b346100c15760003660031901126100c15760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b346100c15760203660031901126100c157610420611061565b60206001600160a01b036024816000541693604051948593849263521d4de960e01b84521660048301525afa801561016d5760209160009161014057506040519015158152f35b346100c15760603660031901126100c157610480611061565b610488611077565b906001600160a01b0380911660005260326020526040600020911660005260205260206104cf60406000205460ff8160781c169060ff8160701c169060801c604435611103565b604051908152f35b346100c15760603660031901126100c1576004356104f3611077565b6104fb61108d565b906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000906040517f4583aea600000000000000000000000000000000000000000000000000000000908181526020968782806105a3888a8660048501916040919493606084019584526001600160a01b03809216602085015216910152565b0381875afa91821561016d5788968891600094610644575b5091836105cc926105d2959461115a565b906110d2565b60405191825260048201526001600160a01b039283166024820152939091166044840152829060649082905afa90811561016d57600091610617575b50604051908152f35b90508181813d831161063d575b61062e81836110a3565b810103126100c157518261060e565b503d610624565b9788919394508092503d8311610678575b61065f81836110a3565b810103126100c1579451879590919087906105cc6105bb565b503d610655565b346100c15760c03660031901126100c15761069861108d565b6001600160a01b03908160643516606435036100c15760843582811681036100c1576040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015260043560648201526064815260a081019080821067ffffffffffffffff831117610ba65761072291604052848416611310565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008082523060048301527f000000000000000000000000000000000000000000000000000000000000000085166001600160a01b031660248301526020826044818789165afa91821561016d57600092610b72575b506004358210610a48575b50506040516301db50ff60e51b81526004356004820152600060248201528383166044820152837f00000000000000000000000000000000000000000000000000000000000000001660648201523060848201524260a482015260208160c4816000887f0000000000000000000000000000000000000000000000000000000000000000165af190811561016d57600091610a16575b50809261084e600435836064358461115a565b8061092e575b50505060c460209260008560405196879586946301db50ff60e51b865260048601526024356024860152817f00000000000000000000000000000000000000000000000000000000000000001660448601528160643516606486015216608484015260a43560a48401527f0000000000000000000000000000000000000000000000000000000000000000165af1801561016d576000906108fb575b602090604051908152f35b506020813d602011610926575b81610915602093836110a3565b810103126100c157602090516108f0565b3d9150610908565b9091935061093b8161152a565b918581166000526032602052604060002086606435166000526020526040600020928354906dffffffffffffffffffffffffffff8082168184160311610a005760209660c4956109c6936dffffffffffffffffffffffffffff808895168183160316906dffffffffffffffffffffffffffff19161790556109be826033546110c5565b6033556110d2565b916040519081527f6ee4d68c462d41c4639ae97a14beea115bfcdf71e4ef3c863ff588451a8f4a1d86888060643516941692a39285610854565b634e487b7160e01b600052601160045260246000fd5b90506020813d602011610a40575b81610a31602093836110a3565b810103126100c157518461083b565b3d9150610a24565b6040519081523060048201527f000000000000000000000000000000000000000000000000000000000000000085166001600160a01b031660248201526020816044818789165afa90811561016d57600091610b3e575b50610b2f610ab5610b2192610b379419906110d2565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000891616602482015260448101919091529182906064820190565b03601f1981018352826110a3565b848416611310565b83806107a5565b90506020813d602011610b6a575b81610b59602093836110a3565b810103126100c15751610b2f610a9f565b3d9150610b4c565b9091506020813d602011610b9e575b81610b8e602093836110a3565b810103126100c15751908561079a565b3d9150610b81565b634e487b7160e01b600052604160045260246000fd5b346100c15760803660031901126100c157610bd5611061565b610bdd611077565b906044356064356001600160a01b0392836000541690604051809263521d4de960e01b825233600483015281602460209586935afa90811561016d57600091610fc5575b501561037c578416938460005260328252806040600020961695866000528252604060002090815460ff8160701c1660ff8260781c16918115610f25575b508115610e60575b60ff1615908115610e54575b50610e2a57610c84856033546110d2565b90602484610ca56dffffffffffffffffffffffffffff9485875416906110c5565b92604051928380926370a0823160e01b82523060048301527f0000000000000000000000000000000000000000000000000000000000000000165afa801561016d578291600091610df9575b50106102e757603355610d038561152a565b168154906fffffffffffffffffffffffffffffffff8511610d8f57917f7870b01b22e7b2fbb2ced2043d7badd877232d56a4fe8e0986aa14b8675bef6195939185936fffff00000000000000000000000000007fffffffffffffffffffffffffffffffff0000000000000000000000000000000060409860801b169216171790558351928352820152a3005b6084846040519062461bcd60e51b82526004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f32382062697473000000000000000000000000000000000000000000000000006064820152fd5b809250868092503d8311610e23575b610e1281836110a3565b810103126100c1578190518a610cf1565b503d610e08565b60046040517f373f15fc000000000000000000000000000000000000000000000000000000008152fd5b60ff9150161588610c73565b90506040519063eb7aac5f60e01b82528860048301528482602481867f0000000000000000000000000000000000000000000000000000000000000000165afa91821561016d57600092610ef3575b5083547fffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffff16607883901b6fff00000000000000000000000000000016178455610c67565b60ff919250610f1790863d8811610f1e575b610f0f81836110a3565b8101906112f7565b9190610eaf565b503d610f05565b90506040519063eb7aac5f60e01b82528860048301528582602481877f0000000000000000000000000000000000000000000000000000000000000000165afa91821561016d57600092610fa6575b506eff00000000000000000000000000001916607082901b6eff00000000000000000000000000001617845589610c5f565b610fbe919250863d8811610f1e57610f0f81836110a3565b908a610f74565b610fdc9150833d85116101665761015881836110a3565b87610c21565b346100c15760403660031901126100c157608090610ffe611061565b611006611077565b906001600160a01b038091166000526032602052604060002091166000526020526040600020546dffffffffffffffffffffffffffff8116825260ff8160701c16602083015260ff8160781c166040830152821c6060820152f35b600435906001600160a01b03821682036100c157565b602435906001600160a01b03821682036100c157565b604435906001600160a01b03821682036100c157565b90601f8019910116810190811067ffffffffffffffff821117610ba657604052565b91908203918211610a0057565b91908201809211610a0057565b81810292918115918404141715610a0057565b60ff16604d8111610a0057600a0a90565b9261111e6111186111189361112495966110df565b916110f2565b906110df565b90670de0b6b3a76400009180830292830403610a00578115611144570490565b634e487b7160e01b600052601260045260246000fd5b9392919060009460006001600160a01b0380921681526020926032845260408220838216835284526111a560408320549660ff8860781c169060ff8960701c16908960801c90611103565b90816111b5575b50505050505050565b6040517f9525f3ab00000000000000000000000000000000000000000000000000000000815260048101929092526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024840152166044820152918390839060649082907f0000000000000000000000000000000000000000000000000000000000000000165afa9283156112d257819361129e575b505050808210611269575b808080806111ac565b6dffffffffffffffffffffffffffff92945090611285916110c5565b9216808311611296575b8080611260565b91503861128f565b9091809350813d83116112cb575b6112b681836110a3565b810103126112c8575051388080611255565b80fd5b503d6112ac565b50604051903d90823e3d90fd5b908160209103126100c1575180151581036100c15790565b908160209103126100c1575160ff811681036100c15790565b6001600160a01b03169060409081519082820167ffffffffffffffff9083811082821117610ba65784526020948584527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656486850152803b1561146c5760008381949282898195519301915af1903d1561145d573d9081116114495784516113b5949392916113a7601f8201601f19168901836110a3565b81528092873d92013e6114af565b805190816113c4575b50505050565b83806113d49383010191016112df565b156113e05780806113be565b60849250519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b602483634e487b7160e01b81526041600452fd5b506113b59291506060906114af565b60648686519062461bcd60e51b82526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b909190156114bb575090565b8151156114cb5750805190602001fd5b6040519062461bcd60e51b82528160208060048301528251908160248401526000935b828510611511575050604492506000838284010152601f80199101168101030190fd5b84810182015186860160440152938101938593506114ee565b6dffffffffffffffffffffffffffff90818111611545571690565b608460405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f31322062697473000000000000000000000000000000000000000000000000006064820152fdfea264697066735822122022ca3a821a690be3fb400f3b189482b2002792e1164053c207fba226dee60c6164736f6c634300081300330000000000000000000000005bc6bef80da563ebf6df6d6913513fa9a7ec89be00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab
Deployed Bytecode
0x608080604052600436101561001357600080fd5b60003560e01c9081630ba8508114610fe25750806334eb265514610bbc5780633b6a1fe01461067f5780634583aea6146104d75780634c11fc6614610467578063521d4de91461040757806376ca0ba7146103c35780638e5116bc146101e4578063b4a0bdf3146101bd578063d0fbd71c14610179578063e43581b8146100c65763ed01bf29146100a357600080fd5b346100c15760003660031901126100c1576020603354604051908152f35b600080fd5b346100c15760203660031901126100c1576100df611061565b60206001600160a01b03602481600054169360405194859384927fe43581b80000000000000000000000000000000000000000000000000000000084521660048301525afa801561016d57602091600091610140575b506040519015158152f35b6101609150823d8111610166575b61015881836110a3565b8101906112df565b82610135565b503d61014e565b6040513d6000823e3d90fd5b346100c15760003660031901126100c15760206040516001600160a01b037f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab168152f35b346100c15760003660031901126100c15760206001600160a01b0360005416604051908152f35b346100c15760603660031901126100c1576101fd611061565b60243561020861108d565b906001600160a01b0390816000541693604051809563521d4de960e01b825233600483015281602460209889935afa90811561016d576000916103a6575b501561037c578216917f0000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce816821480610311575b6102e7576102e5936102d26102e0927fa9059cbb000000000000000000000000000000000000000000000000000000009560405196879485015260248401602090939291936001600160a01b0360408201951681520152565b03601f1981018452836110a3565b611310565b005b60046040517fd2529034000000000000000000000000000000000000000000000000000000008152fd5b506040516370a0823160e01b81523060048201528481602481865afa90811561016d5760009161034f575b50610349826033546110d2565b11610279565b90508481813d8311610375575b61036681836110a3565b810103126100c157518561033c565b503d61035c565b60046040517f99e120bc000000000000000000000000000000000000000000000000000000008152fd5b6103bd9150863d88116101665761015881836110a3565b86610246565b346100c15760003660031901126100c15760206040516001600160a01b037f0000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce8168152f35b346100c15760203660031901126100c157610420611061565b60206001600160a01b036024816000541693604051948593849263521d4de960e01b84521660048301525afa801561016d5760209160009161014057506040519015158152f35b346100c15760603660031901126100c157610480611061565b610488611077565b906001600160a01b0380911660005260326020526040600020911660005260205260206104cf60406000205460ff8160781c169060ff8160701c169060801c604435611103565b604051908152f35b346100c15760603660031901126100c1576004356104f3611077565b6104fb61108d565b906001600160a01b037f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab167f0000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce8906040517f4583aea600000000000000000000000000000000000000000000000000000000908181526020968782806105a3888a8660048501916040919493606084019584526001600160a01b03809216602085015216910152565b0381875afa91821561016d5788968891600094610644575b5091836105cc926105d2959461115a565b906110d2565b60405191825260048201526001600160a01b039283166024820152939091166044840152829060649082905afa90811561016d57600091610617575b50604051908152f35b90508181813d831161063d575b61062e81836110a3565b810103126100c157518261060e565b503d610624565b9788919394508092503d8311610678575b61065f81836110a3565b810103126100c1579451879590919087906105cc6105bb565b503d610655565b346100c15760c03660031901126100c15761069861108d565b6001600160a01b03908160643516606435036100c15760843582811681036100c1576040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015260043560648201526064815260a081019080821067ffffffffffffffff831117610ba65761072291604052848416611310565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008082523060048301527f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab85166001600160a01b031660248301526020826044818789165afa91821561016d57600092610b72575b506004358210610a48575b50506040516301db50ff60e51b81526004356004820152600060248201528383166044820152837f0000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce81660648201523060848201524260a482015260208160c4816000887f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab165af190811561016d57600091610a16575b50809261084e600435836064358461115a565b8061092e575b50505060c460209260008560405196879586946301db50ff60e51b865260048601526024356024860152817f0000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce81660448601528160643516606486015216608484015260a43560a48401527f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab165af1801561016d576000906108fb575b602090604051908152f35b506020813d602011610926575b81610915602093836110a3565b810103126100c157602090516108f0565b3d9150610908565b9091935061093b8161152a565b918581166000526032602052604060002086606435166000526020526040600020928354906dffffffffffffffffffffffffffff8082168184160311610a005760209660c4956109c6936dffffffffffffffffffffffffffff808895168183160316906dffffffffffffffffffffffffffff19161790556109be826033546110c5565b6033556110d2565b916040519081527f6ee4d68c462d41c4639ae97a14beea115bfcdf71e4ef3c863ff588451a8f4a1d86888060643516941692a39285610854565b634e487b7160e01b600052601160045260246000fd5b90506020813d602011610a40575b81610a31602093836110a3565b810103126100c157518461083b565b3d9150610a24565b6040519081523060048201527f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab85166001600160a01b031660248201526020816044818789165afa90811561016d57600091610b3e575b50610b2f610ab5610b2192610b379419906110d2565b6040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201526001600160a01b037f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab891616602482015260448101919091529182906064820190565b03601f1981018352826110a3565b848416611310565b83806107a5565b90506020813d602011610b6a575b81610b59602093836110a3565b810103126100c15751610b2f610a9f565b3d9150610b4c565b9091506020813d602011610b9e575b81610b8e602093836110a3565b810103126100c15751908561079a565b3d9150610b81565b634e487b7160e01b600052604160045260246000fd5b346100c15760803660031901126100c157610bd5611061565b610bdd611077565b906044356064356001600160a01b0392836000541690604051809263521d4de960e01b825233600483015281602460209586935afa90811561016d57600091610fc5575b501561037c578416938460005260328252806040600020961695866000528252604060002090815460ff8160701c1660ff8260781c16918115610f25575b508115610e60575b60ff1615908115610e54575b50610e2a57610c84856033546110d2565b90602484610ca56dffffffffffffffffffffffffffff9485875416906110c5565b92604051928380926370a0823160e01b82523060048301527f0000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce8165afa801561016d578291600091610df9575b50106102e757603355610d038561152a565b168154906fffffffffffffffffffffffffffffffff8511610d8f57917f7870b01b22e7b2fbb2ced2043d7badd877232d56a4fe8e0986aa14b8675bef6195939185936fffff00000000000000000000000000007fffffffffffffffffffffffffffffffff0000000000000000000000000000000060409860801b169216171790558351928352820152a3005b6084846040519062461bcd60e51b82526004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f32382062697473000000000000000000000000000000000000000000000000006064820152fd5b809250868092503d8311610e23575b610e1281836110a3565b810103126100c1578190518a610cf1565b503d610e08565b60046040517f373f15fc000000000000000000000000000000000000000000000000000000008152fd5b60ff9150161588610c73565b90506040519063eb7aac5f60e01b82528860048301528482602481867f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab165afa91821561016d57600092610ef3575b5083547fffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffff16607883901b6fff00000000000000000000000000000016178455610c67565b60ff919250610f1790863d8811610f1e575b610f0f81836110a3565b8101906112f7565b9190610eaf565b503d610f05565b90506040519063eb7aac5f60e01b82528860048301528582602481877f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab165afa91821561016d57600092610fa6575b506eff00000000000000000000000000001916607082901b6eff00000000000000000000000000001617845589610c5f565b610fbe919250863d8811610f1e57610f0f81836110a3565b908a610f74565b610fdc9150833d85116101665761015881836110a3565b87610c21565b346100c15760403660031901126100c157608090610ffe611061565b611006611077565b906001600160a01b038091166000526032602052604060002091166000526020526040600020546dffffffffffffffffffffffffffff8116825260ff8160701c16602083015260ff8160781c166040830152821c6060820152f35b600435906001600160a01b03821682036100c157565b602435906001600160a01b03821682036100c157565b604435906001600160a01b03821682036100c157565b90601f8019910116810190811067ffffffffffffffff821117610ba657604052565b91908203918211610a0057565b91908201809211610a0057565b81810292918115918404141715610a0057565b60ff16604d8111610a0057600a0a90565b9261111e6111186111189361112495966110df565b916110f2565b906110df565b90670de0b6b3a76400009180830292830403610a00578115611144570490565b634e487b7160e01b600052601260045260246000fd5b9392919060009460006001600160a01b0380921681526020926032845260408220838216835284526111a560408320549660ff8860781c169060ff8960701c16908960801c90611103565b90816111b5575b50505050505050565b6040517f9525f3ab00000000000000000000000000000000000000000000000000000000815260048101929092526001600160a01b037f0000000000000000000000001a7e4e63778b4f12a199c062f3efdd288afcbce881166024840152166044820152918390839060649082907f00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab165afa9283156112d257819361129e575b505050808210611269575b808080806111ac565b6dffffffffffffffffffffffffffff92945090611285916110c5565b9216808311611296575b8080611260565b91503861128f565b9091809350813d83116112cb575b6112b681836110a3565b810103126112c8575051388080611255565b80fd5b503d6112ac565b50604051903d90823e3d90fd5b908160209103126100c1575180151581036100c15790565b908160209103126100c1575160ff811681036100c15790565b6001600160a01b03169060409081519082820167ffffffffffffffff9083811082821117610ba65784526020948584527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656486850152803b1561146c5760008381949282898195519301915af1903d1561145d573d9081116114495784516113b5949392916113a7601f8201601f19168901836110a3565b81528092873d92013e6114af565b805190816113c4575b50505050565b83806113d49383010191016112df565b156113e05780806113be565b60849250519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b602483634e487b7160e01b81526041600452fd5b506113b59291506060906114af565b60648686519062461bcd60e51b82526004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b909190156114bb575090565b8151156114cb5750805190602001fd5b6040519062461bcd60e51b82528160208060048301528251908160248401526000935b828510611511575050604492506000838284010152601f80199101168101030190fd5b84810182015186860160440152938101938593506114ee565b6dffffffffffffffffffffffffffff90818111611545571690565b608460405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203160448201527f31322062697473000000000000000000000000000000000000000000000000006064820152fdfea264697066735822122022ca3a821a690be3fb400f3b189482b2002792e1164053c207fba226dee60c6164736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005bc6bef80da563ebf6df6d6913513fa9a7ec89be00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab
-----Decoded View---------------
Arg [0] : _accessControlManager (address): 0x5bc6BEf80DA563EBf6Df6D6913513fa9A7ec89BE
Arg [1] : _transmuter (address): 0x00253582b2a3FE112feEC532221d9708c64cEFAb
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005bc6bef80da563ebf6df6d6913513fa9a7ec89be
Arg [1] : 00000000000000000000000000253582b2a3fe112feec532221d9708c64cefab
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.