More Info
Private Name Tags
ContractCreator
Latest 14 from a total of 14 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Harvest | 21556253 | 27 hrs ago | IN | 0 ETH | 0.00606968 | ||||
Harvest | 21438718 | 17 days ago | IN | 0 ETH | 0.03617484 | ||||
Harvest | 21404100 | 22 days ago | IN | 0 ETH | 0.00729346 | ||||
Harvest | 21396635 | 23 days ago | IN | 0 ETH | 0.0127086 | ||||
Harvest | 21388877 | 24 days ago | IN | 0 ETH | 0.02442971 | ||||
Harvest | 21379625 | 25 days ago | IN | 0 ETH | 0.02219144 | ||||
Harvest | 21371868 | 26 days ago | IN | 0 ETH | 0.01234314 | ||||
Harvest | 21336674 | 31 days ago | IN | 0 ETH | 0.02141839 | ||||
Update Limit Exp... | 21336656 | 31 days ago | IN | 0 ETH | 0.00146315 | ||||
Harvest | 21285366 | 38 days ago | IN | 0 ETH | 0.00787353 | ||||
Harvest | 21278256 | 39 days ago | IN | 0 ETH | 0.00985332 | ||||
Harvest | 21272497 | 40 days ago | IN | 0 ETH | 0.0142615 | ||||
Harvest | 21271020 | 40 days ago | IN | 0 ETH | 0.00781852 | ||||
Add Budget | 21121094 | 61 days ago | IN | 0 ETH | 0.00034822 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
GenericHarvester
Compiler Version
v0.8.23+commit.f704f362
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.23; import { SafeCast } from "oz/utils/math/SafeCast.sol"; import { SafeERC20 } from "oz/token/ERC20/utils/SafeERC20.sol"; import { IERC20 } from "oz/interfaces/IERC20.sol"; import { IERC20Metadata } from "oz/interfaces/IERC20Metadata.sol"; import { ITransmuter } from "interfaces/ITransmuter.sol"; import { IAgToken } from "interfaces/IAgToken.sol"; import { RouterSwapper } from "utils/src/RouterSwapper.sol"; import { IAccessControlManager } from "../utils/AccessControl.sol"; import "../utils/Constants.sol"; import "../utils/Errors.sol"; import { IERC3156FlashBorrower } from "oz/interfaces/IERC3156FlashBorrower.sol"; import { IERC3156FlashLender } from "oz/interfaces/IERC3156FlashLender.sol"; import { IERC4626 } from "interfaces/external/IERC4626.sol"; import { BaseHarvester, YieldBearingParams } from "./BaseHarvester.sol"; enum SwapType { VAULT, SWAP } /// @title GenericHarvester /// @author Angle Labs, Inc. /// @dev Generic contract for anyone to permissionlessly adjust the reserves of Angle Transmuter contract GenericHarvester is BaseHarvester, IERC3156FlashBorrower, RouterSwapper { using SafeCast for uint256; using SafeERC20 for IERC20; bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan"); /// @notice Angle stablecoin flashloan contract IERC3156FlashLender public immutable flashloan; /// @notice Budget of AGToken available for each users mapping(address => uint256) public budget; /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// INITIALIZATION //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ constructor( uint96 initialMaxSlippage, address initialTokenTransferAddress, address initialSwapRouter, IAgToken definitiveAgToken, ITransmuter definitiveTransmuter, IAccessControlManager definitiveAccessControlManager, IERC3156FlashLender definitiveFlashloan ) RouterSwapper(initialSwapRouter, initialTokenTransferAddress) BaseHarvester(initialMaxSlippage, definitiveAccessControlManager, definitiveAgToken, definitiveTransmuter) { if (address(definitiveFlashloan) == address(0)) revert ZeroAddress(); flashloan = definitiveFlashloan; IERC20(agToken).safeApprove(address(definitiveFlashloan), type(uint256).max); } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// BUDGET HANDLING //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /** * @notice Add budget to be spent by the receiver during the flashloan * @param amount amount of AGToken to add to the budget * @param receiver address of the receiver */ function addBudget(uint256 amount, address receiver) public virtual { budget[receiver] += amount; IERC20(agToken).safeTransferFrom(msg.sender, address(this), amount); } /** * @notice Remove budget from the owner and send it to the receiver * @param amount amount of AGToken to remove from the budget * @param receiver address of the receiver */ function removeBudget(uint256 amount, address receiver) public virtual { budget[msg.sender] -= amount; // Will revert if not enough funds IERC20(agToken).safeTransfer(receiver, amount); } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HARVEST //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Invests or divests from the yield asset associated to `yieldBearingAsset` based on the current exposure /// to this yieldBearingAsset /// @dev This transaction either reduces the exposure to `yieldBearingAsset` in the Transmuter or frees up /// some yieldBearingAsset that can then be used for people looking to burn deposit tokens /// @dev Due to potential transaction fees within the Transmuter, this function doesn't exactly bring /// `yieldBearingAsset` to the target exposure /// @dev scale is a number between 0 and 1e9 that represents the proportion of the agToken to harvest, /// it is used to lower the amount of the asset to harvest for example to have a lower slippage function harvest(address yieldBearingAsset, uint256 scale, bytes calldata extraData) public virtual { if (scale > 1e9) revert InvalidParam(); YieldBearingParams memory yieldBearingInfo = yieldBearingData[yieldBearingAsset]; (uint8 increase, uint256 amount) = _computeRebalanceAmount(yieldBearingAsset, yieldBearingInfo); amount = (amount * scale) / 1e9; if (amount == 0) revert ZeroAmount(); (SwapType swapType, bytes memory data) = abi.decode(extraData, (SwapType, bytes)); try transmuter.updateOracle(yieldBearingInfo.asset) {} catch {} adjustYieldExposure( amount, increase, yieldBearingAsset, yieldBearingInfo.asset, (amount * (1e9 - maxSlippage)) / 1e9, swapType, data ); } /// @notice Burns `amountStablecoins` for one yieldBearing asset, swap for asset then mints deposit tokens /// from the proceeds of the swap. /// @dev If `increase` is 1, then the system tries to increase its exposure to the yield bearing asset which means /// burning agToken for the deposit asset, swapping for the yield bearing asset, then minting the agToken /// @dev This function reverts if the second agToken mint gives less than `minAmountOut` of ag tokens /// @dev This function reverts if the swap slippage is higher than `maxSlippage` function adjustYieldExposure( uint256 amountStablecoins, uint8 increase, address yieldBearingAsset, address asset, uint256 minAmountOut, SwapType swapType, bytes memory extraData ) public virtual { flashloan.flashLoan( IERC3156FlashBorrower(address(this)), address(agToken), amountStablecoins, abi.encode(msg.sender, increase, yieldBearingAsset, asset, minAmountOut, swapType, extraData) ); } /// @inheritdoc IERC3156FlashBorrower function onFlashLoan( address initiator, address, uint256 amount, uint256 fee, bytes calldata data ) public virtual returns (bytes32) { if (msg.sender != address(flashloan) || initiator != address(this) || fee != 0) revert NotTrusted(); address sender; uint256 typeAction; uint256 minAmountOut; SwapType swapType; bytes memory callData; address tokenOut; address tokenIn; { address yieldBearingAsset; address asset; (sender, typeAction, yieldBearingAsset, asset, minAmountOut, swapType, callData) = abi.decode( data, (address, uint256, address, address, uint256, SwapType, bytes) ); if (typeAction == 1) { // Increase yield exposure action: we bring in the yield bearing asset tokenOut = yieldBearingAsset; tokenIn = asset; } else { // Decrease yield exposure action: we bring in the deposit asset tokenIn = yieldBearingAsset; tokenOut = asset; } } uint256 amountOut = transmuter.swapExactInput( amount, 0, address(agToken), tokenIn, address(this), block.timestamp ); // Swap to tokenIn amountOut = _swapToTokenOut(typeAction, tokenIn, tokenOut, amountOut, swapType, callData); _adjustAllowance(tokenOut, address(transmuter), amountOut); uint256 amountStableOut = transmuter.swapExactInput( amountOut, minAmountOut, tokenOut, address(agToken), address(this), block.timestamp ); if (amount > amountStableOut) { budget[sender] -= amount - amountStableOut; // Will revert if not enough funds } return CALLBACK_SUCCESS; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SETTERS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /** * @notice Set the token transfer address * @param newTokenTransferAddress address of the token transfer contract */ function setTokenTransferAddress(address newTokenTransferAddress) public override onlyGuardian { super.setTokenTransferAddress(newTokenTransferAddress); } /** * @notice Set the swap router * @param newSwapRouter address of the swap router */ function setSwapRouter(address newSwapRouter) public override onlyGuardian { super.setSwapRouter(newSwapRouter); } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// INTERNALS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ function _swapToTokenOut( uint256 typeAction, address tokenIn, address tokenOut, uint256 amount, SwapType swapType, bytes memory callData ) internal returns (uint256 amountOut) { if (swapType == SwapType.SWAP) { amountOut = _swapToTokenOutSwap(tokenIn, tokenOut, amount, callData); } else if (swapType == SwapType.VAULT) { amountOut = _swapToTokenOutVault(typeAction, tokenIn, tokenOut, amount); } } /** * @notice Swap token using the router/aggregator * @param tokenIn address of the token to swap * @param tokenOut address of the token to receive * @param amount amount of token to swap * @param callData bytes to call the router/aggregator */ function _swapToTokenOutSwap( address tokenIn, address tokenOut, uint256 amount, bytes memory callData ) internal returns (uint256) { uint256 balance = IERC20(tokenOut).balanceOf(address(this)); address[] memory tokens = new address[](1); tokens[0] = tokenIn; bytes[] memory callDatas = new bytes[](1); callDatas[0] = callData; uint256[] memory amounts = new uint256[](1); amounts[0] = amount; _swap(tokens, callDatas, amounts); return IERC20(tokenOut).balanceOf(address(this)) - balance; } /** * @dev Deposit or redeem the vault asset * @param typeAction 1 for deposit, 2 for redeem * @param tokenIn address of the token to swap * @param tokenOut address of the token to receive * @param amount amount of token to swap */ function _swapToTokenOutVault( uint256 typeAction, address tokenIn, address tokenOut, uint256 amount ) internal returns (uint256 amountOut) { if (typeAction == 1) { // Granting allowance with the yieldBearingAsset for the vault asset _adjustAllowance(tokenIn, tokenOut, amount); amountOut = IERC4626(tokenOut).deposit(amount, address(this)); } else amountOut = IERC4626(tokenIn).redeem(amount, address(this), address(this)); } }
// 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: 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 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: 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; 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); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; import { SafeERC20, IERC20 } from "oz/token/ERC20/utils/SafeERC20.sol"; /// @title Swapper /// @author Angle Labs, Inc. /// @dev Abstract contract for swapping tokens using a router/aggregator abstract contract RouterSwapper { using SafeERC20 for IERC20; /*////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ error SwapError(); error ZeroAddress(); /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /** * @notice Event emitted when the swap router is updated */ event SwapRouterUpdated(address newSwapRouter); /** * @notice Event emitted when the token proxy is updated */ event TokenTransferAddressUpdated(address newTokenTransferAddress); /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ modifier noZeroAddress(address targetAddress) { if (targetAddress == address(0)) { revert ZeroAddress(); } _; } /*////////////////////////////////////////////////////////////// MUTABLE VARIABLES //////////////////////////////////////////////////////////////*/ /** * @notice address of the router/aggregator */ address public swapRouter; /** * @notice address to approve to transfer tokens to */ address public tokenTransferAddress; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address initialSwapRouter, address initialTokenTransferAddress) { swapRouter = initialSwapRouter; tokenTransferAddress = initialTokenTransferAddress; } /*////////////////////////////////////////////////////////////// ADMIN FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Set the router/aggregator address * @param newSwapRouter address of the new router/aggregator */ function setSwapRouter(address newSwapRouter) public virtual noZeroAddress(newSwapRouter) { swapRouter = newSwapRouter; emit SwapRouterUpdated(newSwapRouter); } /** * @notice Set the token transfer address * @param newTokenTransferAddress address of the new token transfer address */ function setTokenTransferAddress( address newTokenTransferAddress ) public virtual noZeroAddress(newTokenTransferAddress) { tokenTransferAddress = newTokenTransferAddress; emit TokenTransferAddressUpdated(newTokenTransferAddress); } /*////////////////////////////////////////////////////////////// SWAP FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Approve the router/aggregator to spend the token if needed * @param token address of the token to approve * @param spender address of the router/aggregator * @param amount amount to approve */ function _approveTokenIfNeeded(address token, address spender, uint256 amount) internal { uint256 allowance = IERC20(token).allowance(address(this), spender); if (allowance < amount) { IERC20(token).safeIncreaseAllowance(spender, amount - allowance); } } /** * @notice Perform the swap using the router/aggregator * @param callData bytes to call the router/aggregator */ function _performRouterSwap(bytes memory callData) internal { (bool success, bytes memory retData) = swapRouter.call(callData); if (!success) { if (retData.length != 0) { assembly { revert(add(32, retData), mload(retData)) } } revert SwapError(); } } /** * @notice Swap tokens using the router/aggregator * @param tokens array of tokens to swap * @param callDatas array of bytes to call the router/aggregator * @param amounts array of amounts to swap */ function _swapCalldata(address[] calldata tokens, bytes[] calldata callDatas, uint256[] calldata amounts) internal { uint256 length = tokens.length; for (uint256 i; i < length; ++i) { _approveTokenIfNeeded(tokens[i], tokenTransferAddress, amounts[i]); _performRouterSwap(callDatas[i]); } } /** * @notice Swap tokens using the router/aggregator * @param tokens array of tokens to swap * @param callDatas array of bytes to call the router/aggregator * @param amounts array of amounts to swap */ function _swap(address[] memory tokens, bytes[] memory callDatas, uint256[] memory amounts) internal { uint256 length = tokens.length; for (uint256 i; i < length; ++i) { _approveTokenIfNeeded(tokens[i], tokenTransferAddress, amounts[i]); _performRouterSwap(callDatas[i]); } } }
// 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 BPS = 1e14; 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); address constant XEVT = 0x3Ee320c9F73a84D1717557af00695A34b26d1F1d; address constant USDM = 0x59D9356E565Ab3A36dD77763Fc0d87fEaf85508C; address constant STEAK_USDC = 0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB; address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; address constant EURC = 0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c; address constant ONEINCH_ROUTER = 0x111111125421cA6dc452d289314280a0f8842A65;
// 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 NotTrustedOrGuardian(); error NotWhitelisted(); error OneInchSwapFailed(); error OracleUpdateFailed(); error Paused(); error ReentrantCall(); error RemoveFacetAddressMustBeZeroAddress(address _facetAddress); error TooBigAmountIn(); error TooLate(); error TooSmallAmountOut(); error ZeroAddress(); error ZeroAmount(); error SwapError(); error SlippageTooHigh(); error InsufficientFunds();
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (interfaces/IERC3156FlashBorrower.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC3156 FlashBorrower, as defined in * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. * * _Available since v4.1._ */ interface IERC3156FlashBorrower { /** * @dev Receive a flash loan. * @param initiator The initiator of the loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @param fee The additional amount of tokens to repay. * @param data Arbitrary data structure, intended to contain user-defined parameters. * @return The keccak256 hash of "IERC3156FlashBorrower.onFlashLoan" */ function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC3156FlashLender.sol) pragma solidity ^0.8.0; import "./IERC3156FlashBorrower.sol"; /** * @dev Interface of the ERC3156 FlashLender, as defined in * https://eips.ethereum.org/EIPS/eip-3156[ERC-3156]. * * _Available since v4.1._ */ interface IERC3156FlashLender { /** * @dev The amount of currency available to be lended. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan(address token) external view returns (uint256); /** * @dev The fee to be charged for a given loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee(address token, uint256 amount) external view returns (uint256); /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param data Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external returns (bool); }
// SPDX-License-Identifier: GPL-3.0 // OpenZeppelin Contracts (last updated v4.7.0) (interfaces/IERC4626.sol) pragma solidity >=0.5.0; /// @notice ERC4626 interface /// @author OpenZeppelin /// @dev In this implementation, the interface only contains the functions that the IERC4626 interface adds on top of /// the IERC20 interface interface IERC4626 { /** * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. * * - MUST be an ERC-20 token contract. * - MUST NOT revert. */ function asset() external view returns (address assetTokenAddress); /** * @dev Returns the total amount of the underlying asset that is “managed” by Vault. * * - SHOULD include any compounding that occurs from yield. * - MUST be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT revert. */ function totalAssets() external view returns (uint256 totalManagedAssets); /** * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, * through a deposit call. * * - MUST return a limited value if receiver is subject to some deposit limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. * - MUST NOT revert. */ function maxDeposit(address receiver) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given * current on-chain conditions. * * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called * in the same transaction. * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the * deposit would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewDeposit(uint256 assets) external view returns (uint256 shares); /** * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * deposit execution, and are accounted for during deposit. * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function deposit(uint256 assets, address receiver) external returns (uint256 shares); /** * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. * - MUST return a limited value if receiver is subject to some mint limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. * - MUST NOT revert. */ function maxMint(address receiver) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given * current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the * same transaction. * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint * would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by minting. */ function previewMint(uint256 shares) external view returns (uint256 assets); /** * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint * execution, and are accounted for during mint. * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function mint(uint256 shares, address receiver) external returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the * Vault, through a withdraw call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST NOT revert. */ function maxWithdraw(address owner) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, * given current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if * called * in the same transaction. * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though * the withdrawal would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewWithdraw(uint256 assets) external view returns (uint256 shares); /** * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * withdraw execution, and are accounted for during withdraw. * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); /** * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, * through a redeem call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. * - MUST NOT revert. */ function maxRedeem(address owner) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, * given current on-chain conditions. * * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the * same transaction. * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the * redemption would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by redeeming. */ function previewRedeem(uint256 shares) external view returns (uint256 assets); /** * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * redeem execution, and are accounted for during redeem. * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { AccessControl, IAccessControlManager } from "../utils/AccessControl.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { ITransmuter } from "../interfaces/ITransmuter.sol"; import { IAgToken } from "../interfaces/IAgToken.sol"; import "../utils/Errors.sol"; import "../interfaces/IHarvester.sol"; struct YieldBearingParams { // Address of the asset used to mint the yield bearing asset address asset; // Target exposure to the collateral yield bearing asset used uint64 targetExposure; // Maximum exposure within the Transmuter to the deposit asset uint64 maxExposure; // Minimum exposure within the Transmuter to the deposit asset uint64 minExposure; // Whether limit exposures should be overriden or read onchain through the Transmuter // This value should be 1 to override exposures or 2 if these shouldn't be overriden uint64 overrideExposures; } /// @title BaseHarvester /// @author Angle Labs, Inc. /// @dev Abstract contract for a harvester that aims at rebalancing a Transmuter abstract contract BaseHarvester is IHarvester, AccessControl { using SafeERC20 for IERC20; /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /** * @notice Checks whether the `msg.sender` is trusted to update * target exposure and do others non critical operations */ modifier onlyTrusted() { if (!isTrusted[msg.sender]) revert NotTrusted(); _; } /** * @notice Checks whether the `msg.sender` is trusted or guardian to update * target exposure and do others non critical operations */ modifier onlyTrustedOrGuardian() { if (!isTrusted[msg.sender] && !accessControlManager.isGovernorOrGuardian(msg.sender)) revert NotTrustedOrGuardian(); _; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Reference to the `transmuter` implementation this contract aims at rebalancing ITransmuter public immutable transmuter; /// @notice AgToken handled by the `transmuter` of interest IAgToken public immutable agToken; /// @notice Max slippage when dealing with the Transmuter uint96 public maxSlippage; /// @notice Data associated to a yield bearing asset mapping(address => YieldBearingParams) public yieldBearingData; /// @notice trusted addresses that can update target exposure and do others non critical operations mapping(address => bool) public isTrusted; /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ constructor( uint96 initialMaxSlippage, IAccessControlManager definitiveAccessControlManager, IAgToken definitiveAgToken, ITransmuter definitiveTransmuter ) { _setMaxSlippage(initialMaxSlippage); accessControlManager = definitiveAccessControlManager; agToken = definitiveAgToken; transmuter = definitiveTransmuter; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GUARDIAN FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /** * @notice Set the yieldBearingAsset data * @param yieldBearingAsset address of the yieldBearingAsset * @param asset address of the asset * @param targetExposure target exposure to the yieldBearingAsset asset used * @param minExposure minimum exposure within the Transmuter to the asset * @param maxExposure maximum exposure within the Transmuter to the asset * @param overrideExposures whether limit exposures should be overriden or read onchain through the Transmuter */ function setYieldBearingAssetData( address yieldBearingAsset, address asset, uint64 targetExposure, uint64 minExposure, uint64 maxExposure, uint64 overrideExposures ) external onlyGuardian { _setYieldBearingAssetData( yieldBearingAsset, asset, targetExposure, minExposure, maxExposure, overrideExposures ); } /** * @notice Set the limit exposures to the asset linked to the yield bearing asset * @param yieldBearingAsset address of the yield bearing asset */ function updateLimitExposuresYieldAsset(address yieldBearingAsset) public virtual { YieldBearingParams storage yieldBearingInfo = yieldBearingData[yieldBearingAsset]; if (yieldBearingInfo.overrideExposures == 2) _updateLimitExposuresYieldAsset(yieldBearingInfo.asset, yieldBearingInfo); } /** * @notice Set the max allowed slippage * @param newMaxSlippage new max allowed slippage */ function setMaxSlippage(uint96 newMaxSlippage) external onlyGuardian { _setMaxSlippage(newMaxSlippage); } /** * @notice Toggle the trusted status of an address * @param trusted address to toggle the trusted status */ function toggleTrusted(address trusted) external onlyGuardian { isTrusted[trusted] = !isTrusted[trusted]; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TRUSTED FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /** * @notice Set the target exposure of a yield bearing asset * @param yieldBearingAsset address of the yield bearing asset * @param targetExposure target exposure to the yield bearing asset used */ function setTargetExposure(address yieldBearingAsset, uint64 targetExposure) external onlyTrustedOrGuardian { yieldBearingData[yieldBearingAsset].targetExposure = targetExposure; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /** * @notice Compute the amount needed to rebalance the Transmuter * @param yieldBearingAsset address of the yield bearing asset * @return increase whether the exposure should be increased * @return amount amount to be rebalanced */ function computeRebalanceAmount(address yieldBearingAsset) external view returns (uint8 increase, uint256 amount) { return _computeRebalanceAmount(yieldBearingAsset, yieldBearingData[yieldBearingAsset]); } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ function _computeRebalanceAmount( address yieldBearingAsset, YieldBearingParams memory yieldBearingInfo ) internal view returns (uint8 increase, uint256 amount) { (uint256 stablecoinsFromYieldBearingAsset, uint256 stablecoinsIssued) = transmuter.getIssuedByCollateral( yieldBearingAsset ); (uint256 stablecoinsFromAsset, ) = transmuter.getIssuedByCollateral(yieldBearingInfo.asset); uint256 targetExposureScaled = yieldBearingInfo.targetExposure * stablecoinsIssued; if (stablecoinsFromYieldBearingAsset * 1e9 > targetExposureScaled) { // Need to decrease exposure to yield bearing asset amount = stablecoinsFromYieldBearingAsset - targetExposureScaled / 1e9; uint256 maxValueScaled = yieldBearingInfo.maxExposure * stablecoinsIssued; // These checks assume that there are no transaction fees on the stablecoin->collateral conversion and so // it's still possible that exposure goes above the max exposure in some rare cases if (stablecoinsFromAsset * 1e9 > maxValueScaled) amount = 0; else if ((stablecoinsFromAsset + amount) * 1e9 > maxValueScaled) amount = maxValueScaled / 1e9 - stablecoinsFromAsset; } else { // In this case, exposure after the operation might remain slightly below the targetExposure as less // collateral may be obtained by burning stablecoins for the yield asset and unwrapping it increase = 1; amount = targetExposureScaled / 1e9 - stablecoinsFromYieldBearingAsset; uint256 minValueScaled = yieldBearingInfo.minExposure * stablecoinsIssued; if (stablecoinsFromAsset * 1e9 < minValueScaled) amount = 0; else if (stablecoinsFromAsset * 1e9 < minValueScaled + amount * 1e9) amount = stablecoinsFromAsset - minValueScaled / 1e9; } } function _setYieldBearingAssetData( address yieldBearingAsset, address asset, uint64 targetExposure, uint64 minExposure, uint64 maxExposure, uint64 overrideExposures ) internal virtual { YieldBearingParams storage yieldBearingInfo = yieldBearingData[yieldBearingAsset]; yieldBearingInfo.asset = asset; if (targetExposure >= 1e9) revert InvalidParam(); yieldBearingInfo.targetExposure = targetExposure; yieldBearingInfo.overrideExposures = overrideExposures; if (overrideExposures == 1) { if (maxExposure >= 1e9 || minExposure >= maxExposure) revert InvalidParam(); yieldBearingInfo.maxExposure = maxExposure; yieldBearingInfo.minExposure = minExposure; } else { yieldBearingInfo.overrideExposures = 2; _updateLimitExposuresYieldAsset(asset, yieldBearingInfo); } } function _updateLimitExposuresYieldAsset( address asset, YieldBearingParams storage yieldBearingInfo ) internal virtual { uint64[] memory xFeeMint; (xFeeMint, ) = transmuter.getCollateralMintFees(asset); uint256 length = xFeeMint.length; if (length <= 1) yieldBearingInfo.maxExposure = 1e9; else yieldBearingInfo.maxExposure = xFeeMint[length - 2]; uint64[] memory xFeeBurn; (xFeeBurn, ) = transmuter.getCollateralBurnFees(asset); length = xFeeBurn.length; if (length <= 1) yieldBearingInfo.minExposure = 0; else yieldBearingInfo.minExposure = xFeeBurn[length - 2]; } function _setMaxSlippage(uint96 newMaxSlippage) internal virtual { if (newMaxSlippage > 1e9) revert InvalidParam(); maxSlippage = newMaxSlippage; } function _scaleAmountBasedOnDecimals( uint256 decimalsTokenIn, uint256 decimalsTokenOut, uint256 amountIn, bool assetIn ) internal pure returns (uint256) { if (decimalsTokenIn > decimalsTokenOut) { if (assetIn) { amountIn /= 10 ** (decimalsTokenIn - decimalsTokenOut); } else { amountIn *= 10 ** (decimalsTokenIn - decimalsTokenOut); } } else if (decimalsTokenIn < decimalsTokenOut) { if (assetIn) { amountIn *= 10 ** (decimalsTokenOut - decimalsTokenIn); } else { amountIn /= 10 ** (decimalsTokenOut - decimalsTokenIn); } } return amountIn; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// HELPER //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ function _adjustAllowance(address token, address sender, uint256 amountIn) internal { uint256 allowance = IERC20(token).allowance(address(this), sender); if (allowance < amountIn) IERC20(token).safeIncreaseAllowance(sender, type(uint256).max - allowance); } }
// 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/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 // 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 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, bytes memory hyperparameters ); /// @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); /// @notice Returns the stablecoin cap for `collateral` function getStablecoinCap(address collateral) external view returns (uint256); }
// 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; /// @notice Update oracle data for a given `collateral` function updateOracle(address collateral) 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; /// @notice Sets the stablecoin cap that can be issued from a `collateral` function setStablecoinCap(address collateral, uint256 stablecoinCap) 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: GPL-3.0 pragma solidity >=0.5.0; interface IHarvester { function setYieldBearingAssetData( address yieldBearingAsset, address stablecoin, uint64 targetExposure, uint64 minExposureYieldAsset, uint64 maxExposureYieldAsset, uint64 overrideExposures ) external; function updateLimitExposuresYieldAsset(address yieldBearingAsset) external; function setMaxSlippage(uint96 newMaxSlippage) external; function harvest(address yieldBearingAsset, uint256 scale, bytes calldata extraData) external; }
// 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, MAX, MORPHO_ORACLE } 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 uint256 stablecoinCap; // Cap on the amount of stablecoins that can be issued from this collateral } 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 or to run keeper jobs on oracles mapping(WhitelistType => mapping(address => uint256)) isWhitelistedForType; // Whether an address is whitelisted for a specific whitelist type }
{ "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/", "utils/=lib/utils/", "@chainlink/=lib/borrow-contracts/node_modules/@chainlink/", "@ensdomains/=lib/borrow-contracts/node_modules/@ensdomains/", "@prb/test/=lib/prb-math/lib/prb-test/src/", "@uniswap/=lib/borrow-contracts/node_modules/@uniswap/", "borrow-contracts/=lib/borrow-contracts/", "lz/=lib/utils/lib/solidity-examples/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-examples/=lib/utils/lib/solidity-examples/contracts/", "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": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint96","name":"initialMaxSlippage","type":"uint96"},{"internalType":"address","name":"initialTokenTransferAddress","type":"address"},{"internalType":"address","name":"initialSwapRouter","type":"address"},{"internalType":"contract IAgToken","name":"definitiveAgToken","type":"address"},{"internalType":"contract ITransmuter","name":"definitiveTransmuter","type":"address"},{"internalType":"contract IAccessControlManager","name":"definitiveAccessControlManager","type":"address"},{"internalType":"contract IERC3156FlashLender","name":"definitiveFlashloan","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidParam","type":"error"},{"inputs":[],"name":"NotGovernorOrGuardian","type":"error"},{"inputs":[],"name":"NotTrusted","type":"error"},{"inputs":[],"name":"NotTrustedOrGuardian","type":"error"},{"inputs":[],"name":"SwapError","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSwapRouter","type":"address"}],"name":"SwapRouterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTokenTransferAddress","type":"address"}],"name":"TokenTransferAddressUpdated","type":"event"},{"inputs":[],"name":"CALLBACK_SUCCESS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accessControlManager","outputs":[{"internalType":"contract IAccessControlManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"addBudget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountStablecoins","type":"uint256"},{"internalType":"uint8","name":"increase","type":"uint8"},{"internalType":"address","name":"yieldBearingAsset","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"enum SwapType","name":"swapType","type":"uint8"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"adjustYieldExposure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"agToken","outputs":[{"internalType":"contract IAgToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"budget","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"yieldBearingAsset","type":"address"}],"name":"computeRebalanceAmount","outputs":[{"internalType":"uint8","name":"increase","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flashloan","outputs":[{"internalType":"contract IERC3156FlashLender","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"yieldBearingAsset","type":"address"},{"internalType":"uint256","name":"scale","type":"uint256"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"harvest","outputs":[],"stateMutability":"nonpayable","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":"","type":"address"}],"name":"isTrusted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSlippage","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onFlashLoan","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"removeBudget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"newMaxSlippage","type":"uint96"}],"name":"setMaxSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSwapRouter","type":"address"}],"name":"setSwapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"yieldBearingAsset","type":"address"},{"internalType":"uint64","name":"targetExposure","type":"uint64"}],"name":"setTargetExposure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTokenTransferAddress","type":"address"}],"name":"setTokenTransferAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"yieldBearingAsset","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint64","name":"targetExposure","type":"uint64"},{"internalType":"uint64","name":"minExposure","type":"uint64"},{"internalType":"uint64","name":"maxExposure","type":"uint64"},{"internalType":"uint64","name":"overrideExposures","type":"uint64"}],"name":"setYieldBearingAssetData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"trusted","type":"address"}],"name":"toggleTrusted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenTransferAddress","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":[{"internalType":"address","name":"yieldBearingAsset","type":"address"}],"name":"updateLimitExposuresYieldAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"yieldBearingData","outputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint64","name":"targetExposure","type":"uint64"},{"internalType":"uint64","name":"maxExposure","type":"uint64"},{"internalType":"uint64","name":"minExposure","type":"uint64"},{"internalType":"uint64","name":"overrideExposures","type":"uint64"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b506040516200336f3803806200336f833981016040819052620000349162000503565b8486888487876200004584620000e0565b600080546001600160a01b03199081166001600160a01b039586161790915591831660a052821660805260358054821695831695909517909455603680549094169281169290921790925582169050620000b25760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0380821660c05260a051620000d391168260001962000131565b5050505050505062000670565b633b9aca00816001600160601b031611156200010f57604051633494a40d60e21b815260040160405180910390fd5b603280546001600160601b0319166001600160601b0392909216919091179055565b801580620001af5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801562000187573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ad9190620005b9565b155b620002275760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084015b60405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091526200027f9185916200028416565b505050565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620002d3906001600160a01b03851690849062000355565b8051909150156200027f5780806020019051810190620002f49190620005d3565b6200027f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200021e565b606062000366848460008562000370565b90505b9392505050565b606082471015620003d35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200021e565b6001600160a01b0385163b6200042c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200021e565b600080866001600160a01b031685876040516200044a91906200061d565b60006040518083038185875af1925050503d806000811462000489576040519150601f19603f3d011682016040523d82523d6000602084013e6200048e565b606091505b509092509050620004a1828286620004ac565b979650505050505050565b60608315620004bd57508162000369565b825115620004ce5782518084602001fd5b8160405162461bcd60e51b81526004016200021e91906200063b565b6001600160a01b03811681146200050057600080fd5b50565b600080600080600080600060e0888a0312156200051f57600080fd5b87516001600160601b03811681146200053757600080fd5b60208901519097506200054a81620004ea565b60408901519096506200055d81620004ea565b60608901519095506200057081620004ea565b60808901519094506200058381620004ea565b60a08901519093506200059681620004ea565b60c0890151909250620005a981620004ea565b8091505092959891949750929550565b600060208284031215620005cc57600080fd5b5051919050565b600060208284031215620005e657600080fd5b815180151581146200036957600080fd5b60005b8381101562000614578181015183820152602001620005fa565b50506000910152565b6000825162000631818460208701620005f7565b9190910192915050565b60208152600082518060208401526200065c816040850160208701620005f7565b601f01601f19169190910160400192915050565b60805160a05160c051612c6662000709600039600081816101cd0152818161061e0152610bca0152600081816104f3015281816105e5015281816107030152818161081a01528181610bfa0152610e9c0152600081816102ba01528181610741015281816107c801528181610851015281816110ee0152818161146b015281816114ff0152818161172201526118490152612c666000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806396d64879116100ee578063c5e6d5ea11610097578063e234b90311610071578063e234b903146104b5578063e43581b8146104c8578063edf0ef03146104db578063ee565a63146104ee57600080fd5b8063c5e6d5ea146103e0578063c9c6667414610482578063d2d0ec10146104a257600080fd5b80639ae78486116100c85780639ae78486146103a7578063b4a0bdf3146103ba578063c31c9c07146103cd57600080fd5b806396d648791461035e5780639786909c146103815780639a49e83d1461039457600080fd5b80635a7cb38f1161015b5780637ee84349116101355780637ee84349146102dc5780638195001d146102ef5780638237e538146103025780638c04166f1461032957600080fd5b80635a7cb38f14610276578063641bd503146102895780637239d2b9146102b557600080fd5b806323e30c8b1161018c57806323e30c8b1461021f5780634127365714610240578063521d4de91461025357600080fd5b8063184b949b146101b35780631b89b61a146101c8578063212c8fb11461020c575b600080fd5b6101c66101c1366004612416565b610515565b005b6101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c661021a366004612459565b6105aa565b61023261022d3660046124d2565b610611565b604051908152602001610203565b6101c661024e36600461254e565b610939565b61026661026136600461254e565b6109cb565b6040519015158152602001610203565b6036546101ef906001600160a01b031681565b61029c61029736600461254e565b610a41565b6040805160ff9093168352602083019190915201610203565b6101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6101c66102ea36600461254e565b610acc565b6101c66102fd36600461254e565b610b7e565b6102327f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd981565b603254610341906bffffffffffffffffffffffff1681565b6040516bffffffffffffffffffffffff9091168152602001610203565b61026661036c36600461254e565b60346020526000908152604090205460ff1681565b6101c661038f366004612636565b610bc8565b6101c66103a23660046126eb565b610cb2565b6101c66103b536600461276d565b610d51565b6000546101ef906001600160a01b031681565b6035546101ef906001600160a01b031681565b6104416103ee36600461254e565b603360205260009081526040902080546001909101546001600160a01b0382169167ffffffffffffffff600160a01b90910481169180821691680100000000000000008204811691600160801b90041685565b604080516001600160a01b03909616865267ffffffffffffffff9485166020870152928416928501929092528216606084015216608082015260a001610203565b61023261049036600461254e565b60376020526000908152604090205481565b6101c66104b0366004612459565b610e6a565b6101c66104c336600461254e565b610ec3565b6102666104d636600461254e565b610f55565b6101c66104e936600461279b565b610fa1565b6101ef7f000000000000000000000000000000000000000000000000000000000000000081565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa15801561055d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058191906127f7565b61059e57604051632678482f60e21b815260040160405180910390fd5b6105a7816111a5565b50565b6001600160a01b038116600090815260376020526040812080548492906105d290849061282f565b9091555061060d90506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333085611204565b5050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614158061065457506001600160a01b0387163014155b8061065e57508315155b15610695576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080806060818080806106ac8b8d018d612842565b959e50939c509a50919850919650909250905060018890036106d3578193508092506106da565b8192508093505b50506040516301db50ff60e51b8152600481018d90526000602482018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116604484015283811660648401523060848401524260a484015290917f000000000000000000000000000000000000000000000000000000000000000090911690633b6a1fe09060c4016020604051808303816000875af115801561078c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b0919061287f565b90506107c08783858489896112bb565b90506107ed837f000000000000000000000000000000000000000000000000000000000000000083611319565b6040516301db50ff60e51b815260048101829052602481018790526001600160a01b0384811660448301527f0000000000000000000000000000000000000000000000000000000000000000811660648301523060848301524260a48301526000917f000000000000000000000000000000000000000000000000000000000000000090911690633b6a1fe09060c4016020604051808303816000875af115801561089c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c0919061287f565b9050808e1115610902576108d4818f612898565b6001600160a01b038a16600090815260376020526040812080549091906108fc908490612898565b90915550505b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd999505050505050505050505b9695505050505050565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a591906127f7565b6109c257604051632678482f60e21b815260040160405180910390fd5b6105a7816113b8565b6000805460405163521d4de960e01b81526001600160a01b0384811660048301529091169063521d4de9906024015b602060405180830381865afa158015610a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3b91906127f7565b92915050565b6001600160a01b038181166000908152603360209081526040808320815160a08101835281549586168152600160a01b90950467ffffffffffffffff90811693860193909352600101548083169185019190915268010000000000000000810482166060850152600160801b9004166080830152908190610ac3908490611443565b91509150915091565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3891906127f7565b610b5557604051632678482f60e21b815260040160405180910390fd5b6001600160a01b03166000908152603460205260409020805460ff19811660ff90911615179055565b6001600160a01b03811660009081526033602052604090206001810154600160801b900467ffffffffffffffff1660020361060d57805461060d906001600160a01b0316826116e7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635cffe9de307f00000000000000000000000000000000000000000000000000000000000000008a338b8b8b8b8b8b604051602001610c379796959493929190612911565b6040516020818303038152906040526040518563ffffffff1660e01b8152600401610c659493929190612984565b6020604051808303816000875af1158015610c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca891906127f7565b5050505050505050565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610cfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1e91906127f7565b610d3b57604051632678482f60e21b815260040160405180910390fd5b610d4986868686868661194e565b505050505050565b3360009081526034602052604090205460ff16158015610dda575060005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610db4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd891906127f7565b155b15610e11576040517f0dcc030f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b039091166000908152603360205260409020805467ffffffffffffffff909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b3360009081526037602052604081208054849290610e89908490612898565b9091555061060d90506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168284611b1e565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f91906127f7565b610f4c57604051632678482f60e21b815260040160405180910390fd5b6105a781611b6c565b600080546040517fe43581b80000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529091169063e43581b8906024016109fa565b633b9aca00831115610fc657604051633494a40d60e21b815260040160405180910390fd5b6001600160a01b038481166000908152603360209081526040808320815160a08101835281549586168152600160a01b90950467ffffffffffffffff90811693860193909352600101548083169185019190915268010000000000000000810482166060850152600160801b9004166080830152806110458784611443565b9092509050633b9aca0061105987836129b6565b61106391906129cd565b90508060000361109f576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806110ae868801886129ef565b86516040517f1cb44dfc0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529294509092507f00000000000000000000000000000000000000000000000000000000000000001690631cb44dfc90602401600060405180830381600087803b15801561113257600080fd5b505af1925050508015611143575060015b50845160325461119a91859187918d91633b9aca0090611171906bffffffffffffffffffffffff1682612a3d565b611189906bffffffffffffffffffffffff168a6129b6565b61119391906129cd565b8787610bc8565b505050505050505050565b633b9aca00816bffffffffffffffffffffffff1611156111d857604051633494a40d60e21b815260040160405180910390fd5b603280546bffffffffffffffffffffffff19166bffffffffffffffffffffffff92909216919091179055565b6040516001600160a01b03808516602483015283166044820152606481018290526112b59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611bef565b50505050565b600060018360018111156112d1576112d16128ab565b036112e9576112e286868685611cd9565b905061092f565b60008360018111156112fd576112fd6128ab565b0361092f5761130e87878787611eb8565b979650505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d919061287f565b9050818110156112b5576112b5836113a783600019612898565b6001600160a01b0387169190611ff8565b806001600160a01b0381166113e05760405163d92e233d60e01b815260040160405180910390fd5b6035805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040519081527f36db479a3b4d3672bd6f5fca4484283f60b5ac70647b1ceec13ecbb1d030a2df906020015b60405180910390a15050565b604051634a71aecf60e11b81526001600160a01b0383811660048301526000918291829182917f000000000000000000000000000000000000000000000000000000000000000016906394e35d9e906024016040805180830381865afa1580156114b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d59190612a69565b8651604051634a71aecf60e11b81526001600160a01b0391821660048201529294509092506000917f0000000000000000000000000000000000000000000000000000000000000000909116906394e35d9e906024016040805180830381865afa158015611547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156b9190612a69565b509050600082876020015167ffffffffffffffff1661158a91906129b6565b90508061159b85633b9aca006129b6565b1115611638576115af633b9aca00826129cd565b6115b99085612898565b9450600083886040015167ffffffffffffffff166115d791906129b6565b9050806115e884633b9aca006129b6565b11156115f75760009550611632565b80611602878561282f565b61161090633b9aca006129b6565b11156116325782611625633b9aca00836129cd565b61162f9190612898565b95505b506116dc565b600195508361164b633b9aca00836129cd565b6116559190612898565b9450600083886060015167ffffffffffffffff1661167391906129b6565b90508061168484633b9aca006129b6565b101561169357600095506116da565b6116a186633b9aca006129b6565b6116ab908261282f565b6116b984633b9aca006129b6565b10156116da576116cd633b9aca00826129cd565b6116d79084612898565b95505b505b505050509250929050565b6040517fb85780bc0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526060917f00000000000000000000000000000000000000000000000000000000000000009091169063b85780bc90602401600060405180830381865afa15801561176b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117939190810190612b30565b508051909150600181116117bf5760018301805467ffffffffffffffff1916633b9aca0017905561180e565b816117cb600283612898565b815181106117db576117db612beb565b60200260200101518360010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b6040517f847da7be0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526060917f00000000000000000000000000000000000000000000000000000000000000009091169063847da7be90602401600060405180830381865afa158015611892573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118ba9190810190612b30565b50805192509050600182116118f8576001840180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169055611947565b80611904600284612898565b8151811061191457611914612beb565b60200260200101518460010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5050505050565b6001600160a01b038681166000908152603360205260409020805473ffffffffffffffffffffffffffffffffffffffff1916918716919091178155633b9aca0067ffffffffffffffff8616106119b757604051633494a40d60e21b815260040160405180910390fd5b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16600160a01b67ffffffffffffffff87811691909102919091178255600180830180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b93861693840217905503611ace57633b9aca008367ffffffffffffffff16101580611a6357508267ffffffffffffffff168467ffffffffffffffff1610155b15611a8157604051633494a40d60e21b815260040160405180910390fd5b60018101805467ffffffffffffffff86811668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921690861617179055611b15565b6001810180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700200000000000000000000000000000000179055611b1586826116e7565b50505050505050565b6040516001600160a01b038316602482015260448101829052611b679084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611251565b505050565b806001600160a01b038116611b945760405163d92e233d60e01b815260040160405180910390fd5b6036805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040519081527ffd238617dbf7bc2e2e9c11b00a61a76432989bf0d6ca3a5aa34381a8752db40390602001611437565b6000611c44826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120c39092919063ffffffff16565b805190915015611b675780806020019051810190611c6291906127f7565b611b675760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a0823190602401602060405180830381865afa158015611d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d46919061287f565b60408051600180825281830190925291925060009190602080830190803683370190505090508681600081518110611d8057611d80612beb565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020015b6060815260200190600190039081611db05790505090508481600081518110611ddb57611ddb612beb565b60209081029190910101526040805160018082528183019092526000918160200160208202803683370190505090508681600081518110611e1e57611e1e612beb565b602002602001018181525050611e358383836120dc565b6040516370a0823160e01b815230600482015284906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9f919061287f565b611ea99190612898565b9450505050505b949350505050565b600084600103611f5e57611ecd848484611319565b6040517f6e553f65000000000000000000000000000000000000000000000000000000008152600481018390523060248201526001600160a01b03841690636e553f65906044016020604051808303816000875af1158015611f33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f57919061287f565b9050611eb0565b6040517fba08765200000000000000000000000000000000000000000000000000000000815260048101839052306024820181905260448201526001600160a01b0385169063ba087652906064016020604051808303816000875af1158015611fcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fef919061287f565b95945050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015612049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206d919061287f565b612077919061282f565b6040516001600160a01b0385166024820152604481018290529091506112b59085907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611251565b60606120d28484600085612165565b90505b9392505050565b825160005b818110156119475761213b8582815181106120fe576120fe612beb565b6020026020010151603660009054906101000a90046001600160a01b031685848151811061212e5761212e612beb565b60200260200101516122a2565b61215d84828151811061215057612150612beb565b602002602001015161232e565b6001016120e1565b6060824710156121dd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611cd0565b6001600160a01b0385163b6122345760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611cd0565b600080866001600160a01b031685876040516122509190612c01565b60006040518083038185875af1925050503d806000811461228d576040519150601f19603f3d011682016040523d82523d6000602084013e612292565b606091505b509150915061130e8282866123dd565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa1580156122f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612316919061287f565b9050818110156112b5576112b5836113a78385612898565b60355460405160009182916001600160a01b0390911690612350908590612c01565b6000604051808303816000865af19150503d806000811461238d576040519150601f19603f3d011682016040523d82523d6000602084013e612392565b606091505b509150915081611b67578051156123ab57805181602001fd5b6040517f7c3eb9ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606083156123ec5750816120d5565b8251156123fc5782518084602001fd5b8160405162461bcd60e51b8152600401611cd09190612c1d565b60006020828403121561242857600080fd5b81356bffffffffffffffffffffffff811681146120d557600080fd5b6001600160a01b03811681146105a757600080fd5b6000806040838503121561246c57600080fd5b82359150602083013561247e81612444565b809150509250929050565b60008083601f84011261249b57600080fd5b50813567ffffffffffffffff8111156124b357600080fd5b6020830191508360208285010111156124cb57600080fd5b9250929050565b60008060008060008060a087890312156124eb57600080fd5b86356124f681612444565b9550602087013561250681612444565b94506040870135935060608701359250608087013567ffffffffffffffff81111561253057600080fd5b61253c89828a01612489565b979a9699509497509295939492505050565b60006020828403121561256057600080fd5b81356120d581612444565b80356002811061257a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156125be576125be61257f565b604052919050565b600082601f8301126125d757600080fd5b813567ffffffffffffffff8111156125f1576125f161257f565b612604601f8201601f1916602001612595565b81815284602083860101111561261957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600080600060e0888a03121561265157600080fd5b87359650602088013560ff8116811461266957600080fd5b9550604088013561267981612444565b9450606088013561268981612444565b93506080880135925061269e60a0890161256b565b915060c088013567ffffffffffffffff8111156126ba57600080fd5b6126c68a828b016125c6565b91505092959891949750929550565b67ffffffffffffffff811681146105a757600080fd5b60008060008060008060c0878903121561270457600080fd5b863561270f81612444565b9550602087013561271f81612444565b9450604087013561272f816126d5565b9350606087013561273f816126d5565b9250608087013561274f816126d5565b915060a087013561275f816126d5565b809150509295509295509295565b6000806040838503121561278057600080fd5b823561278b81612444565b9150602083013561247e816126d5565b600080600080606085870312156127b157600080fd5b84356127bc81612444565b935060208501359250604085013567ffffffffffffffff8111156127df57600080fd5b6127eb87828801612489565b95989497509550505050565b60006020828403121561280957600080fd5b815180151581146120d557600080fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610a3b57610a3b612819565b600080600080600080600060e0888a03121561285d57600080fd5b873561286881612444565b965060208801359550604088013561267981612444565b60006020828403121561289157600080fd5b5051919050565b81810381811115610a3b57610a3b612819565b634e487b7160e01b600052602160045260246000fd5b60005b838110156128dc5781810151838201526020016128c4565b50506000910152565b600081518084526128fd8160208601602086016128c1565b601f01601f19169290920160200192915050565b6001600160a01b03888116825260ff881660208301528681166040830152851660608201526080810184905260006002841061295d57634e487b7160e01b600052602160045260246000fd5b8360a083015260e060c083015261297760e08301846128e5565b9998505050505050505050565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261092f60808301846128e5565b8082028115828204841417610a3b57610a3b612819565b6000826129ea57634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215612a0257600080fd5b612a0b8361256b565b9150602083013567ffffffffffffffff811115612a2757600080fd5b612a33858286016125c6565b9150509250929050565b6bffffffffffffffffffffffff828116828216039080821115612a6257612a62612819565b5092915050565b60008060408385031215612a7c57600080fd5b505080516020909101519092909150565b600067ffffffffffffffff821115612aa757612aa761257f565b5060051b60200190565b600082601f830112612ac257600080fd5b81516020612ad7612ad283612a8d565b612595565b8083825260208201915060208460051b870101935086841115612af957600080fd5b602086015b84811015612b255780518060070b8114612b185760008081fd5b8352918301918301612afe565b509695505050505050565b60008060408385031215612b4357600080fd5b825167ffffffffffffffff80821115612b5b57600080fd5b818501915085601f830112612b6f57600080fd5b81516020612b7f612ad283612a8d565b82815260059290921b84018101918181019089841115612b9e57600080fd5b948201945b83861015612bc5578551612bb6816126d5565b82529482019490820190612ba3565b91880151919650909350505080821115612bde57600080fd5b50612a3385828601612ab1565b634e487b7160e01b600052603260045260246000fd5b60008251612c138184602087016128c1565b9190910192915050565b6020815260006120d560208301846128e556fea26469706673582212205c8d9cacb2fb734c2b19d007d2c0616dc207648bf846ed1c0b2437237a75291d64736f6c6343000817003300000000000000000000000000000000000000000000000000000000002dc6c0000000000000000000000000111111125421ca6dc452d289314280a0f8842a65000000000000000000000000111111125421ca6dc452d289314280a0f8842a650000000000000000000000000000206329b97db379d5e1bf586bbdb969c63274000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d01370000000000000000000000005bc6bef80da563ebf6df6d6913513fa9a7ec89be0000000000000000000000004a2ff9bc686a0a23da13b6194c69939189506f7f
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101ae5760003560e01c806396d64879116100ee578063c5e6d5ea11610097578063e234b90311610071578063e234b903146104b5578063e43581b8146104c8578063edf0ef03146104db578063ee565a63146104ee57600080fd5b8063c5e6d5ea146103e0578063c9c6667414610482578063d2d0ec10146104a257600080fd5b80639ae78486116100c85780639ae78486146103a7578063b4a0bdf3146103ba578063c31c9c07146103cd57600080fd5b806396d648791461035e5780639786909c146103815780639a49e83d1461039457600080fd5b80635a7cb38f1161015b5780637ee84349116101355780637ee84349146102dc5780638195001d146102ef5780638237e538146103025780638c04166f1461032957600080fd5b80635a7cb38f14610276578063641bd503146102895780637239d2b9146102b557600080fd5b806323e30c8b1161018c57806323e30c8b1461021f5780634127365714610240578063521d4de91461025357600080fd5b8063184b949b146101b35780631b89b61a146101c8578063212c8fb11461020c575b600080fd5b6101c66101c1366004612416565b610515565b005b6101ef7f0000000000000000000000004a2ff9bc686a0a23da13b6194c69939189506f7f81565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c661021a366004612459565b6105aa565b61023261022d3660046124d2565b610611565b604051908152602001610203565b6101c661024e36600461254e565b610939565b61026661026136600461254e565b6109cb565b6040519015158152602001610203565b6036546101ef906001600160a01b031681565b61029c61029736600461254e565b610a41565b6040805160ff9093168352602083019190915201610203565b6101ef7f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d013781565b6101c66102ea36600461254e565b610acc565b6101c66102fd36600461254e565b610b7e565b6102327f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd981565b603254610341906bffffffffffffffffffffffff1681565b6040516bffffffffffffffffffffffff9091168152602001610203565b61026661036c36600461254e565b60346020526000908152604090205460ff1681565b6101c661038f366004612636565b610bc8565b6101c66103a23660046126eb565b610cb2565b6101c66103b536600461276d565b610d51565b6000546101ef906001600160a01b031681565b6035546101ef906001600160a01b031681565b6104416103ee36600461254e565b603360205260009081526040902080546001909101546001600160a01b0382169167ffffffffffffffff600160a01b90910481169180821691680100000000000000008204811691600160801b90041685565b604080516001600160a01b03909616865267ffffffffffffffff9485166020870152928416928501929092528216606084015216608082015260a001610203565b61023261049036600461254e565b60376020526000908152604090205481565b6101c66104b0366004612459565b610e6a565b6101c66104c336600461254e565b610ec3565b6102666104d636600461254e565b610f55565b6101c66104e936600461279b565b610fa1565b6101ef7f0000000000000000000000000000206329b97db379d5e1bf586bbdb969c6327481565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa15801561055d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058191906127f7565b61059e57604051632678482f60e21b815260040160405180910390fd5b6105a7816111a5565b50565b6001600160a01b038116600090815260376020526040812080548492906105d290849061282f565b9091555061060d90506001600160a01b037f0000000000000000000000000000206329b97db379d5e1bf586bbdb969c6327416333085611204565b5050565b6000336001600160a01b037f0000000000000000000000004a2ff9bc686a0a23da13b6194c69939189506f7f1614158061065457506001600160a01b0387163014155b8061065e57508315155b15610695576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080806060818080806106ac8b8d018d612842565b959e50939c509a50919850919650909250905060018890036106d3578193508092506106da565b8192508093505b50506040516301db50ff60e51b8152600481018d90526000602482018190526001600160a01b037f0000000000000000000000000000206329b97db379d5e1bf586bbdb969c632748116604484015283811660648401523060848401524260a484015290917f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d013790911690633b6a1fe09060c4016020604051808303816000875af115801561078c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b0919061287f565b90506107c08783858489896112bb565b90506107ed837f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d013783611319565b6040516301db50ff60e51b815260048101829052602481018790526001600160a01b0384811660448301527f0000000000000000000000000000206329b97db379d5e1bf586bbdb969c63274811660648301523060848301524260a48301526000917f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d013790911690633b6a1fe09060c4016020604051808303816000875af115801561089c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c0919061287f565b9050808e1115610902576108d4818f612898565b6001600160a01b038a16600090815260376020526040812080549091906108fc908490612898565b90915550505b7f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd999505050505050505050505b9695505050505050565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a591906127f7565b6109c257604051632678482f60e21b815260040160405180910390fd5b6105a7816113b8565b6000805460405163521d4de960e01b81526001600160a01b0384811660048301529091169063521d4de9906024015b602060405180830381865afa158015610a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3b91906127f7565b92915050565b6001600160a01b038181166000908152603360209081526040808320815160a08101835281549586168152600160a01b90950467ffffffffffffffff90811693860193909352600101548083169185019190915268010000000000000000810482166060850152600160801b9004166080830152908190610ac3908490611443565b91509150915091565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3891906127f7565b610b5557604051632678482f60e21b815260040160405180910390fd5b6001600160a01b03166000908152603460205260409020805460ff19811660ff90911615179055565b6001600160a01b03811660009081526033602052604090206001810154600160801b900467ffffffffffffffff1660020361060d57805461060d906001600160a01b0316826116e7565b7f0000000000000000000000004a2ff9bc686a0a23da13b6194c69939189506f7f6001600160a01b0316635cffe9de307f0000000000000000000000000000206329b97db379d5e1bf586bbdb969c632748a338b8b8b8b8b8b604051602001610c379796959493929190612911565b6040516020818303038152906040526040518563ffffffff1660e01b8152600401610c659493929190612984565b6020604051808303816000875af1158015610c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca891906127f7565b5050505050505050565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610cfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1e91906127f7565b610d3b57604051632678482f60e21b815260040160405180910390fd5b610d4986868686868661194e565b505050505050565b3360009081526034602052604090205460ff16158015610dda575060005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610db4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd891906127f7565b155b15610e11576040517f0dcc030f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b039091166000908152603360205260409020805467ffffffffffffffff909216600160a01b027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b3360009081526037602052604081208054849290610e89908490612898565b9091555061060d90506001600160a01b037f0000000000000000000000000000206329b97db379d5e1bf586bbdb969c63274168284611b1e565b60005460405163521d4de960e01b81523360048201526001600160a01b039091169063521d4de990602401602060405180830381865afa158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f91906127f7565b610f4c57604051632678482f60e21b815260040160405180910390fd5b6105a781611b6c565b600080546040517fe43581b80000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529091169063e43581b8906024016109fa565b633b9aca00831115610fc657604051633494a40d60e21b815260040160405180910390fd5b6001600160a01b038481166000908152603360209081526040808320815160a08101835281549586168152600160a01b90950467ffffffffffffffff90811693860193909352600101548083169185019190915268010000000000000000810482166060850152600160801b9004166080830152806110458784611443565b9092509050633b9aca0061105987836129b6565b61106391906129cd565b90508060000361109f576040517f1f2a200500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806110ae868801886129ef565b86516040517f1cb44dfc0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201529294509092507f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d01371690631cb44dfc90602401600060405180830381600087803b15801561113257600080fd5b505af1925050508015611143575060015b50845160325461119a91859187918d91633b9aca0090611171906bffffffffffffffffffffffff1682612a3d565b611189906bffffffffffffffffffffffff168a6129b6565b61119391906129cd565b8787610bc8565b505050505050505050565b633b9aca00816bffffffffffffffffffffffff1611156111d857604051633494a40d60e21b815260040160405180910390fd5b603280546bffffffffffffffffffffffff19166bffffffffffffffffffffffff92909216919091179055565b6040516001600160a01b03808516602483015283166044820152606481018290526112b59085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611bef565b50505050565b600060018360018111156112d1576112d16128ab565b036112e9576112e286868685611cd9565b905061092f565b60008360018111156112fd576112fd6128ab565b0361092f5761130e87878787611eb8565b979650505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611369573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138d919061287f565b9050818110156112b5576112b5836113a783600019612898565b6001600160a01b0387169190611ff8565b806001600160a01b0381166113e05760405163d92e233d60e01b815260040160405180910390fd5b6035805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040519081527f36db479a3b4d3672bd6f5fca4484283f60b5ac70647b1ceec13ecbb1d030a2df906020015b60405180910390a15050565b604051634a71aecf60e11b81526001600160a01b0383811660048301526000918291829182917f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d013716906394e35d9e906024016040805180830381865afa1580156114b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d59190612a69565b8651604051634a71aecf60e11b81526001600160a01b0391821660048201529294509092506000917f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d0137909116906394e35d9e906024016040805180830381865afa158015611547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156b9190612a69565b509050600082876020015167ffffffffffffffff1661158a91906129b6565b90508061159b85633b9aca006129b6565b1115611638576115af633b9aca00826129cd565b6115b99085612898565b9450600083886040015167ffffffffffffffff166115d791906129b6565b9050806115e884633b9aca006129b6565b11156115f75760009550611632565b80611602878561282f565b61161090633b9aca006129b6565b11156116325782611625633b9aca00836129cd565b61162f9190612898565b95505b506116dc565b600195508361164b633b9aca00836129cd565b6116559190612898565b9450600083886060015167ffffffffffffffff1661167391906129b6565b90508061168484633b9aca006129b6565b101561169357600095506116da565b6116a186633b9aca006129b6565b6116ab908261282f565b6116b984633b9aca006129b6565b10156116da576116cd633b9aca00826129cd565b6116d79084612898565b95505b505b505050509250929050565b6040517fb85780bc0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301526060917f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d01379091169063b85780bc90602401600060405180830381865afa15801561176b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117939190810190612b30565b508051909150600181116117bf5760018301805467ffffffffffffffff1916633b9aca0017905561180e565b816117cb600283612898565b815181106117db576117db612beb565b60200260200101518360010160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b6040517f847da7be0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301526060917f000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d01379091169063847da7be90602401600060405180830381865afa158015611892573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118ba9190810190612b30565b50805192509050600182116118f8576001840180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169055611947565b80611904600284612898565b8151811061191457611914612beb565b60200260200101518460010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505b5050505050565b6001600160a01b038681166000908152603360205260409020805473ffffffffffffffffffffffffffffffffffffffff1916918716919091178155633b9aca0067ffffffffffffffff8616106119b757604051633494a40d60e21b815260040160405180910390fd5b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16600160a01b67ffffffffffffffff87811691909102919091178255600180830180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b93861693840217905503611ace57633b9aca008367ffffffffffffffff16101580611a6357508267ffffffffffffffff168467ffffffffffffffff1610155b15611a8157604051633494a40d60e21b815260040160405180910390fd5b60018101805467ffffffffffffffff86811668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921690861617179055611b15565b6001810180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700200000000000000000000000000000000179055611b1586826116e7565b50505050505050565b6040516001600160a01b038316602482015260448101829052611b679084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401611251565b505050565b806001600160a01b038116611b945760405163d92e233d60e01b815260040160405180910390fd5b6036805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040519081527ffd238617dbf7bc2e2e9c11b00a61a76432989bf0d6ca3a5aa34381a8752db40390602001611437565b6000611c44826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166120c39092919063ffffffff16565b805190915015611b675780806020019051810190611c6291906127f7565b611b675760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6040516370a0823160e01b815230600482015260009081906001600160a01b038616906370a0823190602401602060405180830381865afa158015611d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d46919061287f565b60408051600180825281830190925291925060009190602080830190803683370190505090508681600081518110611d8057611d80612beb565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020015b6060815260200190600190039081611db05790505090508481600081518110611ddb57611ddb612beb565b60209081029190910101526040805160018082528183019092526000918160200160208202803683370190505090508681600081518110611e1e57611e1e612beb565b602002602001018181525050611e358383836120dc565b6040516370a0823160e01b815230600482015284906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611e7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9f919061287f565b611ea99190612898565b9450505050505b949350505050565b600084600103611f5e57611ecd848484611319565b6040517f6e553f65000000000000000000000000000000000000000000000000000000008152600481018390523060248201526001600160a01b03841690636e553f65906044016020604051808303816000875af1158015611f33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f57919061287f565b9050611eb0565b6040517fba08765200000000000000000000000000000000000000000000000000000000815260048101839052306024820181905260448201526001600160a01b0385169063ba087652906064016020604051808303816000875af1158015611fcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fef919061287f565b95945050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015612049573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206d919061287f565b612077919061282f565b6040516001600160a01b0385166024820152604481018290529091506112b59085907f095ea7b30000000000000000000000000000000000000000000000000000000090606401611251565b60606120d28484600085612165565b90505b9392505050565b825160005b818110156119475761213b8582815181106120fe576120fe612beb565b6020026020010151603660009054906101000a90046001600160a01b031685848151811061212e5761212e612beb565b60200260200101516122a2565b61215d84828151811061215057612150612beb565b602002602001015161232e565b6001016120e1565b6060824710156121dd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611cd0565b6001600160a01b0385163b6122345760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611cd0565b600080866001600160a01b031685876040516122509190612c01565b60006040518083038185875af1925050503d806000811461228d576040519150601f19603f3d011682016040523d82523d6000602084013e612292565b606091505b509150915061130e8282866123dd565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa1580156122f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612316919061287f565b9050818110156112b5576112b5836113a78385612898565b60355460405160009182916001600160a01b0390911690612350908590612c01565b6000604051808303816000865af19150503d806000811461238d576040519150601f19603f3d011682016040523d82523d6000602084013e612392565b606091505b509150915081611b67578051156123ab57805181602001fd5b6040517f7c3eb9ca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606083156123ec5750816120d5565b8251156123fc5782518084602001fd5b8160405162461bcd60e51b8152600401611cd09190612c1d565b60006020828403121561242857600080fd5b81356bffffffffffffffffffffffff811681146120d557600080fd5b6001600160a01b03811681146105a757600080fd5b6000806040838503121561246c57600080fd5b82359150602083013561247e81612444565b809150509250929050565b60008083601f84011261249b57600080fd5b50813567ffffffffffffffff8111156124b357600080fd5b6020830191508360208285010111156124cb57600080fd5b9250929050565b60008060008060008060a087890312156124eb57600080fd5b86356124f681612444565b9550602087013561250681612444565b94506040870135935060608701359250608087013567ffffffffffffffff81111561253057600080fd5b61253c89828a01612489565b979a9699509497509295939492505050565b60006020828403121561256057600080fd5b81356120d581612444565b80356002811061257a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156125be576125be61257f565b604052919050565b600082601f8301126125d757600080fd5b813567ffffffffffffffff8111156125f1576125f161257f565b612604601f8201601f1916602001612595565b81815284602083860101111561261957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600080600060e0888a03121561265157600080fd5b87359650602088013560ff8116811461266957600080fd5b9550604088013561267981612444565b9450606088013561268981612444565b93506080880135925061269e60a0890161256b565b915060c088013567ffffffffffffffff8111156126ba57600080fd5b6126c68a828b016125c6565b91505092959891949750929550565b67ffffffffffffffff811681146105a757600080fd5b60008060008060008060c0878903121561270457600080fd5b863561270f81612444565b9550602087013561271f81612444565b9450604087013561272f816126d5565b9350606087013561273f816126d5565b9250608087013561274f816126d5565b915060a087013561275f816126d5565b809150509295509295509295565b6000806040838503121561278057600080fd5b823561278b81612444565b9150602083013561247e816126d5565b600080600080606085870312156127b157600080fd5b84356127bc81612444565b935060208501359250604085013567ffffffffffffffff8111156127df57600080fd5b6127eb87828801612489565b95989497509550505050565b60006020828403121561280957600080fd5b815180151581146120d557600080fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115610a3b57610a3b612819565b600080600080600080600060e0888a03121561285d57600080fd5b873561286881612444565b965060208801359550604088013561267981612444565b60006020828403121561289157600080fd5b5051919050565b81810381811115610a3b57610a3b612819565b634e487b7160e01b600052602160045260246000fd5b60005b838110156128dc5781810151838201526020016128c4565b50506000910152565b600081518084526128fd8160208601602086016128c1565b601f01601f19169290920160200192915050565b6001600160a01b03888116825260ff881660208301528681166040830152851660608201526080810184905260006002841061295d57634e487b7160e01b600052602160045260246000fd5b8360a083015260e060c083015261297760e08301846128e5565b9998505050505050505050565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261092f60808301846128e5565b8082028115828204841417610a3b57610a3b612819565b6000826129ea57634e487b7160e01b600052601260045260246000fd5b500490565b60008060408385031215612a0257600080fd5b612a0b8361256b565b9150602083013567ffffffffffffffff811115612a2757600080fd5b612a33858286016125c6565b9150509250929050565b6bffffffffffffffffffffffff828116828216039080821115612a6257612a62612819565b5092915050565b60008060408385031215612a7c57600080fd5b505080516020909101519092909150565b600067ffffffffffffffff821115612aa757612aa761257f565b5060051b60200190565b600082601f830112612ac257600080fd5b81516020612ad7612ad283612a8d565b612595565b8083825260208201915060208460051b870101935086841115612af957600080fd5b602086015b84811015612b255780518060070b8114612b185760008081fd5b8352918301918301612afe565b509695505050505050565b60008060408385031215612b4357600080fd5b825167ffffffffffffffff80821115612b5b57600080fd5b818501915085601f830112612b6f57600080fd5b81516020612b7f612ad283612a8d565b82815260059290921b84018101918181019089841115612b9e57600080fd5b948201945b83861015612bc5578551612bb6816126d5565b82529482019490820190612ba3565b91880151919650909350505080821115612bde57600080fd5b50612a3385828601612ab1565b634e487b7160e01b600052603260045260246000fd5b60008251612c138184602087016128c1565b9190910192915050565b6020815260006120d560208301846128e556fea26469706673582212205c8d9cacb2fb734c2b19d007d2c0616dc207648bf846ed1c0b2437237a75291d64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000002dc6c0000000000000000000000000111111125421ca6dc452d289314280a0f8842a65000000000000000000000000111111125421ca6dc452d289314280a0f8842a650000000000000000000000000000206329b97db379d5e1bf586bbdb969c63274000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d01370000000000000000000000005bc6bef80da563ebf6df6d6913513fa9a7ec89be0000000000000000000000004a2ff9bc686a0a23da13b6194c69939189506f7f
-----Decoded View---------------
Arg [0] : initialMaxSlippage (uint96): 3000000
Arg [1] : initialTokenTransferAddress (address): 0x111111125421cA6dc452d289314280a0f8842A65
Arg [2] : initialSwapRouter (address): 0x111111125421cA6dc452d289314280a0f8842A65
Arg [3] : definitiveAgToken (address): 0x0000206329b97DB379d5E1Bf586BbDB969C63274
Arg [4] : definitiveTransmuter (address): 0x222222fD79264BBE280b4986F6FEfBC3524d0137
Arg [5] : definitiveAccessControlManager (address): 0x5bc6BEf80DA563EBf6Df6D6913513fa9A7ec89BE
Arg [6] : definitiveFlashloan (address): 0x4A2FF9bC686A0A23DA13B6194C69939189506F7F
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000002dc6c0
Arg [1] : 000000000000000000000000111111125421ca6dc452d289314280a0f8842a65
Arg [2] : 000000000000000000000000111111125421ca6dc452d289314280a0f8842a65
Arg [3] : 0000000000000000000000000000206329b97db379d5e1bf586bbdb969c63274
Arg [4] : 000000000000000000000000222222fd79264bbe280b4986f6fefbc3524d0137
Arg [5] : 0000000000000000000000005bc6bef80da563ebf6df6d6913513fa9a7ec89be
Arg [6] : 0000000000000000000000004a2ff9bc686a0a23da13b6194c69939189506f7f
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.9974 | 14,315.6814 | $14,278.46 |
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.