More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x61012060 | 19932683 | 166 days ago | IN | 0 ETH | 0.0243015 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
SecondaryRewarder
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity =0.7.6; import {GenericToken} from "../../internal/balances/protocols/GenericToken.sol"; import {IRewarder} from "../../../interfaces/notional/IRewarder.sol"; import {NotionalProxy} from "../../../interfaces/notional/NotionalProxy.sol"; import {IERC20} from "../../../interfaces/IERC20.sol"; import {IEIP20NonStandard} from "../../../interfaces/IEIP20NonStandard.sol"; import {Constants} from "../../global/Constants.sol"; import {SafeInt256} from "../../math/SafeInt256.sol"; import {SafeUint256} from "../../math/SafeUint256.sol"; import {FloatingPoint} from "../../math/FloatingPoint.sol"; import {MerkleProof} from "@openzeppelin/contracts/cryptography/MerkleProof.sol"; contract SecondaryRewarder is IRewarder { using SafeUint256 for uint256; using SafeInt256 for int256; NotionalProxy public immutable NOTIONAL; address public immutable override NTOKEN_ADDRESS; address public immutable REWARD_TOKEN; uint8 public immutable REWARD_TOKEN_DECIMALS; uint16 public immutable override CURRENCY_ID; /// @notice When a rewarder is detached, it converts to an airdrop contract using the /// this merkleRoot that is set. /// @dev Uses a single storage slot bytes32 public merkleRoot; /* Rest of storage variables are packed into 256 bits */ /// @notice When true user needs to call contract directly to claim any rewards left bool public override detached; /// @notice Marks the timestamp when incentives will end. Will always be less than block.timestamp /// if detached is true. uint32 public endTime; /// @notice Last time the contract accumulated the reward uint32 public override lastAccumulatedTime; // The emission rate of REWARD_TOKEN in INTERNAL_TOKEN_PRECISION packed to uint56 uint56 private packedEmissionRatePerYear; /// @notice Aggregate tokens accumulated per nToken at `lastAccumulateTime` // in INCENTIVE_ACCUMULATION_PRECISION uint128 public override accumulatedRewardPerNToken; /// @notice Reward debt per account stored in 18 decimals. mapping(address => uint128) public rewardDebtPerAccount; modifier onlyOwner() { require(msg.sender == NOTIONAL.owner(), "Only owner"); _; } modifier onlyNotional() { require(msg.sender == address(NOTIONAL), "Only Notional"); _; } constructor( NotionalProxy notional, uint16 currencyId, IERC20 incentive_token, uint128 _emissionRatePerYear, // in INTERNAL_TOKEN_PRECISION uint32 _endTime ) { NOTIONAL = notional; CURRENCY_ID = currencyId; NTOKEN_ADDRESS = notional.nTokenAddress(currencyId); REWARD_TOKEN = address(incentive_token); REWARD_TOKEN_DECIMALS = IERC20(address(incentive_token)).decimals(); packedEmissionRatePerYear = FloatingPoint.packTo56Bits(_emissionRatePerYear); lastAccumulatedTime = uint32(block.timestamp); require(lastAccumulatedTime < _endTime, "Invalid End Time"); endTime = _endTime; } /// @notice The emission rate of REWARD_TOKEN in INTERNAL_TOKEN_PRECISION function emissionRatePerYear() public view override returns(uint128) { return uint128(FloatingPoint.unpackFromBits(packedEmissionRatePerYear)); } /// @notice Get amount of reward account can claim at specified block time, only called before rewarder is detached /// @param account address to get reward amount for /// @param blockTime block time at which to get reward amount function getAccountRewardClaim(address account, uint32 blockTime) external view override returns (uint256 rewardToClaim) { require(!detached, "Detached"); require(lastAccumulatedTime <= blockTime, "Invalid block time"); uint256 totalSupply = IERC20(NTOKEN_ADDRESS).totalSupply(); uint256 nTokenBalance = IERC20(NTOKEN_ADDRESS).balanceOf(account); uint32 time = uint32(SafeInt256.min(blockTime, endTime)); uint128 rewardsPerNToken = _getAccumulatedRewardPerToken(time, totalSupply); rewardToClaim = _calculateRewardToClaim(account, nTokenBalance, rewardsPerNToken); } /// @notice Get amount of reward still left for account to claim, only called after rewarder is detached /// and merkle root is set /// @param account address to get reward amount for /// @param nTokenBalanceAtDetach nToken balance of account at time of detachment /// @param proof merkle proof to prove account and nTokenBalanceAtDetach are in tree function getAccountRewardClaim(address account, uint256 nTokenBalanceAtDetach, bytes32[] calldata proof) external view override returns (uint256 rewardToClaim) { require(detached && merkleRoot != bytes32(0), "Not detached"); _checkProof(account, nTokenBalanceAtDetach, proof); // no need to accumulate, it was already accumulated when rewarder was detached rewardToClaim = _calculateRewardToClaim(account, nTokenBalanceAtDetach, accumulatedRewardPerNToken); } /// @notice Set incentive emission rate and incentive period end time, called only in case emission /// rate or incentive period changes since it is already set at deploy time, only can be called before /// rewarder is detached /// @param _emissionRatePerYear emission rate per year in INTERNAL_TOKEN_PRECISION /// @param _endTime time in seconds when incentive period will end function setIncentiveEmissionRate(uint128 _emissionRatePerYear, uint32 _endTime) external onlyOwner { require(!detached, "Detached"); uint256 totalSupply = IERC20(NTOKEN_ADDRESS).totalSupply(); _accumulateRewardPerNToken(uint32(block.timestamp), totalSupply); packedEmissionRatePerYear = FloatingPoint.packTo56Bits(_emissionRatePerYear); // lastAccumulatedTime is at block.timestamp here, ensure that the end time is always // further in the future. require(lastAccumulatedTime < _endTime, "Invalid End Time"); endTime = _endTime; emit RewardEmissionUpdate(FloatingPoint.unpackFromBits(packedEmissionRatePerYear), _endTime); } /// @notice Set merkle root, only called after rewarder is detached /// @param _merkleRoot merkle root of the tree that contains accounts and nToken balances at detach time function setMerkleRoot(bytes32 _merkleRoot) external onlyOwner { require(_merkleRoot != bytes32(0), "Invalid"); merkleRoot = _merkleRoot; } /// @notice Allows owner to recover any ERC20 or ETH mistakenly sent to this contract /// @param token address of the token to recover, in case of ETH pass address(0) /// @param amount amount to recover function recover(address token, uint256 amount) external onlyOwner { if (Constants.ETH_ADDRESS == token) { (bool status,) = msg.sender.call{value: amount}(""); require(status); } else { GenericToken.safeTransferOut(token, msg.sender, amount); } } /// @dev Called from Notional system to detach rewarder when switching to a new rewarder or when incentive /// period is over, after this merkle tree of user nToken balances at detach time should be generated /// offline and merkle root uploaded to this contract function detach() external override onlyNotional { require(!detached, "Already detached"); // accumulate for the last time if needed uint256 totalSupply = IERC20(NTOKEN_ADDRESS).totalSupply(); _accumulateRewardPerNToken(uint32(block.timestamp), totalSupply); detached = true; packedEmissionRatePerYear = 0; if (block.timestamp < endTime) { endTime = uint32(block.timestamp); } emit RewardEmissionUpdate(0, endTime); } /// @notice Allows claiming rewards after rewarder has been detached /// @param account address to claim rewards for /// @param nTokenBalanceAtDetach nToken balance of account at time of detachment /// @param proof merkle proof to prove account and nTokenBalanceAtDetach are in tree function claimRewardsDirect(address account, uint256 nTokenBalanceAtDetach, bytes32[] calldata proof) external override { require(detached, "Not detached"); _checkProof(account, nTokenBalanceAtDetach, proof); _claimRewards(account, nTokenBalanceAtDetach, nTokenBalanceAtDetach); } /// @notice Allows claiming rewards but only from Notional system, called on each nToken balance change /// @param account address to claim rewards for /// @param currencyId id number of the currency /// @param nTokenBalanceBefore account nToken balance before the change /// @param nTokenBalanceAfter account nToken balance after the change /// @param priorNTokenSupply total nToken supply before the change function claimRewards( address account, uint16 currencyId, uint256 nTokenBalanceBefore, uint256 nTokenBalanceAfter, uint256 priorNTokenSupply ) external override onlyNotional { require(!detached, "Detached"); require(currencyId == CURRENCY_ID, "Wrong currency id"); _accumulateRewardPerNToken(uint32(block.timestamp), priorNTokenSupply); _claimRewards(account, nTokenBalanceBefore, nTokenBalanceAfter); } function _claimRewards(address account, uint256 nTokenBalanceBefore, uint256 nTokenBalanceAfter) private { uint256 rewardToClaim = _calculateRewardToClaim(account, nTokenBalanceBefore, accumulatedRewardPerNToken); // Precision here is: // nTokenBalanceAfter (INTERNAL_TOKEN_PRECISION) // accumulatedRewardPerNToken (INCENTIVE_ACCUMULATION_PRECISION) // DIVIDE BY // INTERNAL_TOKEN_PRECISION // => INCENTIVE_ACCUMULATION_PRECISION (1e18) rewardDebtPerAccount[account] = nTokenBalanceAfter .mul(accumulatedRewardPerNToken) .div(uint256(Constants.INTERNAL_TOKEN_PRECISION)) .toUint128(); if (0 < rewardToClaim) { try IEIP20NonStandard(REWARD_TOKEN).transfer(account, rewardToClaim) { bool success = checkReturnCode(); if (success) { emit RewardTransfer(REWARD_TOKEN, account, rewardToClaim); } // ignore failed reward transfers } catch {} } } function _getAccumulatedRewardPerToken(uint32 time, uint256 totalSupply) private view returns (uint128) { uint256 additionalIncentiveAccumulatedPerNToken; if (lastAccumulatedTime < time && 0 < totalSupply) { // NOTE: no underflow, checked in if statement uint256 timeSinceLastAccumulation = time - lastAccumulatedTime; // Precision here is: // timeSinceLastAccumulation (SECONDS) // INCENTIVE_ACCUMULATION_PRECISION (1e18) // INTERNAL_TOKEN_PRECISION (1e8) // DIVIDE BY // YEAR (SECONDS) // INTERNAL_TOKEN_PRECISION (1e8) // => Precision = INCENTIVE_ACCUMULATION_PRECISION * INTERNAL_TOKEN_PRECISION / INTERNAL_TOKEN_PRECISION // => 1e18 additionalIncentiveAccumulatedPerNToken = timeSinceLastAccumulation .mul(Constants.INCENTIVE_ACCUMULATION_PRECISION) .mul(emissionRatePerYear()) .div(Constants.YEAR) .div(totalSupply); } return uint256(accumulatedRewardPerNToken).add(additionalIncentiveAccumulatedPerNToken).toUint128(); } function _accumulateRewardPerNToken(uint32 blockTime, uint256 totalSupply) private { // Ensure that end time is set to some value require(0 < endTime); uint32 time = uint32(SafeInt256.min(blockTime, endTime)); accumulatedRewardPerNToken = _getAccumulatedRewardPerToken(time, totalSupply); lastAccumulatedTime = uint32(block.timestamp); } function _calculateRewardToClaim(address account, uint256 nTokenBalanceAtLastClaim, uint128 rewardsPerNToken) private view returns (uint256) { // Precision here is: // nTokenBalanceAtLastClaim (INTERNAL_TOKEN_PRECISION) // mul rewardsPerNToken (INCENTIVE_ACCUMULATION_PRECISION) // div INTERNAL_TOKEN_PRECISION // => INCENTIVE_ACCUMULATION_PRECISION // SUB rewardDebtPerAccount (INCENTIVE_ACCUMULATION_PRECISION) // // - mul REWARD_TOKEN_DECIMALS // - div INCENTIVE_ACCUMULATION_PRECISION // => REWARD_TOKEN_DECIMALS return uint256(nTokenBalanceAtLastClaim) .mul(rewardsPerNToken) .div(uint256(Constants.INTERNAL_TOKEN_PRECISION)) .sub(rewardDebtPerAccount[account]) .mul(10 ** REWARD_TOKEN_DECIMALS) .div(Constants.INCENTIVE_ACCUMULATION_PRECISION); } /// @notice Verify merkle proof, or revert if not in tree function _checkProof(address account, uint256 balance, bytes32[] calldata proof) private view { // Verify merkle proof, or revert if not in tree bytes32 leaf = keccak256(abi.encodePacked(account, balance)); bool isValidLeaf = MerkleProof.verify(proof, merkleRoot, leaf); require(isValidLeaf, "NotInMerkle"); } function checkReturnCode() private pure returns(bool success) { uint256[1] memory result; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := 1 // set success to true } case 32 { // This is a compliant ERC-20 returndatacopy(result, 0, 32) success := mload(result) // Set `success = returndata` of external call } default { // This is an excessively non-compliant ERC-20. success := 0 } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev These functions deal with verification of Merkle trees (hash trees), */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { bytes32 proofElement = proof[i]; if (computedHash <= proofElement) { // Hash(current computed hash + current element of the proof) computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { // Hash(current element of the proof + current computed hash) computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } } // Check if the computed hash (root) is equal to the provided root return computedHash == root; } }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; /// @title All shared constants for the Notional system should be declared here. library Constants { uint8 internal constant CETH_DECIMAL_PLACES = 8; // Token precision used for all internal balances, TokenHandler library ensures that we // limit the dust amount caused by precision mismatches int256 internal constant INTERNAL_TOKEN_PRECISION = 1e8; uint256 internal constant INCENTIVE_ACCUMULATION_PRECISION = 1e18; // ETH will be initialized as the first currency uint256 internal constant ETH_CURRENCY_ID = 1; uint8 internal constant ETH_DECIMAL_PLACES = 18; int256 internal constant ETH_DECIMALS = 1e18; address internal constant ETH_ADDRESS = address(0); // Used to prevent overflow when converting decimal places to decimal precision values via // 10**decimalPlaces. This is a safe value for int256 and uint256 variables. We apply this // constraint when storing decimal places in governance. uint256 internal constant MAX_DECIMAL_PLACES = 36; // Address of the account where fees are collected address internal constant FEE_RESERVE = 0x0000000000000000000000000000000000000FEE; // Address of the account where settlement funds are collected, this is only // used for off chain event tracking. address internal constant SETTLEMENT_RESERVE = 0x00000000000000000000000000000000000005e7; // Most significant bit bytes32 internal constant MSB = 0x8000000000000000000000000000000000000000000000000000000000000000; // Each bit set in this mask marks where an active market should be in the bitmap // if the first bit refers to the reference time. Used to detect idiosyncratic // fcash in the nToken accounts bytes32 internal constant ACTIVE_MARKETS_MASK = ( MSB >> ( 90 - 1) | // 3 month MSB >> (105 - 1) | // 6 month MSB >> (135 - 1) | // 1 year MSB >> (147 - 1) | // 2 year MSB >> (183 - 1) | // 5 year MSB >> (211 - 1) | // 10 year MSB >> (251 - 1) // 20 year ); // Basis for percentages int256 internal constant PERCENTAGE_DECIMALS = 100; // Min Buffer Scale and Buffer Scale are used in ExchangeRate to increase the maximum // possible buffer values at the higher end of the uint8 range. int256 internal constant MIN_BUFFER_SCALE = 150; int256 internal constant BUFFER_SCALE = 10; // Max number of traded markets, also used as the maximum number of assets in a portfolio array uint256 internal constant MAX_TRADED_MARKET_INDEX = 7; // Max number of fCash assets in a bitmap, this is based on the gas costs of calculating free collateral // for a bitmap portfolio uint256 internal constant MAX_BITMAP_ASSETS = 20; uint256 internal constant FIVE_MINUTES = 300; // Internal date representations, note we use a 6/30/360 week/month/year convention here uint256 internal constant DAY = 86400; // We use six day weeks to ensure that all time references divide evenly uint256 internal constant WEEK = DAY * 6; uint256 internal constant MONTH = WEEK * 5; uint256 internal constant QUARTER = MONTH * 3; uint256 internal constant YEAR = QUARTER * 4; // These constants are used in DateTime.sol uint256 internal constant DAYS_IN_WEEK = 6; uint256 internal constant DAYS_IN_MONTH = 30; uint256 internal constant DAYS_IN_QUARTER = 90; // Offsets for each time chunk denominated in days uint256 internal constant MAX_DAY_OFFSET = 90; uint256 internal constant MAX_WEEK_OFFSET = 360; uint256 internal constant MAX_MONTH_OFFSET = 2160; uint256 internal constant MAX_QUARTER_OFFSET = 7650; // Offsets for each time chunk denominated in bits uint256 internal constant WEEK_BIT_OFFSET = 90; uint256 internal constant MONTH_BIT_OFFSET = 135; uint256 internal constant QUARTER_BIT_OFFSET = 195; // Number of decimal places that rates are stored in, equals 100% int256 internal constant RATE_PRECISION = 1e9; // Used for prime cash scalars uint256 internal constant SCALAR_PRECISION = 1e18; // Used in prime rate lib int256 internal constant DOUBLE_SCALAR_PRECISION = 1e36; // One basis point in RATE_PRECISION terms uint256 internal constant BASIS_POINT = uint256(RATE_PRECISION / 10000); // Used to when calculating the amount to deleverage of a market when minting nTokens uint256 internal constant DELEVERAGE_BUFFER = 300 * BASIS_POINT; // Used for scaling cash group factors uint256 internal constant FIVE_BASIS_POINTS = 5 * BASIS_POINT; // Used for residual purchase incentive and cash withholding buffer uint256 internal constant TEN_BASIS_POINTS = 10 * BASIS_POINT; // Used for max oracle rate uint256 internal constant FIFTEEN_BASIS_POINTS = 15 * BASIS_POINT; // Used in max rate calculations uint256 internal constant MAX_LOWER_INCREMENT = 150; uint256 internal constant MAX_LOWER_INCREMENT_VALUE = 150 * 25 * BASIS_POINT; uint256 internal constant TWENTY_FIVE_BASIS_POINTS = 25 * BASIS_POINT; uint256 internal constant ONE_HUNDRED_FIFTY_BASIS_POINTS = 150 * BASIS_POINT; // This is the ABDK64x64 representation of RATE_PRECISION // RATE_PRECISION_64x64 = ABDKMath64x64.fromUint(RATE_PRECISION) int128 internal constant RATE_PRECISION_64x64 = 0x3b9aca000000000000000000; uint8 internal constant FCASH_ASSET_TYPE = 1; // Liquidity token asset types are 1 + marketIndex (where marketIndex is 1-indexed) uint8 internal constant MIN_LIQUIDITY_TOKEN_INDEX = 2; uint8 internal constant MAX_LIQUIDITY_TOKEN_INDEX = 8; uint8 internal constant VAULT_SHARE_ASSET_TYPE = 9; uint8 internal constant VAULT_DEBT_ASSET_TYPE = 10; uint8 internal constant VAULT_CASH_ASSET_TYPE = 11; // Used for tracking legacy nToken assets uint8 internal constant LEGACY_NTOKEN_ASSET_TYPE = 12; // Account context flags bytes1 internal constant HAS_ASSET_DEBT = 0x01; bytes1 internal constant HAS_CASH_DEBT = 0x02; bytes2 internal constant ACTIVE_IN_PORTFOLIO = 0x8000; bytes2 internal constant ACTIVE_IN_BALANCES = 0x4000; bytes2 internal constant UNMASK_FLAGS = 0x3FFF; uint16 internal constant MAX_CURRENCIES = uint16(UNMASK_FLAGS); // Equal to 100% of all deposit amounts for nToken liquidity across fCash markets. int256 internal constant DEPOSIT_PERCENT_BASIS = 1e8; // nToken Parameters: there are offsets in the nTokenParameters bytes6 variable returned // in nTokenHandler. Each constant represents a position in the byte array. uint8 internal constant LIQUIDATION_HAIRCUT_PERCENTAGE = 0; uint8 internal constant CASH_WITHHOLDING_BUFFER = 1; uint8 internal constant RESIDUAL_PURCHASE_TIME_BUFFER = 2; uint8 internal constant PV_HAIRCUT_PERCENTAGE = 3; uint8 internal constant RESIDUAL_PURCHASE_INCENTIVE = 4; uint8 internal constant MAX_MINT_DEVIATION_LIMIT = 5; // Liquidation parameters // Default percentage of collateral that a liquidator is allowed to liquidate, will be higher if the account // requires more collateral to be liquidated int256 internal constant DEFAULT_LIQUIDATION_PORTION = 40; // Percentage of local liquidity token cash claim delivered to the liquidator for liquidating liquidity tokens int256 internal constant TOKEN_REPO_INCENTIVE_PERCENT = 30; // Pause Router liquidation enabled states bytes1 internal constant LOCAL_CURRENCY_ENABLED = 0x01; bytes1 internal constant COLLATERAL_CURRENCY_ENABLED = 0x02; bytes1 internal constant LOCAL_FCASH_ENABLED = 0x04; bytes1 internal constant CROSS_CURRENCY_FCASH_ENABLED = 0x08; // Requires vault accounts to enter a position for a minimum of 1 min // to mitigate strange behavior where accounts may enter and exit using // flash loans or other MEV type behavior. uint256 internal constant VAULT_ACCOUNT_MIN_TIME = 1 minutes; // Placeholder constant to mark the variable rate prime cash maturity uint40 internal constant PRIME_CASH_VAULT_MATURITY = type(uint40).max; // This represents the maximum percent change allowed before and after // a rebalancing. 100_000 represents a 0.01% change // as a result of rebalancing. We should expect to never lose value as // a result of rebalancing, but some rounding errors may exist as a result // of redemption and deposit. int256 internal constant REBALANCING_UNDERLYING_DELTA_PERCENT = 100_000; // Ensures that the minimum total underlying held by the contract continues // to accrue interest so that money market oracle rates are properly updated // between rebalancing. With a minimum rebalancing cool down time of 6 hours // we would be able to detect at least 1 unit of accrual at 8 decimal precision // at an interest rate of 2.8 basis points (0.0288%) with 0.05e8 minimum balance // held in a given token. // // MIN_ACCRUAL * (86400 / REBALANCING_COOL_DOWN_HOURS) // MINIMUM_INTEREST_RATE = --------------------------------------------------- // MINIMUM_UNDERLYING_BALANCE int256 internal constant MIN_TOTAL_UNDERLYING_VALUE = 0.05e8; }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; import {WETH9} from "../../interfaces/WETH9.sol"; import {IUpgradeableBeacon} from "../proxy/beacon/IBeacon.sol"; import {AggregatorV2V3Interface} from "../../interfaces/chainlink/AggregatorV2V3Interface.sol"; /// @title Hardcoded deployed contracts are listed here. These are hardcoded to reduce /// gas costs for immutable addresses. They must be updated per environment that Notional /// is deployed to. library Deployments { uint256 internal constant MAINNET = 1; uint256 internal constant ARBITRUM_ONE = 42161; uint256 internal constant LOCAL = 1337; // MAINNET: 0xCFEAead4947f0705A14ec42aC3D44129E1Ef3eD5 address internal constant NOTE_TOKEN_ADDRESS = 0xCFEAead4947f0705A14ec42aC3D44129E1Ef3eD5; // ARBITRUM: 0x019bE259BC299F3F653688c7655C87F998Bc7bC1 // address internal constant NOTE_TOKEN_ADDRESS = 0x019bE259BC299F3F653688c7655C87F998Bc7bC1; // MAINNET: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 WETH9 internal constant WETH = WETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); // ARBITRUM: 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 // WETH9 internal constant WETH = WETH9(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1); // OPTIMISM: 0x4200000000000000000000000000000000000006 // Chainlink L2 Sequencer Uptime: https://docs.chain.link/data-feeds/l2-sequencer-feeds/ // MAINNET: NOT SET AggregatorV2V3Interface internal constant SEQUENCER_UPTIME_ORACLE = AggregatorV2V3Interface(address(0)); // ARBITRUM: 0xFdB631F5EE196F0ed6FAa767959853A9F217697D // AggregatorV2V3Interface internal constant SEQUENCER_UPTIME_ORACLE = AggregatorV2V3Interface(0xFdB631F5EE196F0ed6FAa767959853A9F217697D); enum BeaconType { NTOKEN, PCASH, PDEBT, WRAPPED_FCASH } // NOTE: these are temporary Beacon addresses IUpgradeableBeacon internal constant NTOKEN_BEACON = IUpgradeableBeacon(0xc4FD259b816d081C8bdd22D6bbd3495DB1573DB7); IUpgradeableBeacon internal constant PCASH_BEACON = IUpgradeableBeacon(0x1F681977aF5392d9Ca5572FB394BC4D12939A6A9); IUpgradeableBeacon internal constant PDEBT_BEACON = IUpgradeableBeacon(0xDF08039c0af34E34660aC7c2705C0Da953247640); // Mainnet: IUpgradeableBeacon internal constant WRAPPED_FCASH_BEACON = IUpgradeableBeacon(0xEBe1BF1653d55d31F6ED38B1A4CcFE2A92338f66); // Arbitrum: // IUpgradeableBeacon internal constant WRAPPED_FCASH_BEACON = IUpgradeableBeacon(0xD676d720E4e8B14F545F9116F0CAD47aF32329DD); // NOTE: this is unused and should be removed if the contract is ever deployed again uint256 internal constant NOTIONAL_V2_FINAL_SETTLEMENT = 0; }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import "../../interfaces/chainlink/AggregatorV2V3Interface.sol"; import "../../interfaces/notional/IPrimeCashHoldingsOracle.sol"; import "../../interfaces/notional/AssetRateAdapter.sol"; /// @notice Different types of internal tokens /// - UnderlyingToken: underlying asset for a cToken (except for Ether) /// - cToken: Compound interest bearing token /// - cETH: Special handling for cETH tokens /// - Ether: the one and only /// - NonMintable: tokens that do not have an underlying (therefore not cTokens) /// - aToken: Aave interest bearing tokens enum TokenType { UnderlyingToken, cToken, cETH, Ether, NonMintable, aToken } /// @notice Specifies the different trade action types in the system. Each trade action type is /// encoded in a tightly packed bytes32 object. Trade action type is the first big endian byte of the /// 32 byte trade action object. The schemas for each trade action type are defined below. enum TradeActionType { // (uint8 TradeActionType, uint8 MarketIndex, uint88 fCashAmount, uint32 minImpliedRate, uint120 unused) Lend, // (uint8 TradeActionType, uint8 MarketIndex, uint88 fCashAmount, uint32 maxImpliedRate, uint128 unused) Borrow, // (uint8 TradeActionType, uint8 MarketIndex, uint88 primeCashAmount, uint32 minImpliedRate, uint32 maxImpliedRate, uint88 unused) AddLiquidity, // (uint8 TradeActionType, uint8 MarketIndex, uint88 tokenAmount, uint32 minImpliedRate, uint32 maxImpliedRate, uint88 unused) RemoveLiquidity, // (uint8 TradeActionType, uint32 Maturity, int88 fCashResidualAmount, uint128 unused) PurchaseNTokenResidual, // (uint8 TradeActionType, address CounterpartyAddress, int88 fCashAmountToSettle) SettleCashDebt } /// @notice Specifies different deposit actions that can occur during BalanceAction or BalanceActionWithTrades enum DepositActionType { // No deposit action None, // Deposit asset cash, depositActionAmount is specified in asset cash external precision DepositAsset, // Deposit underlying tokens that are mintable to asset cash, depositActionAmount is specified in underlying token // external precision DepositUnderlying, // Deposits specified asset cash external precision amount into an nToken and mints the corresponding amount of // nTokens into the account DepositAssetAndMintNToken, // Deposits specified underlying in external precision, mints asset cash, and uses that asset cash to mint nTokens DepositUnderlyingAndMintNToken, // Redeems an nToken balance to asset cash. depositActionAmount is specified in nToken precision. Considered a deposit action // because it deposits asset cash into an account. If there are fCash residuals that cannot be sold off, will revert. RedeemNToken, // Converts specified amount of asset cash balance already in Notional to nTokens. depositActionAmount is specified in // Notional internal 8 decimal precision. ConvertCashToNToken } /// @notice Used internally for PortfolioHandler state enum AssetStorageState { NoChange, Update, Delete, RevertIfStored } /****** Calldata objects ******/ /// @notice Defines a batch lending action struct BatchLend { uint16 currencyId; // True if the contract should try to transfer underlying tokens instead of asset tokens bool depositUnderlying; // Array of tightly packed 32 byte objects that represent trades. See TradeActionType documentation bytes32[] trades; } /// @notice Defines a balance action for batchAction struct BalanceAction { // Deposit action to take (if any) DepositActionType actionType; uint16 currencyId; // Deposit action amount must correspond to the depositActionType, see documentation above. uint256 depositActionAmount; // Withdraw an amount of asset cash specified in Notional internal 8 decimal precision uint256 withdrawAmountInternalPrecision; // If set to true, will withdraw entire cash balance. Useful if there may be an unknown amount of asset cash // residual left from trading. bool withdrawEntireCashBalance; // If set to true, will redeem asset cash to the underlying token on withdraw. bool redeemToUnderlying; } /// @notice Defines a balance action with a set of trades to do as well struct BalanceActionWithTrades { DepositActionType actionType; uint16 currencyId; uint256 depositActionAmount; uint256 withdrawAmountInternalPrecision; bool withdrawEntireCashBalance; bool redeemToUnderlying; // Array of tightly packed 32 byte objects that represent trades. See TradeActionType documentation bytes32[] trades; } /****** In memory objects ******/ /// @notice Internal object that represents settled cash balances struct SettleAmount { uint16 currencyId; int256 positiveSettledCash; int256 negativeSettledCash; PrimeRate presentPrimeRate; } /// @notice Internal object that represents a token struct Token { address tokenAddress; bool hasTransferFee; int256 decimals; TokenType tokenType; uint256 deprecated_maxCollateralBalance; } /// @notice Internal object that represents an nToken portfolio struct nTokenPortfolio { CashGroupParameters cashGroup; PortfolioState portfolioState; int256 totalSupply; int256 cashBalance; uint256 lastInitializedTime; bytes6 parameters; address tokenAddress; } /// @notice Internal object used during liquidation struct LiquidationFactors { address account; // Aggregate free collateral of the account denominated in ETH underlying, 8 decimal precision int256 netETHValue; // Amount of net local currency asset cash before haircuts and buffers available int256 localPrimeAvailable; // Amount of net collateral currency asset cash before haircuts and buffers available int256 collateralAssetAvailable; // Haircut value of nToken holdings denominated in asset cash, will be local or collateral nTokens based // on liquidation type int256 nTokenHaircutPrimeValue; // nToken parameters for calculating liquidation amount bytes6 nTokenParameters; // ETH exchange rate from local currency to ETH ETHRate localETHRate; // ETH exchange rate from collateral currency to ETH ETHRate collateralETHRate; // Asset rate for the local currency, used in cross currency calculations to calculate local asset cash required PrimeRate localPrimeRate; // Used during currency liquidations if the account has liquidity tokens CashGroupParameters collateralCashGroup; // Used during currency liquidations if it is only a calculation, defaults to false bool isCalculation; } /// @notice Internal asset array portfolio state struct PortfolioState { // Array of currently stored assets PortfolioAsset[] storedAssets; // Array of new assets to add PortfolioAsset[] newAssets; uint256 lastNewAssetIndex; // Holds the length of stored assets after accounting for deleted assets uint256 storedAssetLength; } /// @notice In memory ETH exchange rate used during free collateral calculation. struct ETHRate { // The decimals (i.e. 10^rateDecimalPlaces) of the exchange rate, defined by the rate oracle int256 rateDecimals; // The exchange rate from base to ETH (if rate invert is required it is already done) int256 rate; // Amount of buffer as a multiple with a basis of 100 applied to negative balances. int256 buffer; // Amount of haircut as a multiple with a basis of 100 applied to positive balances int256 haircut; // Liquidation discount as a multiple with a basis of 100 applied to the exchange rate // as an incentive given to liquidators. int256 liquidationDiscount; } /// @notice Internal object used to handle balance state during a transaction struct BalanceState { uint16 currencyId; // Cash balance stored in balance state at the beginning of the transaction int256 storedCashBalance; // nToken balance stored at the beginning of the transaction int256 storedNTokenBalance; // The net cash change as a result of asset settlement or trading int256 netCashChange; // Amount of prime cash to redeem and withdraw from the system int256 primeCashWithdraw; // Net token transfers into or out of the account int256 netNTokenTransfer; // Net token supply change from minting or redeeming int256 netNTokenSupplyChange; // The last time incentives were claimed for this currency uint256 lastClaimTime; // Accumulator for incentives that the account no longer has a claim over uint256 accountIncentiveDebt; // Prime rate for converting prime cash balances PrimeRate primeRate; } /// @dev Asset rate used to convert between underlying cash and asset cash struct Deprecated_AssetRateParameters { // Address of the asset rate oracle AssetRateAdapter rateOracle; // The exchange rate from base to quote (if invert is required it is already done) int256 rate; // The decimals of the underlying, the rate converts to the underlying decimals int256 underlyingDecimals; } /// @dev Cash group when loaded into memory struct CashGroupParameters { uint16 currencyId; uint256 maxMarketIndex; PrimeRate primeRate; bytes32 data; } /// @dev A portfolio asset when loaded in memory struct PortfolioAsset { // Asset currency id uint16 currencyId; uint256 maturity; // Asset type, fCash or liquidity token. uint256 assetType; // fCash amount or liquidity token amount int256 notional; // Used for managing portfolio asset state uint256 storageSlot; // The state of the asset for when it is written to storage AssetStorageState storageState; } /// @dev Market object as represented in memory struct MarketParameters { bytes32 storageSlot; uint256 maturity; // Total amount of fCash available for purchase in the market. int256 totalfCash; // Total amount of cash available for purchase in the market. int256 totalPrimeCash; // Total amount of liquidity tokens (representing a claim on liquidity) in the market. int256 totalLiquidity; // This is the previous annualized interest rate in RATE_PRECISION that the market traded // at. This is used to calculate the rate anchor to smooth interest rates over time. uint256 lastImpliedRate; // Time lagged version of lastImpliedRate, used to value fCash assets at market rates while // remaining resistent to flash loan attacks. uint256 oracleRate; // This is the timestamp of the previous trade uint256 previousTradeTime; } /****** Storage objects ******/ /// @dev Token object in storage: /// 20 bytes for token address /// 1 byte for hasTransferFee /// 1 byte for tokenType /// 1 byte for tokenDecimals /// 9 bytes for maxCollateralBalance (may not always be set) struct TokenStorage { // Address of the token address tokenAddress; // Transfer fees will change token deposit behavior bool hasTransferFee; TokenType tokenType; uint8 decimalPlaces; uint72 deprecated_maxCollateralBalance; } /// @dev Exchange rate object as it is represented in storage, total storage is 25 bytes. struct ETHRateStorage { // Address of the rate oracle AggregatorV2V3Interface rateOracle; // The decimal places of precision that the rate oracle uses uint8 rateDecimalPlaces; // True of the exchange rate must be inverted bool mustInvert; // NOTE: both of these governance values are set with BUFFER_DECIMALS precision // Amount of buffer to apply to the exchange rate for negative balances. uint8 buffer; // Amount of haircut to apply to the exchange rate for positive balances uint8 haircut; // Liquidation discount in percentage point terms, 106 means a 6% discount uint8 liquidationDiscount; } /// @dev Asset rate oracle object as it is represented in storage, total storage is 21 bytes. struct AssetRateStorage { // Address of the rate oracle AssetRateAdapter rateOracle; // The decimal places of the underlying asset uint8 underlyingDecimalPlaces; } /// @dev Governance parameters for a cash group, total storage is 9 bytes + 7 bytes for liquidity token haircuts /// and 7 bytes for rate scalars, total of 23 bytes. Note that this is stored packed in the storage slot so there /// are no indexes stored for liquidityTokenHaircuts or rateScalars, maxMarketIndex is used instead to determine the /// length. struct CashGroupSettings { // Index of the AMMs on chain that will be made available. Idiosyncratic fCash // that is dated less than the longest AMM will be tradable. uint8 maxMarketIndex; // Time window in 5 minute increments that the rate oracle will be averaged over uint8 rateOracleTimeWindow5Min; // Absolute maximum discount factor as a discount from 1e9, specified in five basis points // subtracted from 1e9 uint8 maxDiscountFactor5BPS; // Share of the fees given to the protocol, denominated in percentage uint8 reserveFeeShare; // Debt buffer specified in 5 BPS increments uint8 debtBuffer25BPS; // fCash haircut specified in 5 BPS increments uint8 fCashHaircut25BPS; // Minimum oracle interest rates for fCash per market, specified in 25 bps increments uint8 minOracleRate25BPS; // If an account has fCash that is being liquidated, this is the discount that the liquidator can purchase it for uint8 liquidationfCashHaircut25BPS; // If an account has fCash that is being liquidated, this is the discount that the liquidator can purchase it for uint8 liquidationDebtBuffer25BPS; // Max oracle rate specified in 25bps increments as a discount from the max rate in the market. uint8 maxOracleRate25BPS; } /// @dev Holds account level context information used to determine settlement and /// free collateral actions. Total storage is 28 bytes struct AccountContext { // Used to check when settlement must be triggered on an account uint40 nextSettleTime; // For lenders that never incur debt, we use this flag to skip the free collateral check. bytes1 hasDebt; // Length of the account's asset array uint8 assetArrayLength; // If this account has bitmaps set, this is the corresponding currency id uint16 bitmapCurrencyId; // 9 total active currencies possible (2 bytes each) bytes18 activeCurrencies; // If this is set to true, the account can borrow variable prime cash and incur // negative cash balances inside BatchAction. This does not impact the settlement // of negative fCash to prime cash which will happen regardless of this setting. This // exists here mainly as a safety setting to ensure that accounts do not accidentally // incur negative cash balances. bool allowPrimeBorrow; } /// @dev Holds nToken context information mapped via the nToken address, total storage is /// 16 bytes struct nTokenContext { // Currency id that the nToken represents uint16 currencyId; // Annual incentive emission rate denominated in WHOLE TOKENS (multiply by // INTERNAL_TOKEN_PRECISION to get the actual rate) uint32 incentiveAnnualEmissionRate; // The last block time at utc0 that the nToken was initialized at, zero if it // has never been initialized uint32 lastInitializedTime; // Length of the asset array, refers to the number of liquidity tokens an nToken // currently holds uint8 assetArrayLength; // Each byte is a specific nToken parameter bytes6 nTokenParameters; // Reserved bytes for future usage bytes14 _unused; // Set to true if a secondary rewarder is set bool hasSecondaryRewarder; } /// @dev Holds account balance information, total storage 32 bytes struct BalanceStorage { // Number of nTokens held by the account uint80 nTokenBalance; // Last time the account claimed their nTokens uint32 lastClaimTime; // Incentives that the account no longer has a claim over uint56 accountIncentiveDebt; // Cash balance of the account int88 cashBalance; } /// @dev Holds information about a settlement rate, total storage 25 bytes struct SettlementRateStorage { uint40 blockTime; uint128 settlementRate; uint8 underlyingDecimalPlaces; } /// @dev Holds information about a market, total storage is 42 bytes so this spans /// two storage words struct MarketStorage { // Total fCash in the market uint80 totalfCash; // Total asset cash in the market uint80 totalPrimeCash; // Last annualized interest rate the market traded at uint32 lastImpliedRate; // Last recorded oracle rate for the market uint32 oracleRate; // Last time a trade was made uint32 previousTradeTime; // This is stored in slot + 1 uint80 totalLiquidity; } struct InterestRateParameters { // First kink for the utilization rate in RATE_PRECISION uint256 kinkUtilization1; // Second kink for the utilization rate in RATE_PRECISION uint256 kinkUtilization2; // First kink interest rate in RATE_PRECISION uint256 kinkRate1; // Second kink interest rate in RATE_PRECISION uint256 kinkRate2; // Max interest rate in RATE_PRECISION uint256 maxRate; // Minimum fee charged in RATE_PRECISION uint256 minFeeRate; // Maximum fee charged in RATE_PRECISION uint256 maxFeeRate; // Percentage of the interest rate that will be applied as a fee uint256 feeRatePercent; } // Specific interest rate curve settings for each market struct InterestRateCurveSettings { // First kink for the utilization rate, specified as a percentage // between 1-100 uint8 kinkUtilization1; // Second kink for the utilization rate, specified as a percentage // between 1-100 uint8 kinkUtilization2; // Interest rate at the first kink, set as 1/256 units from the kink // rate max uint8 kinkRate1; // Interest rate at the second kink, set as 1/256 units from the kink // rate max uint8 kinkRate2; // Max interest rate, set in units in 25bps increments less than or equal to 150 // and 150bps increments from 151 to 255. uint8 maxRateUnits; // Minimum fee charged in basis points uint8 minFeeRate5BPS; // Maximum fee charged in basis points uint8 maxFeeRate25BPS; // Percentage of the interest rate that will be applied as a fee uint8 feeRatePercent; } struct ifCashStorage { // Notional amount of fCash at the slot, limited to int128 to allow for // future expansion int128 notional; } /// @dev A single portfolio asset in storage, total storage of 19 bytes struct PortfolioAssetStorage { // Currency Id for the asset uint16 currencyId; // Maturity of the asset uint40 maturity; // Asset type (fCash or Liquidity Token marker) uint8 assetType; // Notional int88 notional; } /// @dev nToken total supply factors for the nToken, includes factors related /// to claiming incentives, total storage 32 bytes. This is the deprecated version struct nTokenTotalSupplyStorage_deprecated { // Total supply of the nToken uint96 totalSupply; // Integral of the total supply used for calculating the average total supply uint128 integralTotalSupply; // Last timestamp the supply value changed, used for calculating the integralTotalSupply uint32 lastSupplyChangeTime; } /// @dev nToken total supply factors for the nToken, includes factors related /// to claiming incentives, total storage 32 bytes. struct nTokenTotalSupplyStorage { // Total supply of the nToken uint96 totalSupply; // How many NOTE incentives should be issued per nToken in 1e18 precision uint128 accumulatedNOTEPerNToken; // Last timestamp when the accumulation happened uint32 lastAccumulatedTime; } /// @dev Used in view methods to return account balances in a developer friendly manner struct AccountBalance { uint16 currencyId; int256 cashBalance; int256 nTokenBalance; uint256 lastClaimTime; uint256 accountIncentiveDebt; } struct VaultConfigParams { uint16 flags; uint16 borrowCurrencyId; uint256 minAccountBorrowSize; uint16 minCollateralRatioBPS; uint8 feeRate5BPS; uint8 liquidationRate; uint8 reserveFeeShare; uint8 maxBorrowMarketIndex; uint16 maxDeleverageCollateralRatioBPS; uint16[2] secondaryBorrowCurrencies; uint16 maxRequiredAccountCollateralRatioBPS; uint256[2] minAccountSecondaryBorrow; uint8 excessCashLiquidationBonus; } struct VaultConfigStorage { // Vault Flags (documented in VaultConfiguration.sol) uint16 flags; // Primary currency the vault borrows in uint16 borrowCurrencyId; // Specified in whole tokens in 1e8 precision, allows a 4.2 billion min borrow size uint32 minAccountBorrowSize; // Minimum collateral ratio for a vault specified in basis points, valid values are greater than 10_000 // where the largest minimum collateral ratio is 65_536 which is much higher than anything reasonable. uint16 minCollateralRatioBPS; // Allows up to a 12.75% annualized fee uint8 feeRate5BPS; // A percentage that represents the share of the cash raised that will go to the liquidator uint8 liquidationRate; // A percentage of the fee given to the protocol uint8 reserveFeeShare; // Maximum market index where a vault can borrow from uint8 maxBorrowMarketIndex; // Maximum collateral ratio that a liquidator can push a an account to during deleveraging uint16 maxDeleverageCollateralRatioBPS; // An optional list of secondary borrow currencies uint16[2] secondaryBorrowCurrencies; // Required collateral ratio for accounts to stay inside a vault, prevents accounts // from "free riding" on vaults. Enforced on entry and exit, not on deleverage. uint16 maxRequiredAccountCollateralRatioBPS; // Specified in whole tokens in 1e8 precision, allows a 4.2 billion min borrow size uint32[2] minAccountSecondaryBorrow; // Specified as a percent discount off the exchange rate of the excess cash that will be paid to // the liquidator during liquidateExcessVaultCash uint8 excessCashLiquidationBonus; // 8 bytes left } struct VaultBorrowCapacityStorage { // Total fCash across all maturities that caps the borrow capacity uint80 maxBorrowCapacity; // Total fCash debt across all maturities uint80 totalfCashDebt; } struct VaultAccountSecondaryDebtShareStorage { // Maturity for the account's secondary borrows. This is stored separately from // the vault account maturity to ensure that we have access to the proper state // during a roll borrow position. It should never be allowed to deviate from the // vaultAccount.maturity value (unless it is cleared to zero). uint40 maturity; // Account debt for the first secondary currency in either fCash or pCash denomination uint80 accountDebtOne; // Account debt for the second secondary currency in either fCash or pCash denomination uint80 accountDebtTwo; } struct VaultConfig { address vault; uint16 flags; uint16 borrowCurrencyId; int256 minAccountBorrowSize; int256 feeRate; int256 minCollateralRatio; int256 liquidationRate; int256 reserveFeeShare; uint256 maxBorrowMarketIndex; int256 maxDeleverageCollateralRatio; uint16[2] secondaryBorrowCurrencies; PrimeRate primeRate; int256 maxRequiredAccountCollateralRatio; int256[2] minAccountSecondaryBorrow; int256 excessCashLiquidationBonus; } /// @notice Represents a Vault's current borrow and collateral state struct VaultStateStorage { // This represents the total amount of borrowing in the vault for the current // vault term. If the vault state is the prime cash maturity, this is stored in // prime cash debt denomination, if fCash then it is stored in internal underlying. uint80 totalDebt; // The total amount of prime cash in the pool held as a result of emergency settlement uint80 deprecated_totalPrimeCash; // Total vault shares in this maturity uint80 totalVaultShares; // Set to true if a vault's debt position has been migrated to the prime cash vault bool isSettled; // NOTE: 8 bits left // ----- This breaks into a new storage slot ------- // The total amount of strategy tokens held in the pool uint80 deprecated_totalStrategyTokens; // Valuation of a strategy token at settlement int80 deprecated_settlementStrategyTokenValue; // NOTE: 96 bits left } /// @notice Represents the remaining assets in a vault post settlement struct Deprecated_VaultSettledAssetsStorage { // Remaining strategy tokens that have not been withdrawn uint80 remainingStrategyTokens; // Remaining asset cash that has not been withdrawn int80 remainingPrimeCash; } struct VaultState { uint256 maturity; // Total debt is always denominated in underlying on the stack int256 totalDebtUnderlying; uint256 totalVaultShares; bool isSettled; } /// @notice Represents an account's position within an individual vault struct VaultAccountStorage { // Total amount of debt for the account in the primary borrowed currency. // If the account is borrowing prime cash, this is stored in prime cash debt // denomination, if fCash then it is stored in internal underlying. uint80 accountDebt; // Vault shares that the account holds uint80 vaultShares; // Maturity when the vault shares and fCash will mature uint40 maturity; // Last time when a vault was entered or exited, used to ensure that vault accounts do not // flash enter/exit. While there is no specified attack vector here, we can use it to prevent // an entire class of attacks from happening without reducing UX. // NOTE: in the original version this value was set to the block.number, however, in this // version it is being changed to time based. On ETH mainnet block heights are much smaller // than block times, accounts that migrate from lastEntryBlockHeight => lastUpdateBlockTime // will not see any issues with entering / exiting the protocol. uint32 lastUpdateBlockTime; // ---------------- Second Storage Slot ---------------------- // Cash balances held by the vault account as a result of lending at zero interest or due // to deleveraging (liquidation). In the previous version of leveraged vaults, accounts would // simply lend at zero interest which was not a problem. However, with vaults being able to // discount fCash to present value, lending at zero percent interest may have an adverse effect // on the account's collateral position (i.e. lending at zero puts them further into danger). // Holding cash against debt will eliminate that risk, making vault liquidation more similar to // regular Notional liquidation. uint80 primaryCash; uint80 secondaryCashOne; uint80 secondaryCashTwo; } struct VaultAccount { // On the stack, account debts are always in underlying int256 accountDebtUnderlying; uint256 maturity; uint256 vaultShares; address account; // This cash balance is used just within a transaction to track deposits // and withdraws for an account. Must be zeroed by the time we store the account int256 tempCashBalance; uint256 lastUpdateBlockTime; } // Used to hold vault account liquidation factors in memory struct VaultAccountHealthFactors { // Account's calculated collateral ratio int256 collateralRatio; // Total outstanding debt across all borrowed currencies in primary int256 totalDebtOutstandingInPrimary; // Total value of vault shares in underlying denomination int256 vaultShareValueUnderlying; // Debt outstanding in local currency denomination after present value and // account cash held netting applied. Can be positive if the account holds cash // in excess of debt. int256[3] netDebtOutstanding; } // PrimeCashInterestRateParameters take up 16 bytes, this takes up 32 bytes so we // can expand another 16 bytes to increase the storage slots a bit.... struct PrimeCashFactorsStorage { // Storage slot 1 [Prime Supply Factors, 248 bytes] uint40 lastAccrueTime; uint88 totalPrimeSupply; uint88 lastTotalUnderlyingValue; // Overflows at 429% interest using RATE_PRECISION uint32 oracleSupplyRate; bool allowDebt; // Storage slot 2 [Prime Debt Factors, 256 bytes] uint88 totalPrimeDebt; // Each one of these values below is stored as a FloatingPoint32 value which // gives us approx 7 digits of precision for each value. Because these are used // to maintain supply and borrow caps, they are not required to be exact. uint32 maxUnderlyingSupply; // The maximum utilization that prime debt is allowed to reach by users borrowing prime // debt via the markets directly. This cap is not applied to liquidations and settlement. uint8 maxPrimeDebtUtilization; uint120 _reserved; // Reserving the next 128 bytes for future use in case we decide to implement debt // caps on a currency. In that case, we will need to track the total fcash overall // and subtract the total debt held in vaults. // uint32 maxUnderlyingDebt; // uint32 totalfCashDebtOverall; // uint32 totalfCashDebtInVaults; // uint32 totalPrimeDebtInVaults; // 8 bytes left // Storage slot 3 [Prime Scalars, 240 bytes] // Scalars are stored in 18 decimal precision (i.e. double rate precision) and uint80 // maxes out at approx 1,210,000e18 // ln(1,210,000) = rate * years = 14 // Approx 46 years at 30% interest // Approx 233 years at 6% interest uint80 underlyingScalar; uint80 supplyScalar; uint80 debtScalar; // The time window in 5 min increments that the rate oracle will be averaged over uint8 rateOracleTimeWindow5Min; // 8 bytes left } struct PrimeCashFactors { uint256 lastAccrueTime; uint256 totalPrimeSupply; uint256 totalPrimeDebt; uint256 oracleSupplyRate; uint256 lastTotalUnderlyingValue; uint256 underlyingScalar; uint256 supplyScalar; uint256 debtScalar; uint256 rateOracleTimeWindow; } struct PrimeRate { int256 supplyFactor; int256 debtFactor; uint256 oracleSupplyRate; } struct PrimeSettlementRateStorage { uint80 supplyScalar; uint80 debtScalar; uint80 underlyingScalar; bool isSet; } struct PrimeCashHoldingsOracle { IPrimeCashHoldingsOracle oracle; } // Per currency rebalancing context struct RebalancingContextStorage { // Holds the previous supply factor to calculate the oracle money market rate uint128 previousSupplyFactorAtRebalance; // Rebalancing has a cool down period that sets the time averaging of the oracle money market rate uint40 rebalancingCooldownInSeconds; uint40 lastRebalanceTimestampInSeconds; // 48 bytes left } struct TotalfCashDebtStorage { uint80 totalfCashDebt; // These two variables are used to track fCash lend at zero // edge conditions for leveraged vaults. uint80 fCashDebtHeldInSettlementReserve; uint80 primeCashHeldInSettlementReserve; } struct RebalancingTargetData { uint8 targetUtilization; uint16 externalWithdrawThreshold; }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity =0.7.6; import {Deployments} from "../../../global/Deployments.sol"; import {IEIP20NonStandard} from "../../../../interfaces/IEIP20NonStandard.sol"; import {SafeUint256} from "../../../math/SafeUint256.sol"; library GenericToken { using SafeUint256 for uint256; event LowLevelCallFailed(address indexed target, uint256 msgValue, bytes callData, string revertMessage); function transferNativeTokenOut( address account, uint256 amount, bool withdrawWrapped ) internal { // Native token withdraws are processed using .transfer() which is may not work // for certain contracts that do not implement receive() with minimal gas requirements. // Prior to the prime cash upgrade, these contracts could withdraw cETH, however, post // upgrade they no longer have this option. For these contracts, wrap the Native token // (i.e. WETH) and transfer that as an ERC20 instead. if (withdrawWrapped) { Deployments.WETH.deposit{value: amount}(); safeTransferOut(address(Deployments.WETH), account, amount); } else { // TODO: consider using .call with a manual amount of gas forwarding payable(account).transfer(amount); } } function safeTransferOut( address token, address account, uint256 amount ) internal { IEIP20NonStandard(token).transfer(account, amount); checkReturnCode(); } function safeTransferIn( address token, address account, uint256 amount ) internal returns (uint256) { uint256 startingBalance = IEIP20NonStandard(token).balanceOf(address(this)); IEIP20NonStandard(token).transferFrom(account, address(this), amount); checkReturnCode(); uint256 endingBalance = IEIP20NonStandard(token).balanceOf(address(this)); return endingBalance.sub(startingBalance); } function safeTransferFrom( address token, address from, address to, uint256 amount ) internal { IEIP20NonStandard(token).transferFrom(from, to, amount); checkReturnCode(); } function executeLowLevelCall( address target, uint256 msgValue, bytes memory callData ) internal { (bool status, bytes memory returnData) = target.call{value: msgValue}(callData); require(status, checkRevertMessage(returnData)); } function checkRevertMessage(bytes memory returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (returnData.length < 68) return "Silent Revert"; assembly { // Slice the sighash. returnData := add(returnData, 0x04) } return abi.decode(returnData, (string)); // All that remains is the revert string } function checkReturnCode() internal pure { bool success; uint256[1] memory result; assembly { switch returndatasize() case 0 { // This is a non-standard ERC-20 success := 1 // set success to true } case 32 { // This is a compliant ERC-20 returndatacopy(result, 0, 32) success := mload(result) // Set `success = returndata` of external call } default { // This is an excessively non-compliant ERC-20, revert. revert(0, 0) } } require(success, "ERC20"); } }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity =0.7.6; pragma abicoder v2; import {Constants} from "../global/Constants.sol"; /// @notice Helper methods for bitmaps, they are big-endian and 1-indexed. library Bitmap { /// @notice Set a bit on or off in a bitmap, index is 1-indexed function setBit( bytes32 bitmap, uint256 index, bool setOn ) internal pure returns (bytes32) { require(index >= 1 && index <= 256); // dev: set bit index bounds if (setOn) { return bitmap | (Constants.MSB >> (index - 1)); } else { return bitmap & ~(Constants.MSB >> (index - 1)); } } /// @notice Check if a bit is set function isBitSet(bytes32 bitmap, uint256 index) internal pure returns (bool) { require(index >= 1 && index <= 256); // dev: set bit index bounds return ((bitmap << (index - 1)) & Constants.MSB) == Constants.MSB; } /// @notice Count the total bits set function totalBitsSet(bytes32 bitmap) internal pure returns (uint256) { uint256 x = uint256(bitmap); x = (x & 0x5555555555555555555555555555555555555555555555555555555555555555) + (x >> 1 & 0x5555555555555555555555555555555555555555555555555555555555555555); x = (x & 0x3333333333333333333333333333333333333333333333333333333333333333) + (x >> 2 & 0x3333333333333333333333333333333333333333333333333333333333333333); x = (x & 0x0707070707070707070707070707070707070707070707070707070707070707) + (x >> 4); x = (x & 0x000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F) + (x >> 8 & 0x000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F); x = x + (x >> 16); x = x + (x >> 32); x = x + (x >> 64); return (x & 0xFF) + (x >> 128 & 0xFF); } // Does a binary search over x to get the position of the most significant bit function getMSB(uint256 x) internal pure returns (uint256 msb) { // If x == 0 then there is no MSB and this method will return zero. That would // be the same as the return value when x == 1 (MSB is zero indexed), so instead // we have this require here to ensure that the values don't get mixed up. require(x != 0); // dev: get msb zero value if (x >= 0x100000000000000000000000000000000) { x >>= 128; msb += 128; } if (x >= 0x10000000000000000) { x >>= 64; msb += 64; } if (x >= 0x100000000) { x >>= 32; msb += 32; } if (x >= 0x10000) { x >>= 16; msb += 16; } if (x >= 0x100) { x >>= 8; msb += 8; } if (x >= 0x10) { x >>= 4; msb += 4; } if (x >= 0x4) { x >>= 2; msb += 2; } if (x >= 0x2) msb += 1; // No need to shift xc anymore } /// @dev getMSB returns a zero indexed bit number where zero is the first bit counting /// from the right (little endian). Asset Bitmaps are counted from the left (big endian) /// and one indexed. function getNextBitNum(bytes32 bitmap) internal pure returns (uint256 bitNum) { // Short circuit the search if bitmap is all zeros if (bitmap == 0x00) return 0; return 255 - getMSB(uint256(bitmap)) + 1; } }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity =0.7.6; import {Bitmap} from "./Bitmap.sol"; import {SafeInt256} from "./SafeInt256.sol"; import {SafeUint256} from "./SafeUint256.sol"; /** * Packs an uint value into a "floating point" storage slot. Used for storing * lastClaimIntegralSupply values in balance storage. For these values, we don't need * to maintain exact precision but we don't want to be limited by storage size overflows. * * A floating point value is defined by the 48 most significant bits and an 8 bit number * of bit shifts required to restore its precision. The unpacked value will always be less * than the packed value with a maximum absolute loss of precision of (2 ** bitShift) - 1. */ library FloatingPoint { using SafeInt256 for int256; using SafeUint256 for uint256; function packTo56Bits(uint256 value) internal pure returns (uint56) { uint256 bitShift; // If the value is over the uint48 max value then we will shift it down // given the index of the most significant bit. We store this bit shift // in the least significant byte of the 56 bit slot available. if (value > type(uint48).max) bitShift = (Bitmap.getMSB(value) - 47); uint256 shiftedValue = value >> bitShift; return uint56((shiftedValue << 8) | bitShift); } function packTo32Bits(uint256 value) internal pure returns (uint32) { uint256 bitShift; // If the value is over the uint24 max value then we will shift it down // given the index of the most significant bit. We store this bit shift // in the least significant byte of the 32 bit slot available. if (value > type(uint24).max) bitShift = (Bitmap.getMSB(value) - 23); uint256 shiftedValue = value >> bitShift; return uint32((shiftedValue << 8) | bitShift); } function unpackFromBits(uint256 value) internal pure returns (uint256) { // The least significant 8 bits will be the amount to bit shift uint256 bitShift = uint256(uint8(value)); return ((value >> 8) << bitShift); } }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity =0.7.6; import {Constants} from "../global/Constants.sol"; library SafeInt256 { int256 private constant _INT256_MIN = type(int256).min; /// @dev Returns the multiplication of two signed integers, reverting on /// overflow. /// Counterpart to Solidity's `*` operator. /// Requirements: /// - Multiplication cannot overflow. function mul(int256 a, int256 b) internal pure returns (int256 c) { c = a * b; if (a == -1) require (b == 0 || c / b == a); else require (a == 0 || c / a == b); } /// @dev Returns the integer division of two signed integers. Reverts on /// division by zero. The result is rounded towards zero. /// Counterpart to Solidity's `/` operator. Note: this function uses a /// `revert` opcode (which leaves remaining gas untouched) while Solidity /// uses an invalid opcode to revert (consuming all remaining gas). /// Requirements: /// - The divisor cannot be zero. function div(int256 a, int256 b) internal pure returns (int256 c) { require(!(b == -1 && a == _INT256_MIN)); // dev: int256 div overflow // NOTE: solidity will automatically revert on divide by zero c = a / b; } function sub(int256 x, int256 y) internal pure returns (int256 z) { // taken from uniswap v3 require((z = x - y) <= x == (y >= 0)); } function add(int256 x, int256 y) internal pure returns (int256 z) { require((z = x + y) >= x == (y >= 0)); } function neg(int256 x) internal pure returns (int256 y) { return mul(-1, x); } function abs(int256 x) internal pure returns (int256) { if (x < 0) return neg(x); else return x; } function subNoNeg(int256 x, int256 y) internal pure returns (int256 z) { z = sub(x, y); require(z >= 0); // dev: int256 sub to negative return z; } /// @dev Calculates x * RATE_PRECISION / y while checking overflows function divInRatePrecision(int256 x, int256 y) internal pure returns (int256) { return div(mul(x, Constants.RATE_PRECISION), y); } /// @dev Calculates x * y / RATE_PRECISION while checking overflows function mulInRatePrecision(int256 x, int256 y) internal pure returns (int256) { return div(mul(x, y), Constants.RATE_PRECISION); } function toUint(int256 x) internal pure returns (uint256) { require(x >= 0); return uint256(x); } function toInt(uint256 x) internal pure returns (int256) { require (x <= uint256(type(int256).max)); // dev: toInt overflow return int256(x); } function toInt80(int256 x) internal pure returns (int80) { require (int256(type(int80).min) <= x && x <= int256(type(int80).max)); // dev: toInt overflow return int80(x); } function toInt88(int256 x) internal pure returns (int88) { require (int256(type(int88).min) <= x && x <= int256(type(int88).max)); // dev: toInt overflow return int88(x); } function toInt128(int256 x) internal pure returns (int128) { require (int256(type(int128).min) <= x && x <= int256(type(int128).max)); // dev: toInt overflow return int128(x); } function max(int256 x, int256 y) internal pure returns (int256) { return x > y ? x : y; } function min(int256 x, int256 y) internal pure returns (int256) { return x < y ? x : y; } /// @notice Returns the net change in negative signed values, used for /// determining the (positive) amount of debt change function negChange(int256 start, int256 end) internal pure returns (int256) { // No change in these two scenarios if (start == end || (start >= 0 && end >= 0)) return 0; if (start <= 0 && 0 < end) { // Negative portion has been eliminated so the net change on the // negative side is start (i.e. a reduction in the negative balance) return start; } else if (end <= 0 && 0 < start) { // Entire negative portion has been created so the net change on the // negative side is -end (i.e. an increase in the negative balance) return neg(end); } else if (start <= 0 && end <= 0) { // There is some net change in the negative amounts. // If start < end then this is negative, debt has been reduced // If end < start then this is positive, debt has been increased return sub(start, end); } // Should never get to this point revert(); } }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity =0.7.6; import {Constants} from "../global/Constants.sol"; library SafeUint256 { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0); return a / b; } function max(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? x : y; } function min(uint256 x, uint256 y) internal pure returns (uint256) { return x < y ? x : y; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0); return a % b; } function divInRatePrecision(uint256 x, uint256 y) internal pure returns (uint256) { return div(mul(x, uint256(Constants.RATE_PRECISION)), y); } function mulInRatePrecision(uint256 x, uint256 y) internal pure returns (uint256) { return div(mul(x, y), uint256(Constants.RATE_PRECISION)); } function divInScalarPrecision(uint256 x, uint256 y) internal pure returns (uint256) { return div(mul(x, Constants.SCALAR_PRECISION), y); } function mulInScalarPrecision(uint256 x, uint256 y) internal pure returns (uint256) { return div(mul(x, y), Constants.SCALAR_PRECISION); } function toUint8(uint256 x) internal pure returns (uint8) { require(x <= type(uint8).max); return uint8(x); } function toUint32(uint256 x) internal pure returns (uint32) { require(x <= type(uint32).max); return uint32(x); } function toUint40(uint256 x) internal pure returns (uint40) { require(x <= type(uint40).max); return uint40(x); } function toUint48(uint256 x) internal pure returns (uint48) { require(x <= type(uint48).max); return uint48(x); } function toUint56(uint256 x) internal pure returns (uint56) { require(x <= type(uint56).max); return uint56(x); } function toUint72(uint256 x) internal pure returns (uint72) { require(x <= type(uint72).max); return uint72(x); } function toUint80(uint256 x) internal pure returns (uint80) { require(x <= type(uint80).max); return uint80(x); } function toUint88(uint256 x) internal pure returns (uint88) { require(x <= type(uint88).max); return uint88(x); } function toUint104(uint256 x) internal pure returns (uint104) { require(x <= type(uint104).max); return uint104(x); } function toUint112(uint256 x) internal pure returns (uint112) { require(x <= type(uint112).max); return uint112(x); } function toUint128(uint256 x) internal pure returns (uint128) { require(x <= type(uint128).max); return uint128(x); } function toInt(uint256 x) internal pure returns (int256) { require (x <= uint256(type(int256).max)); // dev: toInt overflow return int256(x); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.3.2 (proxy/beacon/IBeacon.sol) pragma solidity >=0.7.6; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); } interface IUpgradeableBeacon is IBeacon { function upgradeTo(address newImplementation) external; }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; struct LendingPoolStorage { ILendingPool lendingPool; } interface ILendingPool { /** * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. * - E.g. User deposits 100 USDC and gets in return 100 aUSDC * @param asset The address of the underlying asset to deposit * @param amount The amount to be deposited * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens * is a different wallet * @param referralCode Code used to register the integrator originating the operation, for potential rewards. * 0 if the action is executed directly by the user, without any middle-man **/ function deposit( address asset, uint256 amount, address onBehalfOf, uint16 referralCode ) external; /** * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC * @param asset The address of the underlying asset to withdraw * @param amount The underlying amount to be withdrawn * - Send the value type(uint256).max in order to withdraw the whole aToken balance * @param to Address that will receive the underlying, same as msg.sender if the user * wants to receive it on his own wallet, or a different address if the beneficiary is a * different wallet * @return The final amount withdrawn **/ function withdraw( address asset, uint256 amount, address to ) external returns (uint256); /** * @dev Returns the normalized income normalized income of the reserve * @param asset The address of the underlying asset of the reserve * @return The reserve's normalized income */ function getReserveNormalizedIncome(address asset) external view returns (uint256); /** * @dev Returns the state and configuration of the reserve * @param asset The address of the underlying asset of the reserve * @return The state of the reserve **/ function getReserveData(address asset) external view returns (ReserveData memory); struct ReserveData { ReserveConfigurationMap configuration; uint128 liquidityIndex; uint128 currentLiquidityRate; uint128 variableBorrowIndex; uint128 currentVariableBorrowRate; uint128 currentStableBorrowRate; uint40 lastUpdateTimestamp; uint16 id; address aTokenAddress; address stableDebtTokenAddress; address variableDebtTokenAddress; address interestRateStrategyAddress; uint128 accruedToTreasury; uint128 unbacked; uint128 isolationModeTotalDebt; } struct ReserveConfigurationMap { //bit 0-15: LTV //bit 16-31: Liq. threshold //bit 32-47: Liq. bonus //bit 48-55: Decimals //bit 56: Reserve is active //bit 57: reserve is frozen //bit 58: borrowing is enabled //bit 59: stable rate borrowing enabled //bit 60-63: reserved //bit 64-79: reserve factor uint256 data; } struct UserConfigurationMap { uint256 data; } enum InterestRateMode {NONE, STABLE, VARIABLE} }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; interface AggregatorInterface { function latestAnswer() external view returns (int256); function latestTimestamp() external view returns (uint256); function latestRound() external view returns (uint256); function getAnswer(uint256 roundId) external view returns (int256); function getTimestamp(uint256 roundId) external view returns (uint256); event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import "./AggregatorInterface.sol"; import "./AggregatorV3Interface.sol"; interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface { }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; /** * @title EIP20NonStandardInterface * @dev Version of ERC20 with no return values for `transfer` and `transferFrom` * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca */ interface IEIP20NonStandard { /** * @notice Get the total number of tokens in circulation * @return The supply of tokens */ function totalSupply() external view returns (uint256); /** * @notice Gets the balance of the specified address * @param owner The address from which the balance will be retrieved * @return balance */ function balanceOf(address owner) external view returns (uint256 balance); /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Transfer `amount` tokens from `msg.sender` to `dst` * @param dst The address of the destination account * @param amount The number of tokens to transfer */ function transfer(address dst, uint256 amount) external; /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Transfer `amount` tokens from `src` to `dst` * @param src The address of the source account * @param dst The address of the destination account * @param amount The number of tokens to transfer */ function transferFrom(address src, address dst, uint256 amount) external; /// /// !!!!!!!!!!!!!! /// !!! NOTICE !!! `approve` does not return a value, in violation of the ERC-20 specification /// !!!!!!!!!!!!!! /// /** * @notice Approve `spender` to transfer up to `amount` from `src` * @dev This will overwrite the approval amount for `spender` * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve) * @param spender The address of the account which may transfer tokens * @param amount The number of tokens that are approved */ function approve(address spender, uint256 amount) external; /** * @notice Get the current allowance from `owner` for `spender` * @param owner The address of the account which owns the tokens to be spent * @param spender The address of the account which may transfer tokens * @return remaining The number of tokens allowed to be spent */ function allowance(address owner, address spender) external view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); }
// SPDX-License-Identifier: MIT pragma solidity >=0.7.6; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); function decimals() external view returns (uint8); /** * @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 `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool); /** * @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); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.0; /// @notice Used as a wrapper for tokens that are interest bearing for an /// underlying token. Follows the cToken interface, however, can be adapted /// for other interest bearing tokens. interface AssetRateAdapter { function token() external view returns (address); function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function underlying() external view returns (address); function getExchangeRateStateful() external returns (int256); function getExchangeRateView() external view returns (int256); function getAnnualizedSupplyRate() external view returns (uint256); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.0; pragma abicoder v2; struct DepositData { address[] targets; bytes[] callData; uint256[] msgValue; uint256 underlyingDepositAmount; address assetToken; uint8 rebasingTokenBalanceAdjustment; } struct RedeemData { address[] targets; bytes[] callData; uint256 expectedUnderlying; address assetToken; uint8 rebasingTokenBalanceAdjustment; } struct OracleData { address holding; uint256 externalUnderlyingAvailableForWithdraw; uint256 currentExternalUnderlyingLend; uint256 maxExternalDeposit; } interface IPrimeCashHoldingsOracle { /// @notice Returns a list of the various holdings for the prime cash /// currency function holdings() external view returns (address[] memory); /// @notice Returns the underlying token that all holdings can be redeemed /// for. function underlying() external view returns (address); /// @notice Returns the native decimal precision of the underlying token function decimals() external view returns (uint8); /// @notice Returns the total underlying held by the caller in all the /// listed holdings function getTotalUnderlyingValueStateful() external returns ( uint256 nativePrecision, uint256 internalPrecision ); function getTotalUnderlyingValueView() external view returns ( uint256 nativePrecision, uint256 internalPrecision ); /// @notice Returns calldata for how to withdraw an amount function getRedemptionCalldata(uint256 withdrawAmount) external view returns ( RedeemData[] memory redeemData ); function holdingValuesInUnderlying() external view returns (uint256[] memory); function getRedemptionCalldataForRebalancing( address[] calldata _holdings, uint256[] calldata withdrawAmounts ) external view returns ( RedeemData[] memory redeemData ); function getDepositCalldataForRebalancing( address[] calldata _holdings, uint256[] calldata depositAmounts ) external view returns ( DepositData[] memory depositData ); function getOracleData() external view returns (OracleData memory); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; interface IRewarder { event RewardTransfer(address indexed rewardToken, address indexed account, uint256 amount); event RewardEmissionUpdate(uint256 emissionRatePerYear, uint256 endTime); function NTOKEN_ADDRESS() external returns(address); function CURRENCY_ID() external returns(uint16); function detached() external returns(bool); function claimRewards( address account, uint16 currencyId, uint256 nTokenBalanceBefore, uint256 nTokenBalanceAfter, uint256 totalSupply ) external; function getAccountRewardClaim(address account, uint32 blockTime) external returns (uint256); function getAccountRewardClaim(address account, uint256 nTokenBalanceAtDetach, bytes32[] calldata proof) external returns (uint256); function claimRewardsDirect(address account, uint256 nTokenBalanceAtDetach, bytes32[] calldata proof) external; function accumulatedRewardPerNToken() external returns (uint128); function lastAccumulatedTime() external returns (uint32); function emissionRatePerYear() external returns (uint128); function detach() external; }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import { VaultConfigParams, VaultConfigStorage, VaultConfig, VaultState, VaultAccount, VaultAccountHealthFactors, PrimeRate } from "../../contracts/global/Types.sol"; interface IVaultAction { /// @notice Emitted when a new vault is listed or updated event VaultUpdated(address indexed vault, bool enabled, uint80 maxPrimaryBorrowCapacity); /// @notice Emitted when a vault's status is updated event VaultPauseStatus(address indexed vault, bool enabled); /// @notice Emitted when a vault's deleverage status is updated event VaultDeleverageStatus(address indexed vaultAddress, bool disableDeleverage); /// @notice Emitted when a secondary currency borrow capacity is updated event VaultUpdateSecondaryBorrowCapacity(address indexed vault, uint16 indexed currencyId, uint80 maxSecondaryBorrowCapacity); /// @notice Emitted when the borrow capacity on a vault changes event VaultBorrowCapacityChange(address indexed vault, uint16 indexed currencyId, uint256 totalUsedBorrowCapacity); /// @notice Emitted when a vault executes a secondary borrow event VaultSecondaryTransaction( address indexed vault, address indexed account, uint16 indexed currencyId, uint256 maturity, int256 netUnderlyingDebt, int256 netPrimeSupply ); /** Vault Action Methods */ /// @notice Governance only method to whitelist a particular vault function updateVault( address vaultAddress, VaultConfigParams memory vaultConfig, uint80 maxPrimaryBorrowCapacity ) external; /// @notice Governance only method to pause a particular vault function setVaultPauseStatus( address vaultAddress, bool enable ) external; function setVaultDeleverageStatus( address vaultAddress, bool disableDeleverage ) external; /// @notice Governance only method to set the borrow capacity function setMaxBorrowCapacity( address vaultAddress, uint80 maxVaultBorrowCapacity ) external; /// @notice Governance only method to update a vault's secondary borrow capacity function updateSecondaryBorrowCapacity( address vaultAddress, uint16 secondaryCurrencyId, uint80 maxBorrowCapacity ) external; function borrowSecondaryCurrencyToVault( address account, uint256 maturity, uint256[2] calldata underlyingToBorrow, uint32[2] calldata maxBorrowRate, uint32[2] calldata minRollLendRate ) external returns (int256[2] memory underlyingTokensTransferred); function repaySecondaryCurrencyFromVault( address account, uint256 maturity, uint256[2] calldata underlyingToRepay, uint32[2] calldata minLendRate ) external payable returns (int256[2] memory underlyingDepositExternal); function settleSecondaryBorrowForAccount(address vault, address account) external; } interface IVaultAccountAction { /** * @notice Borrows a specified amount of fCash in the vault's borrow currency and deposits it * all plus the depositAmountExternal into the vault to mint strategy tokens. * * @param account the address that will enter the vault * @param vault the vault to enter * @param depositAmountExternal some amount of additional collateral in the borrowed currency * to be transferred to vault * @param maturity the maturity to borrow at * @param fCash amount to borrow * @param maxBorrowRate maximum interest rate to borrow at * @param vaultData additional data to pass to the vault contract */ function enterVault( address account, address vault, uint256 depositAmountExternal, uint256 maturity, uint256 fCash, uint32 maxBorrowRate, bytes calldata vaultData ) external payable returns (uint256 strategyTokensAdded); /** * @notice Re-enters the vault at a longer dated maturity. The account's existing borrow * position will be closed and a new borrow position at the specified maturity will be * opened. All strategy token holdings will be rolled forward. * * @param account the address that will reenter the vault * @param vault the vault to reenter * @param fCashToBorrow amount of fCash to borrow in the next maturity * @param maturity new maturity to borrow at */ function rollVaultPosition( address account, address vault, uint256 fCashToBorrow, uint256 maturity, uint256 depositAmountExternal, uint32 minLendRate, uint32 maxBorrowRate, bytes calldata enterVaultData ) external payable returns (uint256 strategyTokensAdded); /** * @notice Prior to maturity, allows an account to withdraw their position from the vault. Will * redeem some number of vault shares to the borrow currency and close the borrow position by * lending `fCashToLend`. Any shortfall in cash from lending will be transferred from the account, * any excess profits will be transferred to the account. * * Post maturity, will net off the account's debt against vault cash balances and redeem all remaining * strategy tokens back to the borrowed currency and transfer the profits to the account. * * @param account the address that will exit the vault * @param vault the vault to enter * @param vaultSharesToRedeem amount of vault tokens to exit, only relevant when exiting pre-maturity * @param fCashToLend amount of fCash to lend * @param minLendRate the minimum rate to lend at * @param exitVaultData passed to the vault during exit * @return underlyingToReceiver amount of underlying tokens returned to the receiver on exit */ function exitVault( address account, address vault, address receiver, uint256 vaultSharesToRedeem, uint256 fCashToLend, uint32 minLendRate, bytes calldata exitVaultData ) external payable returns (uint256 underlyingToReceiver); function settleVaultAccount(address account, address vault) external; } interface IVaultLiquidationAction { event VaultDeleverageAccount( address indexed vault, address indexed account, uint16 currencyId, uint256 vaultSharesToLiquidator, int256 depositAmountPrimeCash ); event VaultLiquidatorProfit( address indexed vault, address indexed account, address indexed liquidator, uint256 vaultSharesToLiquidator, bool transferSharesToLiquidator ); event VaultAccountCashLiquidation( address indexed vault, address indexed account, address indexed liquidator, uint16 currencyId, int256 fCashDeposit, int256 cashToLiquidator ); /** * @notice If an account is below the minimum collateral ratio, this method wil deleverage (liquidate) * that account. `depositAmountExternal` in the borrow currency will be transferred from the liquidator * and used to offset the account's debt position. The liquidator will receive either vaultShares or * cash depending on the vault's configuration. * @param account the address that will exit the vault * @param vault the vault to enter * @param liquidator the address that will receive profits from liquidation * @param depositAmountPrimeCash amount of cash to deposit * @return vaultSharesFromLiquidation amount of vaultShares received from liquidation */ function deleverageAccount( address account, address vault, address liquidator, uint16 currencyIndex, int256 depositUnderlyingInternal ) external payable returns (uint256 vaultSharesFromLiquidation, int256 depositAmountPrimeCash); function liquidateVaultCashBalance( address account, address vault, address liquidator, uint256 currencyIndex, int256 fCashDeposit ) external returns (int256 cashToLiquidator); function liquidateExcessVaultCash( address account, address vault, address liquidator, uint256 excessCashIndex, uint256 debtIndex, uint256 _depositUnderlyingInternal ) external payable returns (int256 cashToLiquidator); } interface IVaultAccountHealth { function getVaultAccountHealthFactors(address account, address vault) external view returns ( VaultAccountHealthFactors memory h, int256[3] memory maxLiquidatorDepositUnderlying, uint256[3] memory vaultSharesToLiquidator ); function calculateDepositAmountInDeleverage( uint256 currencyIndex, VaultAccount memory vaultAccount, VaultConfig memory vaultConfig, VaultState memory vaultState, int256 depositUnderlyingInternal ) external returns (int256 depositInternal, uint256 vaultSharesToLiquidator, PrimeRate memory); function getfCashRequiredToLiquidateCash( uint16 currencyId, uint256 maturity, int256 vaultAccountCashBalance ) external view returns (int256 fCashRequired, int256 discountFactor); function checkVaultAccountCollateralRatio(address vault, address account, bool checkDebtCap) external; function getVaultAccount(address account, address vault) external view returns (VaultAccount memory); function getVaultAccountWithFeeAccrual( address account, address vault ) external view returns (VaultAccount memory, int256 accruedPrimeVaultFeeInUnderlying); function getVaultConfig(address vault) external view returns (VaultConfig memory vaultConfig); function getBorrowCapacity(address vault, uint16 currencyId) external view returns ( uint256 currentPrimeDebtUnderlying, uint256 totalfCashDebt, uint256 maxBorrowCapacity ); function getSecondaryBorrow(address vault, uint16 currencyId, uint256 maturity) external view returns (int256 totalDebt); /// @notice View method to get vault state function getVaultState(address vault, uint256 maturity) external view returns (VaultState memory vaultState); function getVaultAccountSecondaryDebt(address account, address vault) external view returns ( uint256 maturity, int256[2] memory accountSecondaryDebt, int256[2] memory accountSecondaryCashHeld ); function signedBalanceOfVaultTokenId(address account, uint256 id) external view returns (int256); } interface IVaultController is IVaultAccountAction, IVaultAction, IVaultLiquidationAction, IVaultAccountHealth {}
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import "../../contracts/global/Types.sol"; interface nERC1155Interface { event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); event ApprovalForAll(address indexed account, address indexed operator, bool approved); event URI(string value, uint256 indexed id); function supportsInterface(bytes4 interfaceId) external pure returns (bool); function balanceOf(address account, uint256 id) external view returns (uint256); function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); function signedBalanceOf(address account, uint256 id) external view returns (int256); function signedBalanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (int256[] memory); function setApprovalForAll(address operator, bool approved) external; function isApprovedForAll(address account, address operator) external view returns (bool); function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external payable; function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external payable; function decodeToAssets(uint256[] calldata ids, uint256[] calldata amounts) external view returns (PortfolioAsset[] memory); function encodeToId( uint16 currencyId, uint40 maturity, uint8 assetType ) external pure returns (uint256 id); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import "../../contracts/global/Types.sol"; interface NotionalCalculations { function calculateNTokensToMint(uint16 currencyId, uint88 amountToDepositExternalPrecision) external view returns (uint256); function nTokenPresentValueAssetDenominated(uint16 currencyId) external view returns (int256); function nTokenPresentValueUnderlyingDenominated(uint16 currencyId) external view returns (int256); function convertNTokenToUnderlying(uint16 currencyId, int256 nTokenBalance) external view returns (int256); function getfCashAmountGivenCashAmount( uint16 currencyId, int88 netCashToAccount, uint256 marketIndex, uint256 blockTime ) external view returns (int256); function getCashAmountGivenfCashAmount( uint16 currencyId, int88 fCashAmount, uint256 marketIndex, uint256 blockTime ) external view returns (int256, int256); function nTokenGetClaimableIncentives(address account, uint256 blockTime) external view returns (uint256); function getPresentfCashValue( uint16 currencyId, uint256 maturity, int256 notional, uint256 blockTime, bool riskAdjusted ) external view returns (int256 presentValue); function getMarketIndex( uint256 maturity, uint256 blockTime ) external pure returns (uint8 marketIndex); function getfCashLendFromDeposit( uint16 currencyId, uint256 depositAmountExternal, uint256 maturity, uint32 minLendRate, uint256 blockTime, bool useUnderlying ) external view returns ( uint88 fCashAmount, uint8 marketIndex, bytes32 encodedTrade ); function getfCashBorrowFromPrincipal( uint16 currencyId, uint256 borrowedAmountExternal, uint256 maturity, uint32 maxBorrowRate, uint256 blockTime, bool useUnderlying ) external view returns ( uint88 fCashDebt, uint8 marketIndex, bytes32 encodedTrade ); function getDepositFromfCashLend( uint16 currencyId, uint256 fCashAmount, uint256 maturity, uint32 minLendRate, uint256 blockTime ) external view returns ( uint256 depositAmountUnderlying, uint256 depositAmountAsset, uint8 marketIndex, bytes32 encodedTrade ); function getPrincipalFromfCashBorrow( uint16 currencyId, uint256 fCashBorrow, uint256 maturity, uint32 maxBorrowRate, uint256 blockTime ) external view returns ( uint256 borrowAmountUnderlying, uint256 borrowAmountAsset, uint8 marketIndex, bytes32 encodedTrade ); function convertCashBalanceToExternal( uint16 currencyId, int256 cashBalanceInternal, bool useUnderlying ) external view returns (int256); function convertUnderlyingToPrimeCash( uint16 currencyId, int256 underlyingExternal ) external view returns (int256); function convertSettledfCash( uint16 currencyId, uint256 maturity, int256 fCashBalance, uint256 blockTime ) external view returns (int256 signedPrimeSupplyValue); function accruePrimeInterest( uint16 currencyId ) external returns (PrimeRate memory pr, PrimeCashFactors memory); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import "../../contracts/global/Deployments.sol"; import "../../contracts/global/Types.sol"; import "../../interfaces/chainlink/AggregatorV2V3Interface.sol"; import "../../interfaces/notional/NotionalGovernance.sol"; import "../../interfaces/notional/IRewarder.sol"; import "../../interfaces/aave/ILendingPool.sol"; import {IPrimeCashHoldingsOracle} from "../../interfaces/notional/IPrimeCashHoldingsOracle.sol"; interface NotionalGovernance { event ListCurrency(uint16 newCurrencyId); event UpdateETHRate(uint16 currencyId); event UpdateAssetRate(uint16 currencyId); event UpdateCashGroup(uint16 currencyId); event DeployNToken(uint16 currencyId, address nTokenAddress); event UpdateDepositParameters(uint16 currencyId); event UpdateInitializationParameters(uint16 currencyId); event UpdateTokenCollateralParameters(uint16 currencyId); event UpdateGlobalTransferOperator(address operator, bool approved); event UpdateAuthorizedCallbackContract(address operator, bool approved); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event PauseRouterAndGuardianUpdated(address indexed pauseRouter, address indexed pauseGuardian); event UpdateInterestRateCurve(uint16 indexed currencyId, uint8 indexed marketIndex); event UpdateMaxUnderlyingSupply(uint16 indexed currencyId, uint256 maxUnderlyingSupply); event PrimeProxyDeployed(uint16 indexed currencyId, address proxy, bool isCashProxy); function transferOwnership(address newOwner, bool direct) external; function claimOwnership() external; function upgradeBeacon(Deployments.BeaconType proxy, address newBeacon) external; function setPauseRouterAndGuardian(address pauseRouter_, address pauseGuardian_) external; function listCurrency( TokenStorage calldata underlyingToken, ETHRateStorage memory ethRate, InterestRateCurveSettings calldata primeDebtCurve, IPrimeCashHoldingsOracle primeCashHoldingsOracle, bool allowPrimeCashDebt, uint8 rateOracleTimeWindow5Min, string calldata underlyingName, string calldata underlyingSymbol ) external returns (uint16 currencyId); function enableCashGroup( uint16 currencyId, CashGroupSettings calldata cashGroup, string calldata underlyingName, string calldata underlyingSymbol ) external; function updateDepositParameters( uint16 currencyId, uint32[] calldata depositShares, uint32[] calldata leverageThresholds ) external; function updateInitializationParameters( uint16 currencyId, uint32[] calldata annualizedAnchorRates, uint32[] calldata proportions ) external; function updateTokenCollateralParameters( uint16 currencyId, uint8 residualPurchaseIncentive10BPS, uint8 pvHaircutPercentage, uint8 residualPurchaseTimeBufferHours, uint8 cashWithholdingBuffer10BPS, uint8 liquidationHaircutPercentage, uint8 maxMintDeviationPercentage ) external; function updateCashGroup(uint16 currencyId, CashGroupSettings calldata cashGroup) external; function updateInterestRateCurve( uint16 currencyId, uint8[] calldata marketIndices, InterestRateCurveSettings[] calldata settings ) external; function setMaxUnderlyingSupply( uint16 currencyId, uint256 maxUnderlyingSupply, uint8 maxPrimeDebtUtilization ) external; function updatePrimeCashHoldingsOracle( uint16 currencyId, IPrimeCashHoldingsOracle primeCashHoldingsOracle ) external; function updatePrimeCashCurve( uint16 currencyId, InterestRateCurveSettings calldata primeDebtCurve ) external; function enablePrimeDebt( uint16 currencyId, string calldata underlyingName, string calldata underlyingSymbol ) external; function updateETHRate( uint16 currencyId, AggregatorV2V3Interface rateOracle, bool mustInvert, uint8 buffer, uint8 haircut, uint8 liquidationDiscount ) external; function updateAuthorizedCallbackContract(address operator, bool approved) external; }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import "../../contracts/global/Types.sol"; import "./nTokenERC20.sol"; import "./nERC1155Interface.sol"; import "./NotionalGovernance.sol"; import "./NotionalCalculations.sol"; import "./NotionalViews.sol"; import "./NotionalTreasury.sol"; import {IVaultController} from "./IVaultController.sol"; interface NotionalProxy is nTokenERC20, nERC1155Interface, NotionalGovernance, NotionalTreasury, NotionalCalculations, NotionalViews, IVaultController { /** User trading events */ event MarketsInitialized(uint16 currencyId); event SweepCashIntoMarkets(uint16 currencyId, int256 cashIntoMarkets); /// @notice Emitted once when incentives are migrated event IncentivesMigrated( uint16 currencyId, uint256 migrationEmissionRate, uint256 finalIntegralTotalSupply, uint256 migrationTime ); /// @notice Emitted if a token address is migrated event TokenMigrated(uint16 currencyId) ; /// @notice Emitted whenever an account context has updated event AccountContextUpdate(address indexed account); /// @notice Emitted when an account has assets that are settled event AccountSettled(address indexed account); /* Liquidation Events */ event LiquidateLocalCurrency( address indexed liquidated, address indexed liquidator, uint16 localCurrencyId, int256 netLocalFromLiquidator ); event LiquidateCollateralCurrency( address indexed liquidated, address indexed liquidator, uint16 localCurrencyId, uint16 collateralCurrencyId, int256 netLocalFromLiquidator, int256 netCollateralTransfer, int256 netNTokenTransfer ); event LiquidatefCashEvent( address indexed liquidated, address indexed liquidator, uint16 localCurrencyId, uint16 fCashCurrency, int256 netLocalFromLiquidator, uint256[] fCashMaturities, int256[] fCashNotionalTransfer ); event SetPrimeSettlementRate( uint256 indexed currencyId, uint256 indexed maturity, int256 supplyFactor, int256 debtFactor ); /// @notice Emits every time interest is accrued event PrimeCashInterestAccrued( uint16 indexed currencyId, uint256 underlyingScalar, uint256 supplyScalar, uint256 debtScalar ); event PrimeCashCurveChanged(uint16 indexed currencyId); event PrimeCashHoldingsOracleUpdated(uint16 indexed currencyId, address oracle); /** UUPS Upgradeable contract calls */ function upgradeTo(address newImplementation) external; function upgradeToAndCall(address newImplementation, bytes memory data) external payable; function getImplementation() external view returns (address); function owner() external view returns (address); function pauseRouter() external view returns (address); function pauseGuardian() external view returns (address); /** Initialize Markets Action */ function initializeMarkets(uint16 currencyId, bool isFirstInit) external; function sweepCashIntoMarkets(uint16 currencyId) external; /** Account Action */ function nTokenRedeem( address redeemer, uint16 currencyId, uint96 tokensToRedeem_ ) external returns (int256); function enablePrimeBorrow(bool allowPrimeBorrow) external; function enableBitmapCurrency(uint16 currencyId) external; function settleAccount(address account) external; function depositUnderlyingToken( address account, uint16 currencyId, uint256 amountExternalPrecision ) external payable returns (uint256); function withdraw( uint16 currencyId, uint88 amountInternalPrecision, bool redeemToUnderlying ) external returns (uint256); function withdrawViaProxy( uint16 currencyId, address owner, address receiver, address spender, uint88 withdrawAmountPrimeCash ) external returns (uint256); /** Batch Action */ function batchBalanceAction(address account, BalanceAction[] calldata actions) external payable; function batchBalanceAndTradeAction(address account, BalanceActionWithTrades[] calldata actions) external payable; function batchBalanceAndTradeActionWithCallback( address account, BalanceActionWithTrades[] calldata actions, bytes calldata callbackData ) external payable; function batchLend(address account, BatchLend[] calldata actions) external; /** Liquidation Action */ function calculateLocalCurrencyLiquidation( address liquidateAccount, uint16 localCurrency, uint96 maxNTokenLiquidation ) external returns (int256, int256); function liquidateLocalCurrency( address liquidateAccount, uint16 localCurrency, uint96 maxNTokenLiquidation ) external payable returns (int256, int256); function calculateCollateralCurrencyLiquidation( address liquidateAccount, uint16 localCurrency, uint16 collateralCurrency, uint128 maxCollateralLiquidation, uint96 maxNTokenLiquidation ) external returns (int256, int256, int256); function liquidateCollateralCurrency( address liquidateAccount, uint16 localCurrency, uint16 collateralCurrency, uint128 maxCollateralLiquidation, uint96 maxNTokenLiquidation, bool withdrawCollateral, bool redeemToUnderlying ) external payable returns (int256, int256, int256); function calculatefCashLocalLiquidation( address liquidateAccount, uint16 localCurrency, uint256[] calldata fCashMaturities, uint256[] calldata maxfCashLiquidateAmounts ) external returns (int256[] memory, int256); function liquidatefCashLocal( address liquidateAccount, uint16 localCurrency, uint256[] calldata fCashMaturities, uint256[] calldata maxfCashLiquidateAmounts ) external payable returns (int256[] memory, int256); function calculatefCashCrossCurrencyLiquidation( address liquidateAccount, uint16 localCurrency, uint16 fCashCurrency, uint256[] calldata fCashMaturities, uint256[] calldata maxfCashLiquidateAmounts ) external returns (int256[] memory, int256); function liquidatefCashCrossCurrency( address liquidateAccount, uint16 localCurrency, uint16 fCashCurrency, uint256[] calldata fCashMaturities, uint256[] calldata maxfCashLiquidateAmounts ) external payable returns (int256[] memory, int256); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import {IRewarder} from "./IRewarder.sol"; interface NotionalTreasury { event UpdateIncentiveEmissionRate(uint16 currencyId, uint32 newEmissionRate); event UpdateSecondaryIncentiveRewarder(uint16 indexed currencyId, address rewarder); struct RebalancingTargetConfig { address holding; uint8 targetUtilization; uint16 externalWithdrawThreshold; } /// @notice Emitted when reserve balance is updated event ReserveBalanceUpdated(uint16 indexed currencyId, int256 newBalance); /// @notice Emitted when reserve balance is harvested event ExcessReserveBalanceHarvested(uint16 indexed currencyId, int256 harvestAmount); /// @dev Emitted when treasury manager is updated event TreasuryManagerChanged(address indexed previousManager, address indexed newManager); /// @dev Emitted when reserve buffer value is updated event ReserveBufferUpdated(uint16 currencyId, uint256 bufferAmount); event RebalancingTargetsUpdated(uint16 currencyId, RebalancingTargetConfig[] targets); event RebalancingCooldownUpdated(uint16 currencyId, uint40 cooldownTimeInSeconds); event CurrencyRebalanced(uint16 currencyId, uint256 supplyFactor, uint256 annualizedInterestRate); /// @notice Emitted when the interest accrued on asset deposits is harvested event AssetInterestHarvested(uint16 indexed currencyId, address assetToken, uint256 harvestAmount); function transferReserveToTreasury(uint16[] calldata currencies) external returns (uint256[] memory); function harvestAssetInterest(uint16[] calldata currencies) external; function setTreasuryManager(address manager) external; function setRebalancingBot(address _rebalancingBot) external; function setReserveBuffer(uint16 currencyId, uint256 amount) external; function setReserveCashBalance(uint16 currencyId, int256 reserveBalance) external; function setRebalancingTargets(uint16 currencyId, RebalancingTargetConfig[] calldata targets) external; function setRebalancingCooldown(uint16 currencyId, uint40 cooldownTimeInSeconds) external; function checkRebalance() external view returns (uint16[] memory currencyIds); function rebalance(uint16 currencyId) external; function updateIncentiveEmissionRate(uint16 currencyId, uint32 newEmissionRate) external; function setSecondaryIncentiveRewarder(uint16 currencyId, IRewarder rewarder) external; }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; import "../../contracts/global/Types.sol"; interface NotionalViews { function getMaxCurrencyId() external view returns (uint16); function getCurrencyId(address tokenAddress) external view returns (uint16 currencyId); function getCurrency(uint16 currencyId) external view returns (Token memory assetToken, Token memory underlyingToken); function getRateStorage(uint16 currencyId) external view returns (ETHRateStorage memory ethRate, AssetRateStorage memory assetRate); function getCurrencyAndRates(uint16 currencyId) external view returns ( Token memory assetToken, Token memory underlyingToken, ETHRate memory ethRate, Deprecated_AssetRateParameters memory assetRate ); function getCashGroup(uint16 currencyId) external view returns (CashGroupSettings memory); function getCashGroupAndAssetRate(uint16 currencyId) external view returns (CashGroupSettings memory cashGroup, Deprecated_AssetRateParameters memory assetRate); function getInterestRateCurve(uint16 currencyId) external view returns ( InterestRateParameters[] memory nextInterestRateCurve, InterestRateParameters[] memory activeInterestRateCurve ); function getInitializationParameters(uint16 currencyId) external view returns (int256[] memory annualizedAnchorRates, int256[] memory proportions); function getDepositParameters(uint16 currencyId) external view returns (int256[] memory depositShares, int256[] memory leverageThresholds); function nTokenAddress(uint16 currencyId) external view returns (address); function pCashAddress(uint16 currencyId) external view returns (address); function pDebtAddress(uint16 currencyId) external view returns (address); function getNoteToken() external view returns (address); function getOwnershipStatus() external view returns (address owner, address pendingOwner); function getGlobalTransferOperatorStatus(address operator) external view returns (bool isAuthorized); function getAuthorizedCallbackContractStatus(address callback) external view returns (bool isAuthorized); function getSecondaryIncentiveRewarder(uint16 currencyId) external view returns (address incentiveRewarder); function getPrimeFactors(uint16 currencyId, uint256 blockTime) external view returns ( PrimeRate memory primeRate, PrimeCashFactors memory factors, uint256 maxUnderlyingSupply, uint256 totalUnderlyingSupply, uint256 maxUnderlyingDebt, uint256 totalUnderlyingDebt ); function getPrimeFactorsStored(uint16 currencyId) external view returns (PrimeCashFactors memory); function getPrimeCashHoldingsOracle(uint16 currencyId) external view returns (address); function getPrimeInterestRateCurve(uint16 currencyId) external view returns (InterestRateParameters memory); function getPrimeInterestRate(uint16 currencyId) external view returns ( uint256 annualDebtRatePreFee, uint256 annualDebtRatePostFee, uint256 annualSupplyRate ); function getTotalfCashDebtOutstanding(uint16 currencyId, uint256 maturity) external view returns ( int256 totalfCashDebt, int256 fCashDebtHeldInSettlementReserve, int256 primeCashHeldInSettlementReserve ); function getSettlementRate(uint16 currencyId, uint40 maturity) external view returns (PrimeRate memory); function getMarket( uint16 currencyId, uint256 maturity, uint256 settlementDate ) external view returns (MarketParameters memory); function getActiveMarkets(uint16 currencyId) external view returns (MarketParameters[] memory); function getActiveMarketsAtBlockTime(uint16 currencyId, uint32 blockTime) external view returns (MarketParameters[] memory); function getReserveBalance(uint16 currencyId) external view returns (int256 reserveBalance); function getNTokenPortfolio(address tokenAddress) external view returns (PortfolioAsset[] memory liquidityTokens, PortfolioAsset[] memory netfCashAssets); function getNTokenAccount(address tokenAddress) external view returns ( uint16 currencyId, uint256 totalSupply, uint256 incentiveAnnualEmissionRate, uint256 lastInitializedTime, bytes6 nTokenParameters, int256 cashBalance, uint256 accumulatedNOTEPerNToken, uint256 lastAccumulatedTime ); function getAccount(address account) external view returns ( AccountContext memory accountContext, AccountBalance[] memory accountBalances, PortfolioAsset[] memory portfolio ); function getAccountContext(address account) external view returns (AccountContext memory); function getAccountPrimeDebtBalance(uint16 currencyId, address account) external view returns ( int256 debtBalance ); function getAccountBalance(uint16 currencyId, address account) external view returns ( int256 cashBalance, int256 nTokenBalance, uint256 lastClaimTime ); function getBalanceOfPrimeCash( uint16 currencyId, address account ) external view returns (int256 cashBalance); function getAccountPortfolio(address account) external view returns (PortfolioAsset[] memory); function getfCashNotional( address account, uint16 currencyId, uint256 maturity ) external view returns (int256); function getAssetsBitmap(address account, uint16 currencyId) external view returns (bytes32); function getFreeCollateral(address account) external view returns (int256, int256[] memory); function getTreasuryManager() external view returns (address); function getReserveBuffer(uint16 currencyId) external view returns (uint256); function getRebalancingFactors(uint16 currencyId) external view returns (address holding, uint8 target, uint16 externalWithdrawThreshold, RebalancingContextStorage memory context); function getStoredTokenBalances(address[] calldata tokens) external view returns (uint256[] memory balances); function decodeERC1155Id(uint256 id) external view returns ( uint16 currencyId, uint256 maturity, uint256 assetType, address vaultAddress, bool isfCashDebt ); function encode( uint16 currencyId, uint256 maturity, uint256 assetType, address vaultAddress, bool isfCashDebt ) external pure returns (uint256); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; pragma abicoder v2; interface nTokenERC20 { event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); function nTokenTotalSupply(address nTokenAddress) external view returns (uint256); function nTokenBalanceOf(uint16 currencyId, address account) external view returns (uint256); function nTokenTransferAllowance( uint16 currencyId, address owner, address spender ) external view returns (uint256); function pCashTransferAllowance( uint16 currencyId, address owner, address spender ) external view returns (uint256); function nTokenTransferApprove( uint16 currencyId, address owner, address spender, uint256 amount ) external returns (bool); function pCashTransferApprove( uint16 currencyId, address owner, address spender, uint256 amount ) external returns (bool); function nTokenTransfer( uint16 currencyId, address from, address to, uint256 amount ) external returns (bool); function pCashTransfer( uint16 currencyId, address from, address to, uint256 amount ) external returns (bool); function nTokenTransferFrom( uint16 currencyId, address spender, address from, address to, uint256 amount ) external returns (bool); function pCashTransferFrom( uint16 currencyId, address spender, address from, address to, uint256 amount ) external returns (bool); function nTokenTransferApproveAll(address spender, uint256 amount) external returns (bool); function nTokenClaimIncentives() external returns (uint256); }
// SPDX-License-Identifier: BSUL-1.1 pragma solidity >=0.7.6; interface WETH9 { function deposit() external payable; function withdraw(uint256 wad) external; function transfer(address dst, uint256 wad) external returns (bool); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract NotionalProxy","name":"notional","type":"address"},{"internalType":"uint16","name":"currencyId","type":"uint16"},{"internalType":"contract IERC20","name":"incentive_token","type":"address"},{"internalType":"uint128","name":"_emissionRatePerYear","type":"uint128"},{"internalType":"uint32","name":"_endTime","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"emissionRatePerYear","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"RewardEmissionUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardTransfer","type":"event"},{"inputs":[],"name":"CURRENCY_ID","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NOTIONAL","outputs":[{"internalType":"contract NotionalProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NTOKEN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_TOKEN_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accumulatedRewardPerNToken","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint16","name":"currencyId","type":"uint16"},{"internalType":"uint256","name":"nTokenBalanceBefore","type":"uint256"},{"internalType":"uint256","name":"nTokenBalanceAfter","type":"uint256"},{"internalType":"uint256","name":"priorNTokenSupply","type":"uint256"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nTokenBalanceAtDetach","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claimRewardsDirect","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"detach","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"detached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emissionRatePerYear","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"nTokenBalanceAtDetach","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"getAccountRewardClaim","outputs":[{"internalType":"uint256","name":"rewardToClaim","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"blockTime","type":"uint32"}],"name":"getAccountRewardClaim","outputs":[{"internalType":"uint256","name":"rewardToClaim","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastAccumulatedTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardDebtPerAccount","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"_emissionRatePerYear","type":"uint128"},{"internalType":"uint32","name":"_endTime","type":"uint32"}],"name":"setIncentiveEmissionRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b5060405162001c7238038062001c72833981810160405260a08110156200003857600080fd5b5080516020808301516040808501516060808701516080978801519187901b6001600160601b03191690975260f084901b6001600160f01b0319166101005282516325d2c41560e21b815261ffff85166004820152925195969395919490926001600160a01b0388169263974b105492602480840193919291829003018186803b158015620000c657600080fd5b505afa158015620000db573d6000803e3d6000fd5b505050506040513d6020811015620000f257600080fd5b50516001600160601b0319606091821b811660a0529084901b1660c0526040805163313ce56760e01b815290516001600160a01b0385169163313ce567916004808301926020929190829003018186803b1580156200015057600080fd5b505afa15801562000165573d6000803e3d6000fd5b505050506040513d60208110156200017c57600080fd5b505160f81b7fff000000000000000000000000000000000000000000000000000000000000001660e052620001c66001600160801b03831662000291602090811b620010ad17901c565b6001805466ffffffffffffff60481b1916690100000000000000000066ffffffffffffff93909316929092029190911763ffffffff60281b1916650100000000004263ffffffff908116820292909217928390558382169204161062000266576040805162461bcd60e51b815260206004820152601060248201526f496e76616c696420456e642054696d6560801b604482015290519081900360640190fd5b6001805463ffffffff9092166101000264ffffffff0019909216919091179055506200037592505050565b60008065ffffffffffff831115620002bf57602f620002bb84620002ce60201b620010dc1760201c565b0390505b82811c60081b1790505b919050565b600081620002db57600080fd5b600160801b8210620002ef57608091821c91015b6801000000000000000082106200030857604091821c91015b64010000000082106200031d57602091821c91015b6201000082106200033057601091821c91015b61010082106200034257600891821c91015b601082106200035357600491821c91015b600482106200036457600291821c91015b60028210620002c957600101919050565b60805160601c60a05160601c60c05160601c60e05160f81c6101005160f01c61186d6200040560003980610a595280610dcf5250806104585280611535525080610d9552806112e752806113945250806105f25280610790528061086e5280610f225280610fcd5250806104df52806107bd52806109b25280610b015280610c475280610d71525061186d6000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80635705ae43116100ad5780639c07e54c116100715780639c07e54c146103705780639d4be3f514610378578063a105fc9614610397578063dacf76bd1461041c578063dadff3c41461044e5761012c565b80635705ae43146102d55780637cb64759146103015780637d43702f1461031e578063858dccb31461036057806399248ea7146103685761012c565b80632eb4a7ab116100f45780632eb4a7ab146102345780633197cbb61461024e5780633f3ef50d1461026f578063432cc1b3146102b15780634fd371e3146102cd5761012c565b80630330d663146101315780630537b3571461014f5780630e1e772f146101d65780631c92197614610208578063225435c01461022c575b600080fd5b610139610456565b6040805160ff9092168252519081900360200190f35b6101d46004803603606081101561016557600080fd5b6001600160a01b038235169160208101359181019060608101604082013564010000000081111561019557600080fd5b8201836020820111156101a757600080fd5b803590602001918460208302840111640100000000831117156101c957600080fd5b50909250905061047a565b005b6101d4600480360360408110156101ec57600080fd5b5080356001600160801b0316906020013563ffffffff166104dd565b61021061078e565b604080516001600160a01b039092168252519081900360200190f35b6101d46107b2565b61023c610990565b60408051918252519081900360200190f35b610256610996565b6040805163ffffffff9092168252519081900360200190f35b6101d4600480360360a081101561028557600080fd5b506001600160a01b038135169061ffff60208201351690604081013590606081013590608001356109a7565b6102b9610ae3565b604080519115158252519081900360200190f35b610256610aec565b6101d4600480360360408110156102eb57600080fd5b506001600160a01b038135169060200135610aff565b6101d46004803603602081101561031757600080fd5b5035610c45565b6103446004803603602081101561033457600080fd5b50356001600160a01b0316610d54565b604080516001600160801b039092168252519081900360200190f35b610210610d6f565b610210610d93565b610344610db7565b610380610dcd565b6040805161ffff9092168252519081900360200190f35b61023c600480360360608110156103ad57600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156103dd57600080fd5b8201836020820111156103ef57600080fd5b8035906020019184602083028401116401000000008311171561041157600080fd5b509092509050610df1565b61023c6004803603604081101561043257600080fd5b5080356001600160a01b0316906020013563ffffffff16610e7c565b610344611089565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015460ff166104c0576040805162461bcd60e51b815260206004820152600c60248201526b139bdd0819195d1858da195960a21b604482015290519081900360640190fd5b6104cc8484848461117a565b6104d7848485611244565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561053657600080fd5b505afa15801561054a573d6000803e3d6000fd5b505050506040513d602081101561056057600080fd5b50516001600160a01b031633146105ab576040805162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015290519081900360640190fd5b60015460ff16156105ee576040805162461bcd60e51b815260206004820152600860248201526711195d1858da195960c21b604482015290519081900360640190fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561064957600080fd5b505afa15801561065d573d6000803e3d6000fd5b505050506040513d602081101561067357600080fd5b5051905061068142826113fa565b610693836001600160801b03166110ad565b6001805466ffffffffffffff92909216600160481b0266ffffffffffffff60481b19909216919091179081905563ffffffff808416600160281b9092041610610716576040805162461bcd60e51b815260206004820152601060248201526f496e76616c696420456e642054696d6560801b604482015290519081900360640190fd5b6001805464ffffffff00191661010063ffffffff85160217908190557f5208ab6d453e25ff339785d249c1622a65a099886cb31e91ba4bce4987d3316c9061076d90600160481b900466ffffffffffffff1661147c565b6040805191825263ffffffff851660208301528051918290030190a1505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461081f576040805162461bcd60e51b815260206004820152600d60248201526c13db9b1e48139bdd1a5bdb985b609a1b604482015290519081900360640190fd5b60015460ff161561086a576040805162461bcd60e51b815260206004820152601060248201526f105b1c9958591e4819195d1858da195960821b604482015290519081900360640190fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108c557600080fd5b505afa1580156108d9573d6000803e3d6000fd5b505050506040513d60208110156108ef57600080fd5b505190506108fd42826113fa565b6001805460ff1916811766ffffffffffffff60481b191690819055610100900463ffffffff16421015610945576001805464ffffffff0019166101004263ffffffff16021790555b600154604080516000815261010090920463ffffffff16602083015280517f5208ab6d453e25ff339785d249c1622a65a099886cb31e91ba4bce4987d3316c9281900390910190a150565b60005481565b600154610100900463ffffffff1681565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a14576040805162461bcd60e51b815260206004820152600d60248201526c13db9b1e48139bdd1a5bdb985b609a1b604482015290519081900360640190fd5b60015460ff1615610a57576040805162461bcd60e51b815260206004820152600860248201526711195d1858da195960c21b604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff1614610ac7576040805162461bcd60e51b815260206004820152601160248201527015dc9bdb99c818dd5c9c995b98de481a59607a1b604482015290519081900360640190fd5b610ad142826113fa565b610adc858484611244565b5050505050565b60015460ff1681565b600154600160281b900463ffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5857600080fd5b505afa158015610b6c573d6000803e3d6000fd5b505050506040513d6020811015610b8257600080fd5b50516001600160a01b03163314610bcd576040805162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b038216610c3657604051600090339083908381818185875af1925050503d8060008114610c1d576040519150601f19603f3d011682016040523d82523d6000602084013e610c22565b606091505b5050905080610c3057600080fd5b50610c41565b610c4182338361148a565b5050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c9e57600080fd5b505afa158015610cb2573d6000803e3d6000fd5b505050506040513d6020811015610cc857600080fd5b50516001600160a01b03163314610d13576040805162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015290519081900360640190fd5b80610d4f576040805162461bcd60e51b8152602060048201526007602482015266125b9d985b1a5960ca1b604482015290519081900360640190fd5b600055565b6002602052600090815260409020546001600160801b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b600154600160801b90046001600160801b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015460009060ff168015610e07575060005415155b610e47576040805162461bcd60e51b815260206004820152600c60248201526b139bdd0819195d1858da195960a21b604482015290519081900360640190fd5b610e538585858561117a565b610e738585600160109054906101000a90046001600160801b0316611506565b95945050505050565b60015460009060ff1615610ec2576040805162461bcd60e51b815260206004820152600860248201526711195d1858da195960c21b604482015290519081900360640190fd5b60015463ffffffff808416600160281b909204161115610f1e576040805162461bcd60e51b8152602060048201526012602482015271496e76616c696420626c6f636b2074696d6560701b604482015290519081900360640190fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f7957600080fd5b505afa158015610f8d573d6000803e3d6000fd5b505050506040513d6020811015610fa357600080fd5b5051604080516370a0823160e01b81526001600160a01b03878116600483015291519293506000927f0000000000000000000000000000000000000000000000000000000000000000909216916370a0823191602480820192602092909190829003018186803b15801561101657600080fd5b505afa15801561102a573d6000803e3d6000fd5b505050506040513d602081101561104057600080fd5b50516001549091506000906110639063ffffffff80881691610100900416611592565b9050600061107182856115ac565b905061107e878483611506565b979650505050505050565b6001546000906110a890600160481b900466ffffffffffffff1661147c565b905090565b60008065ffffffffffff8311156110cd57602f6110c9846110dc565b0390505b82811c60081b1790505b919050565b6000816110e857600080fd5b600160801b82106110fb57608091821c91015b68010000000000000000821061111357604091821c91015b640100000000821061112757602091821c91015b62010000821061113957601091821c91015b610100821061114a57600891821c91015b6010821061115a57600491821c91015b6004821061116a57600291821c91015b600282106110d757600101919050565b6000848460405160200180836001600160a01b031660601b81526014018281526020019250505060405160208183030381529060405280519060200120905060006111fa84848080602002602001604051908101604052809392919081815260200183836020028082843760009201829052505492508691506116419050565b90508061123c576040805162461bcd60e51b815260206004820152600b60248201526a4e6f74496e4d65726b6c6560a81b604482015290519081900360640190fd5b505050505050565b60006112668484600160109054906101000a90046001600160801b0316611506565b6001549091506112a09061129b906305f5e10090611295908690600160801b90046001600160801b03166116ea565b90611711565b611730565b6001600160a01b038516600090815260026020526040902080546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905580156104d7577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb85836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561135c57600080fd5b505af192505050801561136d575060015b611376576104d7565b600061138061174a565b90508015610adc57846001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167fa282a314ffba449688a7c5eb4426bd8e1781944ce824ce34dfaea4691d08f146846040518082815260200191505060405180910390a35050505050565b600154610100900463ffffffff1661141157600080fd5b60015460009061142f9063ffffffff80861691610100900416611592565b905061143b81836115ac565b6001805463ffffffff4216600160281b0268ffffffff0000000000196001600160801b03948516600160801b02949092169390931716919091179055505050565b600881901c60ff9091161b90565b826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b1580156114e157600080fd5b505af11580156114f5573d6000803e3d6000fd5b50505050611501611785565b505050565b6001600160a01b03831660009081526002602052604081205461158a90670de0b6b3a7640000906112959060ff7f000000000000000000000000000000000000000000000000000000000000000016600a0a90611584906001600160801b039081169061157e906305f5e1009086908c908c166116ea565b906117f2565b906116ea565b949350505050565b60008183126115a157816115a3565b825b90505b92915050565b600154600090819063ffffffff808616600160281b909204161080156115d25750826000105b156116205760015463ffffffff600160281b909104811685031661161c846112956301da9c0081611601611089565b6001600160801b031661158487670de0b6b3a76400006116ea565b9150505b60015461158a9061129b90600160801b90046001600160801b031683611807565b600081815b85518110156116df57600086828151811061165d57fe5b602002602001015190508083116116a457828160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092506116d6565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b50600101611646565b509092149392505050565b6000826116f9575060006115a6565b8282028284828161170657fe5b04146115a357600080fd5b600080821161171f57600080fd5b81838161172857fe5b049392505050565b60006001600160801b0382111561174657600080fd5b5090565b6000611754611819565b3d801561176c57602081146117755760009250611780565b60019250611780565b60206000833e815192505b505090565b600061178f611819565b3d80156117a357602081146117ac57600080fd5b600192506117b7565b60206000833e815192505b5081610c41576040805162461bcd60e51b8152602060048201526005602482015264045524332360dc1b604482015290519081900360640190fd5b60008282111561180157600080fd5b50900390565b6000828201838110156115a357600080fd5b6040518060200160405280600190602082028036833750919291505056fea2646970667358221220a74639935b148d816e897ebe75f8648de6b80ed7bd5ef4f5bd1ebdddbd81bddb64736f6c634300070600330000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066c92280
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80635705ae43116100ad5780639c07e54c116100715780639c07e54c146103705780639d4be3f514610378578063a105fc9614610397578063dacf76bd1461041c578063dadff3c41461044e5761012c565b80635705ae43146102d55780637cb64759146103015780637d43702f1461031e578063858dccb31461036057806399248ea7146103685761012c565b80632eb4a7ab116100f45780632eb4a7ab146102345780633197cbb61461024e5780633f3ef50d1461026f578063432cc1b3146102b15780634fd371e3146102cd5761012c565b80630330d663146101315780630537b3571461014f5780630e1e772f146101d65780631c92197614610208578063225435c01461022c575b600080fd5b610139610456565b6040805160ff9092168252519081900360200190f35b6101d46004803603606081101561016557600080fd5b6001600160a01b038235169160208101359181019060608101604082013564010000000081111561019557600080fd5b8201836020820111156101a757600080fd5b803590602001918460208302840111640100000000831117156101c957600080fd5b50909250905061047a565b005b6101d4600480360360408110156101ec57600080fd5b5080356001600160801b0316906020013563ffffffff166104dd565b61021061078e565b604080516001600160a01b039092168252519081900360200190f35b6101d46107b2565b61023c610990565b60408051918252519081900360200190f35b610256610996565b6040805163ffffffff9092168252519081900360200190f35b6101d4600480360360a081101561028557600080fd5b506001600160a01b038135169061ffff60208201351690604081013590606081013590608001356109a7565b6102b9610ae3565b604080519115158252519081900360200190f35b610256610aec565b6101d4600480360360408110156102eb57600080fd5b506001600160a01b038135169060200135610aff565b6101d46004803603602081101561031757600080fd5b5035610c45565b6103446004803603602081101561033457600080fd5b50356001600160a01b0316610d54565b604080516001600160801b039092168252519081900360200190f35b610210610d6f565b610210610d93565b610344610db7565b610380610dcd565b6040805161ffff9092168252519081900360200190f35b61023c600480360360608110156103ad57600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156103dd57600080fd5b8201836020820111156103ef57600080fd5b8035906020019184602083028401116401000000008311171561041157600080fd5b509092509050610df1565b61023c6004803603604081101561043257600080fd5b5080356001600160a01b0316906020013563ffffffff16610e7c565b610344611089565b7f000000000000000000000000000000000000000000000000000000000000001281565b60015460ff166104c0576040805162461bcd60e51b815260206004820152600c60248201526b139bdd0819195d1858da195960a21b604482015290519081900360640190fd5b6104cc8484848461117a565b6104d7848485611244565b50505050565b7f0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561053657600080fd5b505afa15801561054a573d6000803e3d6000fd5b505050506040513d602081101561056057600080fd5b50516001600160a01b031633146105ab576040805162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015290519081900360640190fd5b60015460ff16156105ee576040805162461bcd60e51b815260206004820152600860248201526711195d1858da195960c21b604482015290519081900360640190fd5b60007f0000000000000000000000002f7350cb5e434c2d177922110c7e314953b84afc6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561064957600080fd5b505afa15801561065d573d6000803e3d6000fd5b505050506040513d602081101561067357600080fd5b5051905061068142826113fa565b610693836001600160801b03166110ad565b6001805466ffffffffffffff92909216600160481b0266ffffffffffffff60481b19909216919091179081905563ffffffff808416600160281b9092041610610716576040805162461bcd60e51b815260206004820152601060248201526f496e76616c696420456e642054696d6560801b604482015290519081900360640190fd5b6001805464ffffffff00191661010063ffffffff85160217908190557f5208ab6d453e25ff339785d249c1622a65a099886cb31e91ba4bce4987d3316c9061076d90600160481b900466ffffffffffffff1661147c565b6040805191825263ffffffff851660208301528051918290030190a1505050565b7f0000000000000000000000002f7350cb5e434c2d177922110c7e314953b84afc81565b336001600160a01b037f0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f161461081f576040805162461bcd60e51b815260206004820152600d60248201526c13db9b1e48139bdd1a5bdb985b609a1b604482015290519081900360640190fd5b60015460ff161561086a576040805162461bcd60e51b815260206004820152601060248201526f105b1c9958591e4819195d1858da195960821b604482015290519081900360640190fd5b60007f0000000000000000000000002f7350cb5e434c2d177922110c7e314953b84afc6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108c557600080fd5b505afa1580156108d9573d6000803e3d6000fd5b505050506040513d60208110156108ef57600080fd5b505190506108fd42826113fa565b6001805460ff1916811766ffffffffffffff60481b191690819055610100900463ffffffff16421015610945576001805464ffffffff0019166101004263ffffffff16021790555b600154604080516000815261010090920463ffffffff16602083015280517f5208ab6d453e25ff339785d249c1622a65a099886cb31e91ba4bce4987d3316c9281900390910190a150565b60005481565b600154610100900463ffffffff1681565b336001600160a01b037f0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f1614610a14576040805162461bcd60e51b815260206004820152600d60248201526c13db9b1e48139bdd1a5bdb985b609a1b604482015290519081900360640190fd5b60015460ff1615610a57576040805162461bcd60e51b815260206004820152600860248201526711195d1858da195960c21b604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000000000b61ffff168461ffff1614610ac7576040805162461bcd60e51b815260206004820152601160248201527015dc9bdb99c818dd5c9c995b98de481a59607a1b604482015290519081900360640190fd5b610ad142826113fa565b610adc858484611244565b5050505050565b60015460ff1681565b600154600160281b900463ffffffff1681565b7f0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b5857600080fd5b505afa158015610b6c573d6000803e3d6000fd5b505050506040513d6020811015610b8257600080fd5b50516001600160a01b03163314610bcd576040805162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015290519081900360640190fd5b6001600160a01b038216610c3657604051600090339083908381818185875af1925050503d8060008114610c1d576040519150601f19603f3d011682016040523d82523d6000602084013e610c22565b606091505b5050905080610c3057600080fd5b50610c41565b610c4182338361148a565b5050565b7f0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c9e57600080fd5b505afa158015610cb2573d6000803e3d6000fd5b505050506040513d6020811015610cc857600080fd5b50516001600160a01b03163314610d13576040805162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015290519081900360640190fd5b80610d4f576040805162461bcd60e51b8152602060048201526007602482015266125b9d985b1a5960ca1b604482015290519081900360640190fd5b600055565b6002602052600090815260409020546001600160801b031681565b7f0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f81565b7f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f81565b600154600160801b90046001600160801b031681565b7f000000000000000000000000000000000000000000000000000000000000000b81565b60015460009060ff168015610e07575060005415155b610e47576040805162461bcd60e51b815260206004820152600c60248201526b139bdd0819195d1858da195960a21b604482015290519081900360640190fd5b610e538585858561117a565b610e738585600160109054906101000a90046001600160801b0316611506565b95945050505050565b60015460009060ff1615610ec2576040805162461bcd60e51b815260206004820152600860248201526711195d1858da195960c21b604482015290519081900360640190fd5b60015463ffffffff808416600160281b909204161115610f1e576040805162461bcd60e51b8152602060048201526012602482015271496e76616c696420626c6f636b2074696d6560701b604482015290519081900360640190fd5b60007f0000000000000000000000002f7350cb5e434c2d177922110c7e314953b84afc6001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f7957600080fd5b505afa158015610f8d573d6000803e3d6000fd5b505050506040513d6020811015610fa357600080fd5b5051604080516370a0823160e01b81526001600160a01b03878116600483015291519293506000927f0000000000000000000000002f7350cb5e434c2d177922110c7e314953b84afc909216916370a0823191602480820192602092909190829003018186803b15801561101657600080fd5b505afa15801561102a573d6000803e3d6000fd5b505050506040513d602081101561104057600080fd5b50516001549091506000906110639063ffffffff80881691610100900416611592565b9050600061107182856115ac565b905061107e878483611506565b979650505050505050565b6001546000906110a890600160481b900466ffffffffffffff1661147c565b905090565b60008065ffffffffffff8311156110cd57602f6110c9846110dc565b0390505b82811c60081b1790505b919050565b6000816110e857600080fd5b600160801b82106110fb57608091821c91015b68010000000000000000821061111357604091821c91015b640100000000821061112757602091821c91015b62010000821061113957601091821c91015b610100821061114a57600891821c91015b6010821061115a57600491821c91015b6004821061116a57600291821c91015b600282106110d757600101919050565b6000848460405160200180836001600160a01b031660601b81526014018281526020019250505060405160208183030381529060405280519060200120905060006111fa84848080602002602001604051908101604052809392919081815260200183836020028082843760009201829052505492508691506116419050565b90508061123c576040805162461bcd60e51b815260206004820152600b60248201526a4e6f74496e4d65726b6c6560a81b604482015290519081900360640190fd5b505050505050565b60006112668484600160109054906101000a90046001600160801b0316611506565b6001549091506112a09061129b906305f5e10090611295908690600160801b90046001600160801b03166116ea565b90611711565b611730565b6001600160a01b038516600090815260026020526040902080546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905580156104d7577f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6001600160a01b031663a9059cbb85836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b15801561135c57600080fd5b505af192505050801561136d575060015b611376576104d7565b600061138061174a565b90508015610adc57846001600160a01b03167f00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f6001600160a01b03167fa282a314ffba449688a7c5eb4426bd8e1781944ce824ce34dfaea4691d08f146846040518082815260200191505060405180910390a35050505050565b600154610100900463ffffffff1661141157600080fd5b60015460009061142f9063ffffffff80861691610100900416611592565b905061143b81836115ac565b6001805463ffffffff4216600160281b0268ffffffff0000000000196001600160801b03948516600160801b02949092169390931716919091179055505050565b600881901c60ff9091161b90565b826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050600060405180830381600087803b1580156114e157600080fd5b505af11580156114f5573d6000803e3d6000fd5b50505050611501611785565b505050565b6001600160a01b03831660009081526002602052604081205461158a90670de0b6b3a7640000906112959060ff7f000000000000000000000000000000000000000000000000000000000000001216600a0a90611584906001600160801b039081169061157e906305f5e1009086908c908c166116ea565b906117f2565b906116ea565b949350505050565b60008183126115a157816115a3565b825b90505b92915050565b600154600090819063ffffffff808616600160281b909204161080156115d25750826000105b156116205760015463ffffffff600160281b909104811685031661161c846112956301da9c0081611601611089565b6001600160801b031661158487670de0b6b3a76400006116ea565b9150505b60015461158a9061129b90600160801b90046001600160801b031683611807565b600081815b85518110156116df57600086828151811061165d57fe5b602002602001015190508083116116a457828160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092506116d6565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b50600101611646565b509092149392505050565b6000826116f9575060006115a6565b8282028284828161170657fe5b04146115a357600080fd5b600080821161171f57600080fd5b81838161172857fe5b049392505050565b60006001600160801b0382111561174657600080fd5b5090565b6000611754611819565b3d801561176c57602081146117755760009250611780565b60019250611780565b60206000833e815192505b505090565b600061178f611819565b3d80156117a357602081146117ac57600080fd5b600192506117b7565b60206000833e815192505b5081610c41576040805162461bcd60e51b8152602060048201526005602482015264045524332360dc1b604482015290519081900360640190fd5b60008282111561180157600080fd5b50900390565b6000828201838110156115a357600080fd5b6040518060200160405280600190602082028036833750919291505056fea2646970667358221220a74639935b148d816e897ebe75f8648de6b80ed7bd5ef4f5bd1ebdddbd81bddb64736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f000000000000000000000000000000000000000000000000000000000000000b00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066c92280
-----Decoded View---------------
Arg [0] : notional (address): 0x6e7058c91F85E0F6db4fc9da2CA41241f5e4263f
Arg [1] : currencyId (uint16): 11
Arg [2] : incentive_token (address): 0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f
Arg [3] : _emissionRatePerYear (uint128): 0
Arg [4] : _endTime (uint32): 1724457600
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000006e7058c91f85e0f6db4fc9da2ca41241f5e4263f
Arg [1] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [2] : 00000000000000000000000040d16fc0246ad3160ccc09b8d0d3a2cd28ae6c2f
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000066c92280
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $1 | 65.9136 | $66.18 |
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.