Overview
xDAI Balance
xDAI Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
SuperToken
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPLv3 pragma solidity ^0.8.23; // solhint-disable max-states-count // Notes: SuperToken is rich with states, disable this default rule here. import { UUPSProxiable } from "../upgradability/UUPSProxiable.sol"; import { ISuperfluid, ISuperToken, IERC20, IConstantOutflowNFT, IConstantInflowNFT, IPoolAdminNFT, IPoolMemberNFT } from "../interfaces/superfluid/ISuperfluid.sol"; import { SuperfluidToken } from "./SuperfluidToken.sol"; import { ERC777Helper } from "../libs/ERC777Helper.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { SafeMath } from "@openzeppelin/contracts/utils/math/SafeMath.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { IERC777Recipient } from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; import { IERC777Sender } from "@openzeppelin/contracts/token/ERC777/IERC777Sender.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; /** * @title Superfluid's super token implementation * * @author Superfluid */ contract SuperToken is UUPSProxiable, SuperfluidToken, ISuperToken { using SafeMath for uint256; using SafeCast for uint256; using Address for address; using ERC777Helper for ERC777Helper.Operators; using SafeERC20 for IERC20; // See: https://eips.ethereum.org/EIPS/eip-1967#admin-address bytes32 constant private _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; uint8 constant private _STANDARD_DECIMALS = 18; // solhint-disable-next-line var-name-mixedcase IConstantOutflowNFT immutable public CONSTANT_OUTFLOW_NFT; // solhint-disable-next-line var-name-mixedcase IConstantInflowNFT immutable public CONSTANT_INFLOW_NFT; // solhint-disable-next-line var-name-mixedcase IPoolMemberNFT immutable public POOL_MEMBER_NFT; // solhint-disable-next-line var-name-mixedcase IPoolAdminNFT immutable public POOL_ADMIN_NFT; /* WARNING: NEVER RE-ORDER VARIABLES! Including the base contracts. Always double-check that new variables are added APPEND-ONLY. Re-ordering variables can permanently BREAK the deployed proxy contract. */ /// @dev The underlying ERC20 token IERC20 internal _underlyingToken; /// @dev Decimals of the underlying token uint8 internal _underlyingDecimals; /// @dev IERC20Metadata Name property string internal _name; /// @dev IERC20Metadata Symbol property string internal _symbol; /// @dev ERC20 Allowances Storage mapping(address => mapping (address => uint256)) internal _allowances; /// @dev ERC777 operators support data ERC777Helper.Operators internal _operators; // NOTE: for future compatibility, these are reserved solidity slots // The sub-class of SuperToken solidity slot will start after _reserve22 // NOTE: Whenever modifying the storage layout here it is important to update the validateStorageLayout // function in its respective mock contract to ensure that it doesn't break anything or lead to unexpected // behaviors/layout when upgrading uint256 internal _reserve22; uint256 private _reserve23; uint256 private _reserve24; uint256 private _reserve25; uint256 private _reserve26; uint256 private _reserve27; uint256 private _reserve28; uint256 private _reserve29; uint256 private _reserve30; uint256 internal _reserve31; // NOTE: You cannot add more storage here. Refer to CustomSuperTokenBase.sol // to see the hard-coded storage padding used by SETH and PureSuperToken constructor( ISuperfluid host, IConstantOutflowNFT constantOutflowNFT, IConstantInflowNFT constantInflowNFT, IPoolAdminNFT poolAdminNFT, IPoolMemberNFT poolMemberNFT ) SuperfluidToken(host) // solhint-disable-next-line no-empty-blocks { // @note This constructor is only run for the initial // deployment of the logic contract. // set the immutable canonical NFT proxy addresses CONSTANT_OUTFLOW_NFT = constantOutflowNFT; CONSTANT_INFLOW_NFT = constantInflowNFT; POOL_ADMIN_NFT = poolAdminNFT; POOL_MEMBER_NFT = poolMemberNFT; emit ConstantOutflowNFTCreated(constantOutflowNFT); emit ConstantInflowNFTCreated(constantInflowNFT); emit PoolAdminNFTCreated(poolAdminNFT); emit PoolMemberNFTCreated(poolMemberNFT); } /// @dev Initialize the Super Token proxy function initialize( IERC20 underlyingToken, uint8 underlyingDecimals, string calldata n, string calldata s ) external virtual override initializer // OpenZeppelin Initializable { // @note This function is only run once during the initial // deployment of the proxy contract. // initialize the Super Token _initialize(underlyingToken, underlyingDecimals, n, s, address(0)); } /// @dev Initialize the Super Token proxy with an admin function initializeWithAdmin( IERC20 underlyingToken, uint8 underlyingDecimals, string calldata n, string calldata s, address admin ) external virtual override initializer // OpenZeppelin Initializable { // @note This function is only run once during the initial // deployment of the proxy contract. // initialize the Super Token _initialize(underlyingToken, underlyingDecimals, n, s, admin); } function proxiableUUID() public pure virtual override returns (bytes32) { return keccak256("org.superfluid-finance.contracts.SuperToken.implementation"); } /** * @notice Updates the logic contract the proxy is pointing at * @dev Only the admin can call this function (host if admin == address(0)) * @param newAddress Address of the new logic contract */ function updateCode(address newAddress) external virtual override onlyAdmin { UUPSProxiable._updateCodeAddress(newAddress); // @note This is another check to ensure that when updating to a new SuperToken logic contract // that we have passed the correct NFT proxy contracts in the construction of the new SuperToken // logic contract if ( CONSTANT_OUTFLOW_NFT != SuperToken(newAddress).CONSTANT_OUTFLOW_NFT() || CONSTANT_INFLOW_NFT != SuperToken(newAddress).CONSTANT_INFLOW_NFT() ) { revert SUPER_TOKEN_NFT_PROXY_ADDRESS_CHANGED(); } } function changeAdmin(address newAdmin) external override onlyAdmin { address oldAdmin = _getAdmin(); _setAdmin(newAdmin); emit AdminChanged(oldAdmin, newAdmin); } function getAdmin() external view override returns (address) { return _getAdmin(); } function _getAdmin() internal view returns (address admin) { assembly { // solium-disable-line admin := sload(_ADMIN_SLOT) } } function _setAdmin(address newAdmin) internal { assembly { // solium-disable-line sstore(_ADMIN_SLOT, newAdmin) } } /************************************************************************** * ERC20 Token Info *************************************************************************/ function name() external view virtual override returns (string memory) { return _name; } function symbol() external view virtual override returns (string memory) { return _symbol; } function decimals() external pure virtual override returns (uint8) { return _STANDARD_DECIMALS; } /************************************************************************** * (private) Token Logics *************************************************************************/ function _initialize( IERC20 underlyingToken, uint8 underlyingDecimals, string calldata n, string calldata s, address admin ) internal { _underlyingToken = underlyingToken; _underlyingDecimals = underlyingDecimals; _name = n; _symbol = s; _setAdmin(admin); // register interfaces ERC777Helper.register(address(this)); // help tools like explorers detect the token contract emit Transfer(address(0), address(0), 0); // previous admin will always be the zero address in an uninitialized contract emit AdminChanged(address(0), admin); } /** * @notice in the original openzeppelin implementation, transfer() and transferFrom() * did invoke the send and receive hooks, as required by ERC777. * This hooks were removed from super tokens for ERC20 transfers in order to protect * interfacing contracts which don't expect invocations of ERC20 transfers to potentially reenter. * Interactions relying on ERC777 hooks need to use the ERC777 interface. * For more context, see https://github.com/superfluid-finance/protocol-monorepo/wiki/About-ERC-777 */ function _transferFrom(address spender, address holder, address recipient, uint amount) internal returns (bool) { if (holder == address(0)) { revert SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); } if (recipient == address(0)) { revert SUPER_TOKEN_TRANSFER_TO_ZERO_ADDRESS(); } address operator = msg.sender; _move(operator, holder, recipient, amount, "", ""); if (spender != holder) { _approve( holder, spender, _allowances[holder][spender].sub(amount, "SuperToken: transfer amount exceeds allowance")); } return true; } /** * @dev Send tokens * @param operator address operator address * @param from address token holder address * @param to address recipient address * @param amount uint256 amount of tokens to transfer * @param userData bytes extra information provided by the token holder (if any) * @param operatorData bytes extra information provided by the operator (if any) * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient */ function _send( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData, bool requireReceptionAck ) internal { if (from == address(0)) { revert SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); } if (to == address(0)) { revert SUPER_TOKEN_TRANSFER_TO_ZERO_ADDRESS(); } _callTokensToSend(operator, from, to, amount, userData, operatorData); _move(operator, from, to, amount, userData, operatorData); _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck); } function _move( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData ) private { SuperfluidToken._move(from, to, amount.toInt256()); emit Sent(operator, from, to, amount, userData, operatorData); emit Transfer(from, to, amount); } /** * @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * If invokeHook is true and a send hook is registered for `account`, * the corresponding function will be called with `operator`, `userData` and `operatorData`. * * See {IERC777Sender} and {IERC777Recipient}. * * Emits {Minted} and {IERC20.Transfer} events. * * Requirements * * - `account` cannot be the zero address. * - if `invokeHook` and `requireReceptionAck` are set and `account` is a contract, * it must implement the {IERC777Recipient} * interface. */ function _mint( address operator, address account, uint256 amount, bool invokeHook, bool requireReceptionAck, bytes memory userData, bytes memory operatorData ) internal { if (account == address(0)) { revert SUPER_TOKEN_MINT_TO_ZERO_ADDRESS(); } SuperfluidToken._mint(account, amount); if (invokeHook) { _callTokensReceived(operator, address(0), account, amount, userData, operatorData, requireReceptionAck); } emit Minted(operator, account, amount, userData, operatorData); emit Transfer(address(0), account, amount); } /** * @dev Burn tokens * @param from address token holder address * @param amount uint256 amount of tokens to burn * @param userData bytes extra information provided by the token holder * @param operatorData bytes extra information provided by the operator (if any) */ function _burn( address operator, address from, uint256 amount, bool invokeHook, bytes memory userData, bytes memory operatorData ) internal { if (from == address(0)) { revert SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS(); } if (invokeHook) { _callTokensToSend(operator, from, address(0), amount, userData, operatorData); } SuperfluidToken._burn(from, amount); emit Burned(operator, from, amount, userData, operatorData); emit Transfer(from, address(0), amount); } /** * @notice Sets `amount` as the allowance of `spender` over the `account`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `account` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address account, address spender, uint256 amount) internal { if (account == address(0)) { revert SUPER_TOKEN_APPROVE_FROM_ZERO_ADDRESS(); } if (spender == address(0)) { revert SUPER_TOKEN_APPROVE_TO_ZERO_ADDRESS(); } _allowances[account][spender] = amount; emit Approval(account, spender, amount); } /** * @dev Call from.tokensToSend() if the interface is registered * @param operator address operator requesting the transfer * @param from address token holder address * @param to address recipient address * @param amount uint256 amount of tokens to transfer * @param userData bytes extra information provided by the token holder (if any) * @param operatorData bytes extra information provided by the operator (if any) */ function _callTokensToSend( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData ) private { address implementer = ERC777Helper._ERC1820_REGISTRY.getInterfaceImplementer( from, ERC777Helper._TOKENS_SENDER_INTERFACE_HASH); if (implementer != address(0)) { IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData); } } /** * @dev Call to.tokensReceived() if the interface is registered. Reverts if the recipient is a contract but * tokensReceived() was not registered for the recipient * @param operator address operator requesting the transfer * @param from address token holder address * @param to address recipient address * @param amount uint256 amount of tokens to transfer * @param userData bytes extra information provided by the token holder (if any) * @param operatorData bytes extra information provided by the operator (if any) * @param requireReceptionAck if true, contract recipients are required to implement ERC777TokensRecipient */ function _callTokensReceived( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData, bool requireReceptionAck ) private { address implementer = ERC777Helper._ERC1820_REGISTRY.getInterfaceImplementer( to, ERC777Helper._TOKENS_RECIPIENT_INTERFACE_HASH); if (implementer != address(0)) { IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData); } else if (requireReceptionAck) { if (to.isContract()) revert SUPER_TOKEN_NOT_ERC777_TOKENS_RECIPIENT(); } } /************************************************************************** * ERC20 Implementations *************************************************************************/ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } function balanceOf( address account ) public view virtual override returns(uint256 balance) { // solhint-disable-next-line not-rely-on-time (int256 availableBalance, , ,) = super.realtimeBalanceOfNow(account); return availableBalance < 0 ? 0 : uint256(availableBalance); } function transfer(address recipient, uint256 amount) public virtual override returns (bool) { return _transferFrom(msg.sender, msg.sender, recipient, amount); } function allowance(address account, address spender) public view virtual override returns (uint256) { return _allowances[account][spender]; } function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(msg.sender, spender, amount); return true; } function transferFrom(address holder, address recipient, uint256 amount) public virtual override returns (bool) { return _transferFrom(msg.sender, holder, recipient, amount); } function increaseAllowance(address spender, uint256 addedValue) public virtual override returns (bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender] + addedValue); return true; } function decreaseAllowance(address spender, uint256 subtractedValue) public virtual override returns (bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "SuperToken: decreased allowance below zero")); return true; } /************************************************************************** * ERC-777 functions *************************************************************************/ function granularity() external pure virtual override returns (uint256) { return 1; } function send(address recipient, uint256 amount, bytes calldata userData) external virtual override { _send(msg.sender, msg.sender, recipient, amount, userData, "", true); } function burn(uint256 amount, bytes calldata userData) external virtual override { _downgrade(msg.sender, msg.sender, msg.sender, amount, userData, ""); } function isOperatorFor(address operator, address tokenHolder) external virtual override view returns (bool) { return _operators.isOperatorFor(operator, tokenHolder); } function authorizeOperator(address operator) external virtual override { address holder = msg.sender; _operators.authorizeOperator(holder, operator); emit AuthorizedOperator(operator, holder); } function revokeOperator(address operator) external virtual override { address holder = msg.sender; _operators.revokeOperator(holder, operator); emit RevokedOperator(operator, holder); } function defaultOperators() external virtual override view returns (address[] memory) { return ERC777Helper.defaultOperators(_operators); } function operatorSend( address sender, address recipient, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external virtual override { address operator = msg.sender; if (!_operators.isOperatorFor(operator, sender)) revert SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); _send(operator, sender, recipient, amount, userData, operatorData, true); } function operatorBurn( address account, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external virtual override { address operator = msg.sender; if (!_operators.isOperatorFor(operator, account)) revert SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); _downgrade(operator, account, account, amount, userData, operatorData); } function _setupDefaultOperators(address[] memory operators) internal { _operators.setupDefaultOperators(operators); } /************************************************************************** * SuperToken custom token functions *************************************************************************/ function selfMint( address account, uint256 amount, bytes memory userData ) external virtual override onlySelf { _mint(msg.sender, account, amount, userData.length != 0 /* invokeHook */, userData.length != 0 /* requireReceptionAck */, userData, new bytes(0)); } function selfBurn( address account, uint256 amount, bytes memory userData ) external virtual override onlySelf { _burn(msg.sender, account, amount, userData.length != 0 /* invokeHook */, userData, new bytes(0)); } function selfApproveFor( address account, address spender, uint256 amount ) external virtual override onlySelf { _approve(account, spender, amount); } function selfTransferFrom( address holder, address spender, address recipient, uint256 amount ) external virtual override onlySelf { _transferFrom(spender, holder, recipient, amount); } /************************************************************************** * SuperToken extra functions *************************************************************************/ function transferAll(address recipient) external virtual override { _transferFrom(msg.sender, msg.sender, recipient, balanceOf(msg.sender)); } /************************************************************************** * ERC20 wrapping *************************************************************************/ /// @inheritdoc ISuperToken function getUnderlyingToken() external view virtual override returns(address) { return address(_underlyingToken); } /// @inheritdoc ISuperToken function getUnderlyingDecimals() external view virtual override returns (uint8) { return _underlyingDecimals; } /// @inheritdoc ISuperToken function toUnderlyingAmount(uint256 amount) external view virtual override returns (uint256 underlyingAmount, uint256 adjustedAmount) { return _toUnderlyingAmount(amount); } /// @inheritdoc ISuperToken function upgrade(uint256 amount) external virtual override { _upgrade(msg.sender, msg.sender, msg.sender, amount, "", ""); } /// @inheritdoc ISuperToken function upgradeTo(address to, uint256 amount, bytes calldata userData) external virtual override { _upgrade(msg.sender, msg.sender, to, amount, userData, ""); } /// @inheritdoc ISuperToken function downgrade(uint256 amount) external virtual override { _downgrade(msg.sender, msg.sender, msg.sender, amount, "", ""); } /// @inheritdoc ISuperToken function downgradeTo(address to, uint256 amount) external virtual override { _downgrade(msg.sender, msg.sender, to, amount, "", ""); } function _upgrade( address operator, address account, address to, uint256 amount, bytes memory userData, bytes memory operatorData ) internal { if (address(_underlyingToken) == address(0)) revert SUPER_TOKEN_NO_UNDERLYING_TOKEN(); (uint256 underlyingAmount, uint256 adjustedAmount) = _toUnderlyingAmount(amount); uint256 amountBefore = _underlyingToken.balanceOf(address(this)); _underlyingToken.safeTransferFrom(account, address(this), underlyingAmount); uint256 amountAfter = _underlyingToken.balanceOf(address(this)); uint256 actualUpgradedAmount = amountAfter - amountBefore; if (underlyingAmount != actualUpgradedAmount) revert SUPER_TOKEN_INFLATIONARY_DEFLATIONARY_NOT_SUPPORTED(); _mint(operator, to, adjustedAmount, // if `userData.length` is greater than 0, we set invokeHook and requireReceptionAck true userData.length != 0, userData.length != 0, userData, operatorData); emit TokenUpgraded(to, adjustedAmount); } function _downgrade( address operator, // the account executing the transaction address account, // the account whose super tokens we are burning address to, // the account receiving the underlying tokens uint256 amount, bytes memory userData, bytes memory operatorData ) internal { if (address(_underlyingToken) == address(0)) revert SUPER_TOKEN_NO_UNDERLYING_TOKEN(); (uint256 underlyingAmount, uint256 adjustedAmount) = _toUnderlyingAmount(amount); // _burn will check the (actual) amount availability again _burn(operator, account, adjustedAmount, userData.length != 0, userData, operatorData); uint256 amountBefore = _underlyingToken.balanceOf(address(this)); _underlyingToken.safeTransfer(to, underlyingAmount); uint256 amountAfter = _underlyingToken.balanceOf(address(this)); uint256 actualDowngradedAmount = amountBefore - amountAfter; if (underlyingAmount != actualDowngradedAmount) revert SUPER_TOKEN_INFLATIONARY_DEFLATIONARY_NOT_SUPPORTED(); emit TokenDowngraded(account, adjustedAmount); } /** * @dev Handle decimal differences between underlying token and super token */ function _toUnderlyingAmount(uint256 amount) private view returns (uint256 underlyingAmount, uint256 adjustedAmount) { uint256 factor; if (_underlyingDecimals < _STANDARD_DECIMALS) { // if underlying has less decimals // one can upgrade less "granualar" amount of tokens factor = 10 ** (_STANDARD_DECIMALS - _underlyingDecimals); underlyingAmount = amount / factor; // remove precision errors adjustedAmount = underlyingAmount * factor; } else if (_underlyingDecimals > _STANDARD_DECIMALS) { // if underlying has more decimals // one can upgrade more "granualar" amount of tokens factor = 10 ** (_underlyingDecimals - _STANDARD_DECIMALS); underlyingAmount = amount * factor; adjustedAmount = amount; } else { underlyingAmount = adjustedAmount = amount; } } /************************************************************************** * Superfluid Batch Operations *************************************************************************/ function operationApprove( address account, address spender, uint256 amount ) external virtual override onlyHost { _approve(account, spender, amount); } function operationIncreaseAllowance( address account, address spender, uint256 addedValue ) external virtual override onlyHost { _approve(account, spender, _allowances[account][spender] + addedValue); } function operationDecreaseAllowance( address account, address spender, uint256 subtractedValue ) external virtual override onlyHost { _approve(account, spender, _allowances[account][spender].sub(subtractedValue, "SuperToken: decreased allowance below zero")); } function operationTransferFrom( address account, address spender, address recipient, uint256 amount ) external virtual override onlyHost { _transferFrom(account, spender, recipient, amount); } function operationSend( address spender, address recipient, uint256 amount, bytes memory userData ) external virtual override onlyHost { _send(msg.sender, spender, recipient, amount, userData, "", true); } function operationUpgrade(address account, uint256 amount) external virtual override onlyHost { _upgrade(msg.sender, account, account, amount, "", ""); } function operationDowngrade(address account, uint256 amount) external virtual override onlyHost { _downgrade(msg.sender, account, account, amount, "", ""); } function operationUpgradeTo(address account, address to, uint256 amount) external virtual override onlyHost { _upgrade(msg.sender, account, to, amount, "", ""); } function operationDowngradeTo(address account, address to, uint256 amount) external virtual override onlyHost { _downgrade(msg.sender, account, to, amount, "", ""); } /************************************************************************** * Modifiers *************************************************************************/ modifier onlySelf() { if (msg.sender != address(this)) revert SUPER_TOKEN_ONLY_SELF(); _; } /** * @dev The host contract is implicitly the admin if admin is address(0) else it is the explicitly set admin * override address */ modifier onlyAdmin() { address adminSlotAdmin = _getAdmin(); address admin = adminSlotAdmin == address(0) ? address(_host) : adminSlotAdmin; if (msg.sender != admin) revert SUPER_TOKEN_ONLY_ADMIN(); _; } }
// SPDX-License-Identifier: AGPLv3 pragma solidity ^0.8.23; /** * @title UUPS (Universal Upgradeable Proxy Standard) Shared Library */ library UUPSUtils { /** * @dev Implementation slot constant. * Using https://eips.ethereum.org/EIPS/eip-1967 standard * Storage slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc * (obtained as bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)). */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /// @dev Get implementation address. function implementation() internal view returns (address impl) { assembly { // solium-disable-line impl := sload(_IMPLEMENTATION_SLOT) } } /// @dev Set new implementation address. function setImplementation(address codeAddress) internal { assembly { // solium-disable-line sstore( _IMPLEMENTATION_SLOT, codeAddress ) } } }
// SPDX-License-Identifier: AGPLv3 pragma solidity ^0.8.23; import { UUPSUtils } from "./UUPSUtils.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; /** * @title UUPS (Universal Upgradeable Proxy Standard) Proxiable contract. */ abstract contract UUPSProxiable is Initializable { /** * @dev Get current implementation code address. */ function getCodeAddress() public view returns (address codeAddress) { return UUPSUtils.implementation(); } function updateCode(address newAddress) external virtual; // allows to mark logic contracts as initialized // solhint-disable-next-line no-empty-blocks function castrate() external initializer { } /** * @dev Proxiable UUID marker function, this would help to avoid wrong logic * contract to be used for upgrading. * * NOTE: The semantics of the UUID deviates from the actual UUPS standard, * where it is equivalent of _IMPLEMENTATION_SLOT. */ function proxiableUUID() public view virtual returns (bytes32); /** * @dev Update code address function. * It is internal, so the derived contract could setup its own permission logic. */ function _updateCodeAddress(address newAddress) internal { // require UUPSProxy.initializeProxy first require(UUPSUtils.implementation() != address(0), "UUPSProxiable: not upgradable"); require( proxiableUUID() == UUPSProxiable(newAddress).proxiableUUID(), "UUPSProxiable: not compatible logic" ); require( address(this) != newAddress, "UUPSProxiable: proxy loop" ); UUPSUtils.setImplementation(newAddress); emit CodeUpdated(proxiableUUID(), newAddress); } event CodeUpdated(bytes32 uuid, address codeAddress); }
// SPDX-License-Identifier: AGPLv3 pragma solidity ^0.8.23; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { ISuperfluid, ISuperAgreement, ISuperfluidGovernance, ISuperfluidToken } from "../interfaces/superfluid/ISuperfluid.sol"; import { FixedSizeData } from "../libs/FixedSizeData.sol"; /** * @title Superfluid's token implementation * * @author Superfluid */ abstract contract SuperfluidToken is ISuperfluidToken { bytes32 private constant _REWARD_ADDRESS_CONFIG_KEY = keccak256("org.superfluid-finance.superfluid.rewardAddress"); using SafeCast for uint256; using SafeCast for int256; /// @dev Superfluid contract ISuperfluid immutable internal _host; /// @dev Active agreement bitmap mapping(address => uint256) internal _inactiveAgreementBitmap; /// @dev Shared Settled balance for the account mapping(address => int256) internal _sharedSettledBalances; /// @dev Total supply uint256 internal _totalSupply; // NOTE: for future compatibility, these are reserved solidity slots // The sub-class of SuperfluidToken solidity slot will start after _reserve13 uint256 internal _reserve4; uint256 private _reserve5; uint256 private _reserve6; uint256 private _reserve7; uint256 private _reserve8; uint256 private _reserve9; uint256 private _reserve10; uint256 private _reserve11; uint256 private _reserve12; uint256 internal _reserve13; constructor( ISuperfluid host ) { _host = host; } /// @dev ISuperfluidToken.getHost implementation function getHost() external view override(ISuperfluidToken) returns(address host) { return address(_host); } /************************************************************************** * Real-time balance functions *************************************************************************/ /// @dev ISuperfluidToken.realtimeBalanceOf implementation function realtimeBalanceOf( address account, uint256 timestamp ) public view virtual override returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit) { availableBalance = _sharedSettledBalances[account]; ISuperAgreement[] memory activeAgreements = getAccountActiveAgreements(account); for (uint256 i = 0; i < activeAgreements.length; ++i) { ( int256 agreementDynamicBalance, uint256 agreementDeposit, uint256 agreementOwedDeposit) = activeAgreements[i] .realtimeBalanceOf( this, account, timestamp ); deposit = deposit + agreementDeposit; owedDeposit = owedDeposit + agreementOwedDeposit; // 1. Available Balance = Dynamic Balance - Max(0, Deposit - OwedDeposit) // 2. Deposit should not be shared between agreements availableBalance = availableBalance + agreementDynamicBalance - ( agreementDeposit > agreementOwedDeposit ? (agreementDeposit - agreementOwedDeposit) : 0 ).toInt256(); } } /// @dev ISuperfluidToken.realtimeBalanceOfNow implementation function realtimeBalanceOfNow( address account ) public view virtual override returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit, uint256 timestamp) { timestamp = _host.getNow(); ( availableBalance, deposit, owedDeposit ) = realtimeBalanceOf(account, timestamp); } function isAccountCritical( address account, uint256 timestamp ) public view virtual override returns(bool isCritical) { (int256 availableBalance,,) = realtimeBalanceOf(account, timestamp); return availableBalance < 0; } function isAccountCriticalNow( address account ) external view virtual override returns(bool isCritical) { return isAccountCritical(account, _host.getNow()); } function isAccountSolvent( address account, uint256 timestamp ) public view virtual override returns(bool isSolvent) { (int256 availableBalance, uint256 deposit, uint256 owedDeposit) = realtimeBalanceOf(account, timestamp); // Available Balance = Realtime Balance - Max(0, Deposit - OwedDeposit) int realtimeBalance = availableBalance + (deposit > owedDeposit ? (deposit - owedDeposit) : 0).toInt256(); return realtimeBalance >= 0; } function isAccountSolventNow( address account ) external view virtual override returns(bool isSolvent) { return isAccountSolvent(account, _host.getNow()); } /// @dev ISuperfluidToken.getAccountActiveAgreements implementation function getAccountActiveAgreements(address account) public view virtual override returns(ISuperAgreement[] memory) { return _host.mapAgreementClasses(~_inactiveAgreementBitmap[account]); } /************************************************************************** * Token implementation helpers *************************************************************************/ function _mint( address account, uint256 amount ) internal { _sharedSettledBalances[account] = _sharedSettledBalances[account] + amount.toInt256(); _totalSupply = _totalSupply + amount; } function _burn( address account, uint256 amount ) internal { (int256 availableBalance,,) = realtimeBalanceOf(account, _host.getNow()); if (availableBalance < amount.toInt256()) { revert SF_TOKEN_BURN_INSUFFICIENT_BALANCE(); } _sharedSettledBalances[account] = _sharedSettledBalances[account] - amount.toInt256(); _totalSupply = _totalSupply - amount; } function _move( address from, address to, int256 amount ) internal { (int256 availableBalance,,) = realtimeBalanceOf(from, _host.getNow()); if (availableBalance < amount) { revert SF_TOKEN_MOVE_INSUFFICIENT_BALANCE(); } _sharedSettledBalances[from] = _sharedSettledBalances[from] - amount; _sharedSettledBalances[to] = _sharedSettledBalances[to] + amount; } function _getRewardAccount() internal view returns (address rewardAccount) { ISuperfluidGovernance gov = _host.getGovernance(); rewardAccount = gov.getConfigAsAddress(_host, this, _REWARD_ADDRESS_CONFIG_KEY); } /************************************************************************** * Super Agreement hosting functions *************************************************************************/ /// @dev ISuperfluidToken.createAgreement implementation function createAgreement( bytes32 id, bytes32[] calldata data ) external virtual override { address agreementClass = msg.sender; bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); if (FixedSizeData.hasData(slot, data.length)) { revert SF_TOKEN_AGREEMENT_ALREADY_EXISTS(); } FixedSizeData.storeData(slot, data); emit AgreementCreated(agreementClass, id, data); } /// @dev ISuperfluidToken.getAgreementData implementation function getAgreementData( address agreementClass, bytes32 id, uint dataLength ) external view virtual override returns(bytes32[] memory data) { bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); data = FixedSizeData.loadData(slot, dataLength); } /// @dev ISuperfluidToken.updateAgreementData implementation function updateAgreementData( bytes32 id, bytes32[] calldata data ) external virtual override { address agreementClass = msg.sender; bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); FixedSizeData.storeData(slot, data); emit AgreementUpdated(msg.sender, id, data); } /// @dev ISuperfluidToken.terminateAgreement implementation function terminateAgreement( bytes32 id, uint dataLength ) external virtual override { address agreementClass = msg.sender; bytes32 slot = keccak256(abi.encode("AgreementData", agreementClass, id)); if (!FixedSizeData.hasData(slot,dataLength)) { revert SF_TOKEN_AGREEMENT_DOES_NOT_EXIST(); } FixedSizeData.eraseData(slot, dataLength); emit AgreementTerminated(msg.sender, id); } /// @dev ISuperfluidToken.updateAgreementState implementation function updateAgreementStateSlot( address account, uint256 slotId, bytes32[] calldata slotData ) external virtual override { bytes32 slot = keccak256(abi.encode("AgreementState", msg.sender, account, slotId)); FixedSizeData.storeData(slot, slotData); emit AgreementStateUpdated(msg.sender, account, slotId); } /// @dev ISuperfluidToken.getAgreementState implementation function getAgreementStateSlot( address agreementClass, address account, uint256 slotId, uint dataLength ) external view virtual override returns (bytes32[] memory slotData) { bytes32 slot = keccak256(abi.encode("AgreementState", agreementClass, account, slotId)); slotData = FixedSizeData.loadData(slot, dataLength); } /// @dev ISuperfluidToken.settleBalance implementation function settleBalance( address account, int256 delta ) external virtual override onlyAgreement { _sharedSettledBalances[account] = _sharedSettledBalances[account] + delta; } /// @dev ISuperfluidToken.makeLiquidationPayoutsV2 implementation function makeLiquidationPayoutsV2( bytes32 id, bytes memory liquidationTypeData, address liquidatorAccount, // the address executing the liquidation bool useDefaultRewardAccount, // Whether or not the default reward account receives the rewardAmount address targetAccount, // Account to be liquidated uint256 rewardAmount, // The amount the rewarded account will receive int256 targetAccountBalanceDelta // The delta amount the target account balance should change by ) external virtual override onlyAgreement { address rewardAccount = _getRewardAccount(); // we set the rewardAccount to the user who executed the liquidation if // no rewardAccount is set (aka. ANARCHY MODE - should not occur in reality, for testing purposes) if (rewardAccount == address(0)) { rewardAccount = liquidatorAccount; } address rewardAmountReceiver = useDefaultRewardAccount ? rewardAccount : liquidatorAccount; if (targetAccountBalanceDelta <= 0) { // LIKELY BRANCH: target account pays penalty to rewarded account assert(rewardAmount.toInt256() == -targetAccountBalanceDelta); _sharedSettledBalances[rewardAmountReceiver] += rewardAmount.toInt256(); _sharedSettledBalances[targetAccount] += targetAccountBalanceDelta; emit IERC20.Transfer(targetAccount, rewardAmountReceiver, rewardAmount); } else { // LESS LIKELY BRANCH: target account is bailed out // NOTE: useDefaultRewardAccount being true is undefined behavior // because the default reward account isn't receiving the rewardAmount by default assert(!useDefaultRewardAccount); _sharedSettledBalances[rewardAccount] -= (rewardAmount.toInt256() + targetAccountBalanceDelta); _sharedSettledBalances[liquidatorAccount] += rewardAmount.toInt256(); _sharedSettledBalances[targetAccount] += targetAccountBalanceDelta; emit IERC20.Transfer(rewardAccount, liquidatorAccount, rewardAmount); emit IERC20.Transfer(rewardAccount, targetAccount, uint256(targetAccountBalanceDelta)); } emit AgreementLiquidatedV2( msg.sender, id, liquidatorAccount, targetAccount, rewardAmountReceiver, rewardAmount, targetAccountBalanceDelta, liquidationTypeData ); } /************************************************************************** * Modifiers *************************************************************************/ modifier onlyAgreement() { if (!_host.isAgreementClassListed(ISuperAgreement(msg.sender))) { revert SF_TOKEN_ONLY_LISTED_AGREEMENT(); } _; } modifier onlyHost() { if (address(_host) != msg.sender) { revert SF_TOKEN_ONLY_HOST(); } _; } }
// SPDX-License-Identifier: AGPLv3 pragma solidity ^0.8.23; /** * @title Utilities for fixed size data in storage * @author Superfluid * * When using solidity dynamic array, first word is used to store the length * of the array. For use cases that the length doesn't change, it is better * to use a fixed size data premitive. * * To use this library: * - The pointer to the storage is `slot`, the user could use `keccak256(abi.encode(...))` * scheme to create collision-free slot ID for locating the data. * - To load data, or erase data and get all gas refund, data length is always required. */ library FixedSizeData { /** * @dev Store data to the slot at `slot` */ function storeData(bytes32 slot, bytes32[] memory data) internal { for (uint j = 0; j < data.length; ++j) { bytes32 d = data[j]; assembly { sstore(add(slot, j), d) } } } function hasData(bytes32 slot, uint dataLength) internal view returns (bool) { for (uint j = 0; j < dataLength; ++j) { bytes32 d; assembly { d := sload(add(slot, j)) } if (uint256(d) > 0) return true; } return false; } /** * @dev Load data of size `dataLength` from the slot at `slot` */ function loadData(bytes32 slot, uint dataLength) internal view returns (bytes32[] memory data) { data = new bytes32[](dataLength); for (uint j = 0; j < dataLength; ++j) { bytes32 d; assembly { d := sload(add(slot, j)) } data[j] = d; } } /** * @dev Erase data of size `dataLength` from the slot at `slot` */ function eraseData(bytes32 slot, uint dataLength) internal { for (uint j = 0; j < dataLength; ++j) { assembly { sstore(add(slot, j), 0) } } } }
// SPDX-License-Identifier: AGPLv3 pragma solidity ^0.8.23; import { IERC1820Registry } from "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol"; /** * @title ERC777 helper library * @author Superfluid */ library ERC777Helper { IERC1820Registry constant internal _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24); bytes32 constant internal _TOKENS_SENDER_INTERFACE_HASH = keccak256("ERC777TokensSender"); bytes32 constant internal _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient"); /// @dev ERC777 operators support self structure struct Operators { address[] defaultOperatorsArray; mapping(address => bool) defaultOperators; mapping(address => mapping(address => bool)) operators; mapping(address => mapping(address => bool)) revokedDefaultOperators; } function register(address token) internal { _ERC1820_REGISTRY.setInterfaceImplementer(token, keccak256("ERC777Token"), address(this)); _ERC1820_REGISTRY.setInterfaceImplementer(token, keccak256("ERC20Token"), address(this)); } function isOperatorFor(Operators storage self, address operator, address tokenHolder) internal view returns (bool) { return operator == tokenHolder || ( self.defaultOperators[operator] && !self.revokedDefaultOperators[tokenHolder][operator] ) || self.operators[tokenHolder][operator]; } function authorizeOperator(Operators storage self, address holder, address operator) internal { require(holder != operator, "ERC777Operators: authorizing self as operator"); if (self.defaultOperators[operator]) { delete self.revokedDefaultOperators[holder][operator]; } else { self.operators[holder][operator] = true; } } function revokeOperator(Operators storage self, address holder, address operator) internal { require(operator != msg.sender, "ERC777Operators: revoking self as operator"); if (self.defaultOperators[operator]) { self.revokedDefaultOperators[holder][operator] = true; } else { delete self.operators[holder][operator]; } } function defaultOperators(Operators storage self) internal view returns (address[] memory) { return self.defaultOperatorsArray; } function setupDefaultOperators(Operators storage self, address[] memory operators) internal { // According to 777 spec: default operators should only be setup once assert(self.defaultOperatorsArray.length == 0); self.defaultOperatorsArray = operators; for (uint i = 0; i < operators.length; ++i) { self.defaultOperators[operators[i]] = true; } } }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperToken } from "../superfluid/ISuperToken.sol"; /** * @title Super ETH (SETH) custom token interface * @author Superfluid */ interface ISETHCustom { // using native token function upgradeByETH() external payable; function upgradeByETHTo(address to) external payable; function downgradeToETH(uint wad) external; } /** * @title Super ETH (SETH) full interface * @author Superfluid */ // solhint-disable-next-line no-empty-blocks interface ISETH is ISETHCustom, ISuperToken {}
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperAgreement } from "./ISuperAgreement.sol"; /** * @title Superfluid token interface * @author Superfluid */ interface ISuperfluidToken { /************************************************************************** * Errors *************************************************************************/ error SF_TOKEN_AGREEMENT_ALREADY_EXISTS(); // 0xf05521f6 error SF_TOKEN_AGREEMENT_DOES_NOT_EXIST(); // 0xdae18809 error SF_TOKEN_BURN_INSUFFICIENT_BALANCE(); // 0x10ecdf44 error SF_TOKEN_MOVE_INSUFFICIENT_BALANCE(); // 0x2f4cb941 error SF_TOKEN_ONLY_LISTED_AGREEMENT(); // 0xc9ff6644 error SF_TOKEN_ONLY_HOST(); // 0xc51efddd /************************************************************************** * Basic information *************************************************************************/ /** * @dev Get superfluid host contract address */ function getHost() external view returns(address host); /** * @dev Encoded liquidation type data mainly used for handling stack to deep errors * * @custom:note * - version: 1 * - liquidationType key: * - 0 = reward account receives reward (PIC period) * - 1 = liquidator account receives reward (Pleb period) * - 2 = liquidator account receives reward (Pirate period/bailout) */ struct LiquidationTypeData { uint256 version; uint8 liquidationType; } /************************************************************************** * Real-time balance functions *************************************************************************/ /** * @dev Calculate the real balance of a user, taking in consideration all agreements of the account * @param account for the query * @param timestamp Time of balance * @return availableBalance Real-time balance * @return deposit Account deposit * @return owedDeposit Account owed Deposit */ function realtimeBalanceOf( address account, uint256 timestamp ) external view returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit); /** * @notice Calculate the realtime balance given the current host.getNow() value * @dev realtimeBalanceOf with timestamp equals to block timestamp * @param account for the query * @return availableBalance Real-time balance * @return deposit Account deposit * @return owedDeposit Account owed Deposit */ function realtimeBalanceOfNow( address account ) external view returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit, uint256 timestamp); /** * @notice Check if account is critical * @dev A critical account is when availableBalance < 0 * @param account The account to check * @param timestamp The time we'd like to check if the account is critical (should use future) * @return isCritical Whether the account is critical */ function isAccountCritical( address account, uint256 timestamp ) external view returns(bool isCritical); /** * @notice Check if account is critical now (current host.getNow()) * @dev A critical account is when availableBalance < 0 * @param account The account to check * @return isCritical Whether the account is critical */ function isAccountCriticalNow( address account ) external view returns(bool isCritical); /** * @notice Check if account is solvent * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance * @param account The account to check * @param timestamp The time we'd like to check if the account is solvent (should use future) * @return isSolvent True if the account is solvent, false otherwise */ function isAccountSolvent( address account, uint256 timestamp ) external view returns(bool isSolvent); /** * @notice Check if account is solvent now * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance * @param account The account to check * @return isSolvent True if the account is solvent, false otherwise */ function isAccountSolventNow( address account ) external view returns(bool isSolvent); /** * @notice Get a list of agreements that is active for the account * @dev An active agreement is one that has state for the account * @param account Account to query * @return activeAgreements List of accounts that have non-zero states for the account */ function getAccountActiveAgreements(address account) external view returns(ISuperAgreement[] memory activeAgreements); /************************************************************************** * Super Agreement hosting functions *************************************************************************/ /** * @dev Create a new agreement * @param id Agreement ID * @param data Agreement data */ function createAgreement( bytes32 id, bytes32[] calldata data ) external; /** * @dev Agreement created event * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param data Agreement data */ event AgreementCreated( address indexed agreementClass, bytes32 id, bytes32[] data ); /** * @dev Get data of the agreement * @param agreementClass Contract address of the agreement * @param id Agreement ID * @return data Data of the agreement */ function getAgreementData( address agreementClass, bytes32 id, uint dataLength ) external view returns(bytes32[] memory data); /** * @dev Create a new agreement * @param id Agreement ID * @param data Agreement data */ function updateAgreementData( bytes32 id, bytes32[] calldata data ) external; /** * @dev Agreement updated event * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param data Agreement data */ event AgreementUpdated( address indexed agreementClass, bytes32 id, bytes32[] data ); /** * @dev Close the agreement * @param id Agreement ID */ function terminateAgreement( bytes32 id, uint dataLength ) external; /** * @dev Agreement terminated event * @param agreementClass Contract address of the agreement * @param id Agreement ID */ event AgreementTerminated( address indexed agreementClass, bytes32 id ); /** * @dev Update agreement state slot * @param account Account to be updated * * @custom:note * - To clear the storage out, provide zero-ed array of intended length */ function updateAgreementStateSlot( address account, uint256 slotId, bytes32[] calldata slotData ) external; /** * @dev Agreement account state updated event * @param agreementClass Contract address of the agreement * @param account Account updated * @param slotId slot id of the agreement state */ event AgreementStateUpdated( address indexed agreementClass, address indexed account, uint256 slotId ); /** * @dev Get data of the slot of the state of an agreement * @param agreementClass Contract address of the agreement * @param account Account to query * @param slotId slot id of the state * @param dataLength length of the state data */ function getAgreementStateSlot( address agreementClass, address account, uint256 slotId, uint dataLength ) external view returns (bytes32[] memory slotData); /** * @notice Settle balance from an account by the agreement * @dev The agreement needs to make sure that the balance delta is balanced afterwards * @param account Account to query. * @param delta Amount of balance delta to be settled * * @custom:modifiers * - onlyAgreement */ function settleBalance( address account, int256 delta ) external; /** * @dev Make liquidation payouts (v2) * @param id Agreement ID * @param liquidationTypeData Data regarding the version of the liquidation schema and the type * @param liquidatorAccount Address of the executor of the liquidation * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount * @param targetAccount Account to be liquidated * @param rewardAmount The amount the rewarded account will receive * @param targetAccountBalanceDelta The delta amount the target account balance should change by * * @custom:note * - If a bailout is required (bailoutAmount > 0) * - the actual reward (single deposit) goes to the executor, * - while the reward account becomes the bailout account * - total bailout include: bailout amount + reward amount * - the targetAccount will be bailed out * - If a bailout is not required * - the targetAccount will pay the rewardAmount * - the liquidator (reward account in PIC period) will receive the rewardAmount * * @custom:modifiers * - onlyAgreement */ function makeLiquidationPayoutsV2 ( bytes32 id, bytes memory liquidationTypeData, address liquidatorAccount, bool useDefaultRewardAccount, address targetAccount, uint256 rewardAmount, int256 targetAccountBalanceDelta ) external; /** * @dev Agreement liquidation event v2 (including agent account) * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param liquidatorAccount Address of the executor of the liquidation * @param targetAccount Account of the stream sender * @param rewardAmountReceiver Account that collects the reward or bails out insolvent accounts * @param rewardAmount The amount the reward recipient account balance should change by * @param targetAccountBalanceDelta The amount the sender account balance should change by * @param liquidationTypeData The encoded liquidation type data including the version (how to decode) * * @custom:note * Reward account rule: * - if the agreement is liquidated during the PIC period * - the rewardAmountReceiver will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount * - the targetAccount will pay for the rewardAmount * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent * - the rewardAmountReceiver will get the rewardAmount (remaining deposit) * - the targetAccount will pay for the rewardAmount * - if the targetAccount is insolvent * - the liquidatorAccount will get the rewardAmount (single deposit) * - the default reward account (governance) will pay for both the rewardAmount and bailoutAmount * - the targetAccount will receive the bailoutAmount */ event AgreementLiquidatedV2( address indexed agreementClass, bytes32 id, address indexed liquidatorAccount, address indexed targetAccount, address rewardAmountReceiver, uint256 rewardAmount, int256 targetAccountBalanceDelta, bytes liquidationTypeData ); /************************************************************************** * Function modifiers for access control and parameter validations * * While they cannot be explicitly stated in function definitions, they are * listed in function definition comments instead for clarity. * * NOTE: solidity-coverage not supporting it *************************************************************************/ /// @dev The msg.sender must be host contract //modifier onlyHost() virtual; /// @dev The msg.sender must be a listed agreement. //modifier onlyAgreement() virtual; /************************************************************************** * DEPRECATED *************************************************************************/ /** * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy) * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param penaltyAccount Account of the agreement to be penalized * @param rewardAccount Account that collect the reward * @param rewardAmount Amount of liquidation reward * * @custom:deprecated Use AgreementLiquidatedV2 instead */ event AgreementLiquidated( address indexed agreementClass, bytes32 id, address indexed penaltyAccount, address indexed rewardAccount, uint256 rewardAmount ); /** * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy) * @param bailoutAccount Account that bailout the penalty account * @param bailoutAmount Amount of account bailout * * @custom:deprecated Use AgreementLiquidatedV2 instead */ event Bailout( address indexed bailoutAccount, uint256 bailoutAmount ); /** * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2) * @param liquidatorAccount Account of the agent that performed the liquidation. * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param penaltyAccount Account of the agreement to be penalized * @param bondAccount Account that collect the reward or bailout accounts * @param rewardAmount Amount of liquidation reward * @param bailoutAmount Amount of liquidation bailouot * * @custom:deprecated Use AgreementLiquidatedV2 instead * * @custom:note * Reward account rule: * - if bailout is equal to 0, then * - the bondAccount will get the rewardAmount, * - the penaltyAccount will pay for the rewardAmount. * - if bailout is larger than 0, then * - the liquidatorAccount will get the rewardAmouont, * - the bondAccount will pay for both the rewardAmount and bailoutAmount, * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount. */ event AgreementLiquidatedBy( address liquidatorAccount, address indexed agreementClass, bytes32 id, address indexed penaltyAccount, address indexed bondAccount, uint256 rewardAmount, uint256 bailoutAmount ); }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperfluid } from "./ISuperfluid.sol"; import { ISuperToken } from "./ISuperToken.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; /** * @title Superfluid governance interface * @author Superfluid */ interface ISuperfluidGovernance { /************************************************************************** * Errors *************************************************************************/ error SF_GOV_INVALID_LIQUIDATION_OR_PATRICIAN_PERIOD(); // 0xe171980a error SF_GOV_MUST_BE_CONTRACT(); // 0x80dddd73 /** * @dev Replace the current governance with a new governance */ function replaceGovernance( ISuperfluid host, address newGov) external; /** * @dev Register a new agreement class */ function registerAgreementClass( ISuperfluid host, address agreementClass) external; /** * @dev Update logics of the contracts * * @custom:note * - Because they might have inter-dependencies, it is good to have one single function to update them all */ function updateContracts( ISuperfluid host, address hostNewLogic, address[] calldata agreementClassNewLogics, address superTokenFactoryNewLogic, address beaconNewLogic ) external; /** * @dev Update supertoken logic contract to the latest that is managed by the super token factory */ function batchUpdateSuperTokenLogic( ISuperfluid host, ISuperToken[] calldata tokens) external; /** * @dev Update supertoken logic contract to the provided logic contracts. * Note that this is an overloaded version taking an additional argument `tokenLogics` */ function batchUpdateSuperTokenLogic( ISuperfluid host, ISuperToken[] calldata tokens, address[] calldata tokenLogics) external; /** * @dev Set configuration as address value */ function setConfig( ISuperfluid host, ISuperfluidToken superToken, bytes32 key, address value ) external; /** * @dev Set configuration as uint256 value */ function setConfig( ISuperfluid host, ISuperfluidToken superToken, bytes32 key, uint256 value ) external; /** * @dev Clear configuration */ function clearConfig( ISuperfluid host, ISuperfluidToken superToken, bytes32 key ) external; /** * @dev Get configuration as address value */ function getConfigAsAddress( ISuperfluid host, ISuperfluidToken superToken, bytes32 key) external view returns (address value); /** * @dev Get configuration as uint256 value */ function getConfigAsUint256( ISuperfluid host, ISuperfluidToken superToken, bytes32 key) external view returns (uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; // ISuperfluid.sol can also be used as an umbrella-import for everything Superfluid, hence we should have these unused // import. // // solhint-disable no-unused-import /// Global definitions import { SuperAppDefinitions, ContextDefinitions, FlowOperatorDefinitions, BatchOperation, SuperfluidGovernanceConfigs } from "./Definitions.sol"; /// Super token related interfaces: /// Note: CustomSuperTokenBase is not included for people building CustomSuperToken. import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { ISuperToken } from "./ISuperToken.sol"; import { ISuperTokenFactory } from "./ISuperTokenFactory.sol"; import { ISETH } from "../tokens/ISETH.sol"; /// Superfluid/ERC20x NFTs import { IFlowNFTBase } from "./IFlowNFTBase.sol"; import { IConstantOutflowNFT } from "./IConstantOutflowNFT.sol"; import { IConstantInflowNFT } from "./IConstantInflowNFT.sol"; import { IPoolAdminNFT } from "../agreements/gdav1/IPoolAdminNFT.sol"; import { IPoolMemberNFT } from "../agreements/gdav1/IPoolMemberNFT.sol"; /// Superfluid agreement interfaces: import { ISuperAgreement } from "./ISuperAgreement.sol"; import { IConstantFlowAgreementV1 } from "../agreements/IConstantFlowAgreementV1.sol"; import { IInstantDistributionAgreementV1 } from "../agreements/IInstantDistributionAgreementV1.sol"; import { IGeneralDistributionAgreementV1, PoolConfig } from "../agreements/gdav1/IGeneralDistributionAgreementV1.sol"; import { ISuperfluidPool } from "../agreements/gdav1/ISuperfluidPool.sol"; /// Superfluid App interfaces: import { ISuperApp } from "./ISuperApp.sol"; /// Superfluid governance import { ISuperfluidGovernance } from "./ISuperfluidGovernance.sol"; /** * @title Host interface * @author Superfluid * @notice This is the central contract of the system where super agreement, super app * and super token features are connected. * * The Superfluid host contract is also the entry point for the protocol users, * where batch call and meta transaction are provided for UX improvements. * */ interface ISuperfluid { /************************************************************************** * Errors *************************************************************************/ // Superfluid Custom Errors error HOST_AGREEMENT_CALLBACK_IS_NOT_ACTION(); // 0xef4295f6 error HOST_CANNOT_DOWNGRADE_TO_NON_UPGRADEABLE(); // 0x474e7641 error HOST_CALL_AGREEMENT_WITH_CTX_FROM_WRONG_ADDRESS(); // 0x0cd0ebc2 error HOST_CALL_APP_ACTION_WITH_CTX_FROM_WRONG_ADDRESS(); // 0x473f7bd4 error HOST_INVALID_CONFIG_WORD(); // 0xf4c802a4 error HOST_MAX_256_AGREEMENTS(); // 0x7c281a78 error HOST_NON_UPGRADEABLE(); // 0x14f72c9f error HOST_NON_ZERO_LENGTH_PLACEHOLDER_CTX(); // 0x67e9985b error HOST_ONLY_GOVERNANCE(); // 0xc5d22a4e error HOST_UNKNOWN_BATCH_CALL_OPERATION_TYPE(); // 0xb4770115 error HOST_AGREEMENT_ALREADY_REGISTERED(); // 0xdc9ddba8 error HOST_AGREEMENT_IS_NOT_REGISTERED(); // 0x1c9e9bea error HOST_MUST_BE_CONTRACT(); // 0xd4f6b30c error HOST_ONLY_LISTED_AGREEMENT(); // 0x619c5359 error HOST_NEED_MORE_GAS(); // 0xd4f5d496 // App Related Custom Errors // uses SuperAppDefinitions' App Jail Reasons as _code error APP_RULE(uint256 _code); // 0xa85ba64f error HOST_NOT_A_SUPER_APP(); // 0x163cbe43 error HOST_NO_APP_REGISTRATION_PERMISSION(); // 0xb56455f0 error HOST_RECEIVER_IS_NOT_SUPER_APP(); // 0x96aa315e error HOST_SENDER_IS_NOT_SUPER_APP(); // 0xbacfdc40 error HOST_SOURCE_APP_NEEDS_HIGHER_APP_LEVEL(); // 0x44725270 error HOST_SUPER_APP_IS_JAILED(); // 0x02384b64 error HOST_SUPER_APP_ALREADY_REGISTERED(); // 0x01b0a935 /************************************************************************** * Time * * > The Oracle: You have the sight now, Neo. You are looking at the world without time. * > Neo: Then why can't I see what happens to her? * > The Oracle: We can never see past the choices we don't understand. * > - The Oracle and Neo conversing about the future of Trinity and the effects of Neo's choices *************************************************************************/ function getNow() external view returns (uint256); /************************************************************************** * Governance *************************************************************************/ /** * @dev Get the current governance address of the Superfluid host */ function getGovernance() external view returns(ISuperfluidGovernance governance); /** * @dev Replace the current governance with a new one */ function replaceGovernance(ISuperfluidGovernance newGov) external; /** * @dev Governance replaced event * @param oldGov Address of the old governance contract * @param newGov Address of the new governance contract */ event GovernanceReplaced(ISuperfluidGovernance oldGov, ISuperfluidGovernance newGov); /************************************************************************** * Agreement Whitelisting *************************************************************************/ /** * @dev Register a new agreement class to the system * @param agreementClassLogic Initial agreement class code * * @custom:modifiers * - onlyGovernance */ function registerAgreementClass(ISuperAgreement agreementClassLogic) external; /** * @notice Agreement class registered event * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param agreementType The agreement type registered * @param code Address of the new agreement */ event AgreementClassRegistered(bytes32 agreementType, address code); /** * @dev Update code of an agreement class * @param agreementClassLogic New code for the agreement class * * @custom:modifiers * - onlyGovernance */ function updateAgreementClass(ISuperAgreement agreementClassLogic) external; /** * @notice Agreement class updated event * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param agreementType The agreement type updated * @param code Address of the new agreement */ event AgreementClassUpdated(bytes32 agreementType, address code); /** * @notice Check if the agreement type is whitelisted * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" */ function isAgreementTypeListed(bytes32 agreementType) external view returns(bool yes); /** * @dev Check if the agreement class is whitelisted */ function isAgreementClassListed(ISuperAgreement agreementClass) external view returns(bool yes); /** * @notice Get agreement class * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" */ function getAgreementClass(bytes32 agreementType) external view returns(ISuperAgreement agreementClass); /** * @dev Map list of the agreement classes using a bitmap * @param bitmap Agreement class bitmap */ function mapAgreementClasses(uint256 bitmap) external view returns (ISuperAgreement[] memory agreementClasses); /** * @notice Create a new bitmask by adding a agreement class to it * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param bitmap Agreement class bitmap */ function addToAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType) external view returns (uint256 newBitmap); /** * @notice Create a new bitmask by removing a agreement class from it * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param bitmap Agreement class bitmap */ function removeFromAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType) external view returns (uint256 newBitmap); /************************************************************************** * Super Token Factory **************************************************************************/ /** * @dev Get the super token factory * @return factory The factory */ function getSuperTokenFactory() external view returns (ISuperTokenFactory factory); /** * @dev Get the super token factory logic (applicable to upgradable deployment) * @return logic The factory logic */ function getSuperTokenFactoryLogic() external view returns (address logic); /** * @dev Update super token factory * @param newFactory New factory logic */ function updateSuperTokenFactory(ISuperTokenFactory newFactory) external; /** * @dev SuperToken factory updated event * @param newFactory Address of the new factory */ event SuperTokenFactoryUpdated(ISuperTokenFactory newFactory); /** * @notice Update the super token logic to the latest (canonical) implementation * if `newLogicOverride` is zero, or to `newLogicOverride` otherwise. * or to the provided implementation `. * @dev Refer to ISuperTokenFactory.Upgradability for expected behaviours */ function updateSuperTokenLogic(ISuperToken token, address newLogicOverride) external; /** * @notice Update the super token logic to the provided one * @dev newLogic must implement UUPSProxiable with matching proxiableUUID */ event SuperTokenLogicUpdated(ISuperToken indexed token, address code); /** * @notice Change the SuperToken admin address * @dev The admin is the only account allowed to update the token logic * For backward compatibility, the "host" is the default "admin" if unset (address(0)). */ function changeSuperTokenAdmin(ISuperToken token, address newAdmin) external; /** * @notice Change the implementation address the pool beacon points to * @dev Updating the logic the beacon points to will update the logic of all the Pool BeaconProxy instances */ function updatePoolBeaconLogic(address newBeaconLogic) external; /** * @dev Pool Beacon logic updated event * @param beaconProxy addrss of the beacon proxy * @param newBeaconLogic address of the new beacon logic */ event PoolBeaconLogicUpdated(address indexed beaconProxy, address newBeaconLogic); /************************************************************************** * App Registry *************************************************************************/ /** * @dev Message sender (must be a contract) registers itself as a super app. * @param configWord The super app manifest configuration, flags are defined in * `SuperAppDefinitions` * @notice On some mainnet deployments, pre-authorization by governance may be needed for this to succeed. * See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide */ function registerApp(uint256 configWord) external; /** * @dev Registers an app (must be a contract) as a super app. * @param app The super app address * @param configWord The super app manifest configuration, flags are defined in * `SuperAppDefinitions` * @notice On some mainnet deployments, pre-authorization by governance may be needed for this to succeed. * See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide */ function registerApp(ISuperApp app, uint256 configWord) external; /** * @dev App registered event * @param app Address of jailed app */ event AppRegistered(ISuperApp indexed app); /** * @dev DO NOT USE for new deployments * @custom:deprecated you should use `registerApp(uint256 configWord) instead. */ function registerAppWithKey(uint256 configWord, string calldata registrationKey) external; /** * @dev DO NOT USE for new deployments * @custom:deprecated you should use `registerApp(ISuperApp app, uint256 configWord) instead. */ function registerAppByFactory(ISuperApp app, uint256 configWord) external; /** * @dev Query if the app is registered * @param app Super app address */ function isApp(ISuperApp app) external view returns(bool); /** * @dev Query app callbacklevel * @param app Super app address */ function getAppCallbackLevel(ISuperApp app) external view returns(uint8 appCallbackLevel); /** * @dev Get the manifest of the super app * @param app Super app address */ function getAppManifest( ISuperApp app ) external view returns ( bool isSuperApp, bool isJailed, uint256 noopMask ); /** * @dev Query if the app has been jailed * @param app Super app address */ function isAppJailed(ISuperApp app) external view returns (bool isJail); /** * @dev Whitelist the target app for app composition for the source app (msg.sender) * @param targetApp The target super app address */ function allowCompositeApp(ISuperApp targetApp) external; /** * @dev Query if source app is allowed to call the target app as downstream app * @param app Super app address * @param targetApp The target super app address */ function isCompositeAppAllowed( ISuperApp app, ISuperApp targetApp ) external view returns (bool isAppAllowed); /************************************************************************** * Agreement Framework * * Agreements use these function to trigger super app callbacks, updates * app credit and charge gas fees. * * These functions can only be called by registered agreements. *************************************************************************/ /** * @dev (For agreements) StaticCall the app before callback * @param app The super app. * @param callData The call data sending to the super app. * @param isTermination Is it a termination callback? * @param ctx Current ctx, it will be validated. * @return cbdata Data returned from the callback. */ function callAppBeforeCallback( ISuperApp app, bytes calldata callData, bool isTermination, bytes calldata ctx ) external // onlyAgreement // assertValidCtx(ctx) returns(bytes memory cbdata); /** * @dev (For agreements) Call the app after callback * @param app The super app. * @param callData The call data sending to the super app. * @param isTermination Is it a termination callback? * @param ctx Current ctx, it will be validated. * @return newCtx The current context of the transaction. */ function callAppAfterCallback( ISuperApp app, bytes calldata callData, bool isTermination, bytes calldata ctx ) external // onlyAgreement // assertValidCtx(ctx) returns(bytes memory newCtx); /** * @dev (For agreements) Create a new callback stack * @param ctx The current ctx, it will be validated. * @param app The super app. * @param appCreditGranted App credit granted so far. * @param appCreditUsed App credit used so far. * @return newCtx The current context of the transaction. */ function appCallbackPush( bytes calldata ctx, ISuperApp app, uint256 appCreditGranted, int256 appCreditUsed, ISuperfluidToken appCreditToken ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev (For agreements) Pop from the current app callback stack * @param ctx The ctx that was pushed before the callback stack. * @param appCreditUsedDelta App credit used by the app. * @return newCtx The current context of the transaction. * * @custom:security * - Here we cannot do assertValidCtx(ctx), since we do not really save the stack in memory. * - Hence there is still implicit trust that the agreement handles the callback push/pop pair correctly. */ function appCallbackPop( bytes calldata ctx, int256 appCreditUsedDelta ) external // onlyAgreement returns (bytes memory newCtx); /** * @dev (For agreements) Use app credit. * @param ctx The current ctx, it will be validated. * @param appCreditUsedMore See app credit for more details. * @return newCtx The current context of the transaction. */ function ctxUseCredit( bytes calldata ctx, int256 appCreditUsedMore ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev (For agreements) Jail the app. * @param app The super app. * @param reason Jail reason code. * @return newCtx The current context of the transaction. */ function jailApp( bytes calldata ctx, ISuperApp app, uint256 reason ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev Jail event for the app * @param app Address of jailed app * @param reason Reason the app is jailed (see Definitions.sol for the full list) */ event Jail(ISuperApp indexed app, uint256 reason); /************************************************************************** * Contextless Call Proxies * * NOTE: For EOAs or non-app contracts, they are the entry points for interacting * with agreements or apps. * * NOTE: The contextual call data should be generated using * abi.encodeWithSelector. The context parameter should be set to "0x", * an empty bytes array as a placeholder to be replaced by the host * contract. *************************************************************************/ /** * @dev Call agreement function * @param agreementClass The agreement address you are calling * @param callData The contextual call data with placeholder ctx * @param userData Extra user data being sent to the super app callbacks */ function callAgreement( ISuperAgreement agreementClass, bytes calldata callData, bytes calldata userData ) external //cleanCtx //isAgreement(agreementClass) returns(bytes memory returnedData); /** * @notice Call app action * @dev Main use case is calling app action in a batch call via the host * @param callData The contextual call data * * @custom:note See "Contextless Call Proxies" above for more about contextual call data. */ function callAppAction( ISuperApp app, bytes calldata callData ) external //cleanCtx //isAppActive(app) //isValidAppAction(callData) returns(bytes memory returnedData); /************************************************************************** * Contextual Call Proxies and Context Utilities * * For apps, they must use context they receive to interact with * agreements or apps. * * The context changes must be saved and returned by the apps in their * callbacks always, any modification to the context will be detected and * the violating app will be jailed. *************************************************************************/ /** * @dev Context Struct * * @custom:note on backward compatibility: * - Non-dynamic fields are padded to 32bytes and packed * - Dynamic fields are referenced through a 32bytes offset to their "parents" field (or root) * - The order of the fields hence should not be rearranged in order to be backward compatible: * - non-dynamic fields will be parsed at the same memory location, * - and dynamic fields will simply have a greater offset than it was. * - We cannot change the structure of the Context struct because of ABI compatibility requirements */ struct Context { // // Call context // // app callback level uint8 appCallbackLevel; // type of call uint8 callType; // the system timestamp uint256 timestamp; // The intended message sender for the call address msgSender; // // Callback context // // For callbacks it is used to know which agreement function selector is called bytes4 agreementSelector; // User provided data for app callbacks bytes userData; // // App context // // app credit granted uint256 appCreditGranted; // app credit wanted by the app callback uint256 appCreditWantedDeprecated; // app credit used, allowing negative values over a callback session // the appCreditUsed value over a callback sessions is calculated with: // existing flow data owed deposit + sum of the callback agreements // deposit deltas // the final value used to modify the state is determined by the // _adjustNewAppCreditUsed function (in AgreementLibrary.sol) which takes // the appCreditUsed value reached in the callback session and the app // credit granted int256 appCreditUsed; // app address address appAddress; // app credit in super token ISuperfluidToken appCreditToken; } function callAgreementWithContext( ISuperAgreement agreementClass, bytes calldata callData, bytes calldata userData, bytes calldata ctx ) external // requireValidCtx(ctx) // onlyAgreement(agreementClass) returns (bytes memory newCtx, bytes memory returnedData); function callAppActionWithContext( ISuperApp app, bytes calldata callData, bytes calldata ctx ) external // requireValidCtx(ctx) // isAppActive(app) returns (bytes memory newCtx); function decodeCtx(bytes memory ctx) external pure returns (Context memory context); function isCtxValid(bytes calldata ctx) external view returns (bool); /************************************************************************** * Batch call **************************************************************************/ /** * @dev Batch operation data */ struct Operation { // Operation type. Defined in BatchOperation (Definitions.sol) uint32 operationType; // Operation target address target; // Data specific to the operation bytes data; } /** * @dev Batch call function * @param operations Array of batch operations * * NOTE: `batchCall` is `payable, because there's limited support for sending * native tokens to batch operation targets. * If value is > 0, the whole amount is sent to the first operation matching any of: * - OPERATION_TYPE_SUPERFLUID_CALL_APP_ACTION * - OPERATION_TYPE_SIMPLE_FORWARD_CALL * - OPERATION_TYPE_ERC2771_FORWARD_CALL * If the first such operation does not allow receiving native tokens, * the transaction will revert. * It's currently not possible to send native tokens to multiple operations, or to * any but the first operation of one of the above mentioned types. * If no such operation is included, the native tokens will be sent back to the sender. */ function batchCall(Operation[] calldata operations) external payable; /** * @dev Batch call function with EIP-2771 encoded msgSender * @param operations Array of batch operations * * NOTE: This can be called only by contracts recognized as _trusted forwarder_ * by the host contract (see `Superfluid.isTrustedForwarder`). * If native tokens are passed along, the same rules as for `batchCall` apply, * with an optional refund going to the encoded msgSender. */ function forwardBatchCall(Operation[] calldata operations) external payable; /************************************************************************** * Function modifiers for access control and parameter validations * * While they cannot be explicitly stated in function definitions, they are * listed in function definition comments instead for clarity. * * TODO: turning these off because solidity-coverage doesn't like it *************************************************************************/ /* /// @dev The current superfluid context is clean. modifier cleanCtx() virtual; /// @dev Require the ctx being valid. modifier requireValidCtx(bytes memory ctx) virtual; /// @dev Assert the ctx being valid. modifier assertValidCtx(bytes memory ctx) virtual; /// @dev The agreement is a listed agreement. modifier isAgreement(ISuperAgreement agreementClass) virtual; // onlyGovernance /// @dev The msg.sender must be a listed agreement. modifier onlyAgreement() virtual; /// @dev The app is registered and not jailed. modifier isAppActive(ISuperApp app) virtual; */ }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { ISuperToken } from "./ISuperToken.sol"; /** * @title Super token factory interface * @author Superfluid */ interface ISuperTokenFactory { /************************************************************************** * Errors *************************************************************************/ error SUPER_TOKEN_FACTORY_ALREADY_EXISTS(); // 0x91d67972 error SUPER_TOKEN_FACTORY_DOES_NOT_EXIST(); // 0x872cac48 error SUPER_TOKEN_FACTORY_UNINITIALIZED(); // 0x1b39b9b4 error SUPER_TOKEN_FACTORY_ONLY_HOST(); // 0x478b8e83 error SUPER_TOKEN_FACTORY_NON_UPGRADEABLE_IS_DEPRECATED(); // 0xc4901a43 error SUPER_TOKEN_FACTORY_ZERO_ADDRESS(); // 0x305c9e82 /** * @dev Get superfluid host contract address */ function getHost() external view returns(address host); /// @dev Initialize the contract function initialize() external; /** * @notice Get the canonical super token logic. */ function getSuperTokenLogic() external view returns (ISuperToken superToken); /** * @dev Upgradability modes */ enum Upgradability { /// Non upgradable super token, `host.updateSuperTokenLogic` will revert NON_UPGRADABLE, /// Upgradable through `host.updateSuperTokenLogic` operation SEMI_UPGRADABLE, /// Always using the latest super token logic FULL_UPGRADABLE } /** * @notice Create new super token wrapper for the underlying ERC20 token * @param underlyingToken Underlying ERC20 token * @param underlyingDecimals Underlying token decimals * @param upgradability Upgradability mode * @param name Super token name * @param symbol Super token symbol * @param admin Admin address * @return superToken The deployed and initialized wrapper super token */ function createERC20Wrapper( IERC20Metadata underlyingToken, uint8 underlyingDecimals, Upgradability upgradability, string calldata name, string calldata symbol, address admin ) external returns (ISuperToken superToken); /** * @notice Create new super token wrapper for the underlying ERC20 token * @param underlyingToken Underlying ERC20 token * @param underlyingDecimals Underlying token decimals * @param upgradability Upgradability mode * @param name Super token name * @param symbol Super token symbol * @return superToken The deployed and initialized wrapper super token */ function createERC20Wrapper( IERC20Metadata underlyingToken, uint8 underlyingDecimals, Upgradability upgradability, string calldata name, string calldata symbol ) external returns (ISuperToken superToken); /** * @notice Create new super token wrapper for the underlying ERC20 token * @param underlyingToken Underlying ERC20 token * @param upgradability Upgradability mode * @param name Super token name * @param symbol Super token symbol * @param admin Admin address * @return superToken The deployed and initialized wrapper super token */ function createERC20Wrapper( IERC20Metadata underlyingToken, Upgradability upgradability, string calldata name, string calldata symbol, address admin ) external returns (ISuperToken superToken); /** * @notice Create new super token wrapper for the underlying ERC20 token with extra token info * @param underlyingToken Underlying ERC20 token * @param upgradability Upgradability mode * @param name Super token name * @param symbol Super token symbol * @return superToken The deployed and initialized wrapper super token * NOTE: * - It assumes token provide the .decimals() function */ function createERC20Wrapper( IERC20Metadata underlyingToken, Upgradability upgradability, string calldata name, string calldata symbol ) external returns (ISuperToken superToken); /** * @notice Creates a wrapper super token AND sets it in the canonical list OR reverts if it already exists * @dev salt for create2 is the keccak256 hash of abi.encode(address(_underlyingToken)) * @param _underlyingToken Underlying ERC20 token * @return ISuperToken the created supertoken */ function createCanonicalERC20Wrapper(IERC20Metadata _underlyingToken) external returns (ISuperToken); /** * @notice Computes/Retrieves wrapper super token address given the underlying token address * @dev We return from our canonical list if it already exists, otherwise we compute it * @dev note that this function only computes addresses for SEMI_UPGRADABLE SuperTokens * @param _underlyingToken Underlying ERC20 token address * @return superTokenAddress Super token address * @return isDeployed whether the super token is deployed AND set in the canonical mapping */ function computeCanonicalERC20WrapperAddress(address _underlyingToken) external view returns (address superTokenAddress, bool isDeployed); /** * @notice Gets the canonical ERC20 wrapper super token address given the underlying token address * @dev We return the address if it exists and the zero address otherwise * @param _underlyingTokenAddress Underlying ERC20 token address * @return superTokenAddress Super token address */ function getCanonicalERC20Wrapper(address _underlyingTokenAddress) external view returns (address superTokenAddress); /** * @dev Creates a new custom super token * @param customSuperTokenProxy address of the custom supertoken proxy */ function initializeCustomSuperToken( address customSuperTokenProxy ) external; /** * @dev Super token logic created event * @param tokenLogic Token logic address */ event SuperTokenLogicCreated(ISuperToken indexed tokenLogic); /** * @dev Super token created event * @param token Newly created super token address */ event SuperTokenCreated(ISuperToken indexed token); /** * @dev Custom super token created event * @param token Newly created custom super token address */ event CustomSuperTokenCreated(ISuperToken indexed token); }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; import { IConstantOutflowNFT } from "./IConstantOutflowNFT.sol"; import { IConstantInflowNFT } from "./IConstantInflowNFT.sol"; import { IPoolAdminNFT } from "../agreements/gdav1/IPoolAdminNFT.sol"; import { IPoolMemberNFT } from "../agreements/gdav1/IPoolMemberNFT.sol"; /** * @title Super token (Superfluid Token + ERC20 + ERC777) interface * @author Superfluid */ interface ISuperToken is ISuperfluidToken, IERC20Metadata, IERC777 { /************************************************************************** * Errors *************************************************************************/ error SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); // 0xf7f02227 error SUPER_TOKEN_NOT_ERC777_TOKENS_RECIPIENT(); // 0xfe737d05 error SUPER_TOKEN_INFLATIONARY_DEFLATIONARY_NOT_SUPPORTED(); // 0xe3e13698 error SUPER_TOKEN_NO_UNDERLYING_TOKEN(); // 0xf79cf656 error SUPER_TOKEN_ONLY_SELF(); // 0x7ffa6648 error SUPER_TOKEN_ONLY_ADMIN(); // 0x0484acab error SUPER_TOKEN_ONLY_GOV_OWNER(); // 0xd9c7ed08 error SUPER_TOKEN_APPROVE_FROM_ZERO_ADDRESS(); // 0x81638627 error SUPER_TOKEN_APPROVE_TO_ZERO_ADDRESS(); // 0xdf070274 error SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS(); // 0xba2ab184 error SUPER_TOKEN_MINT_TO_ZERO_ADDRESS(); // 0x0d243157 error SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); // 0xeecd6c9b error SUPER_TOKEN_TRANSFER_TO_ZERO_ADDRESS(); // 0xe219bd39 error SUPER_TOKEN_NFT_PROXY_ADDRESS_CHANGED(); // 0x6bef249d /** * @dev Initialize the contract */ function initialize( IERC20 underlyingToken, uint8 underlyingDecimals, string calldata n, string calldata s ) external; /** * @dev Initialize the contract with an admin */ function initializeWithAdmin( IERC20 underlyingToken, uint8 underlyingDecimals, string calldata n, string calldata s, address admin ) external; /** * @notice Changes the admin for the SuperToken * @dev Only the current admin can call this function * if admin is address(0), it is implicitly the host address * @param newAdmin New admin address */ function changeAdmin(address newAdmin) external; event AdminChanged(address indexed oldAdmin, address indexed newAdmin); /** * @dev Returns the admin address for the SuperToken */ function getAdmin() external view returns (address admin); /************************************************************************** * Immutable variables *************************************************************************/ // solhint-disable-next-line func-name-mixedcase function CONSTANT_OUTFLOW_NFT() external view returns (IConstantOutflowNFT); // solhint-disable-next-line func-name-mixedcase function CONSTANT_INFLOW_NFT() external view returns (IConstantInflowNFT); // solhint-disable-next-line func-name-mixedcase function POOL_ADMIN_NFT() external view returns (IPoolAdminNFT); // solhint-disable-next-line func-name-mixedcase function POOL_MEMBER_NFT() external view returns (IPoolMemberNFT); /************************************************************************** * IERC20Metadata & ERC777 *************************************************************************/ /** * @dev Returns the name of the token. */ function name() external view override(IERC777, IERC20Metadata) returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view override(IERC777, IERC20Metadata) returns (string memory); /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * @custom:note SuperToken always uses 18 decimals. * * This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external view override(IERC20Metadata) returns (uint8); /************************************************************************** * ERC20 & ERC777 *************************************************************************/ /** * @dev See {IERC20-totalSupply}. */ function totalSupply() external view override(IERC777, IERC20) returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address account) external view override(IERC777, IERC20) returns(uint256 balance); /************************************************************************** * ERC20 *************************************************************************/ /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external override(IERC20) 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. * * @notice This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external override(IERC20) view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:note 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 * * @custom:emits an {Approval} event. */ function approve(address spender, uint256 amount) external override(IERC20) returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external override(IERC20) returns (bool); /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * @custom:emits an {Approval} event indicating the updated allowance. * * @custom:requirements * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) external returns (bool); /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * @custom:emits an {Approval} event indicating the updated allowance. * * @custom:requirements * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); /************************************************************************** * ERC777 *************************************************************************/ /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * @custom:note For super token contracts, this value is always 1 */ function granularity() external view override(IERC777) returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * @dev If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `userData` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * @custom:emits a {Sent} event. * * @custom:requirements * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send(address recipient, uint256 amount, bytes calldata userData) external override(IERC777); /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply and transfers the underlying token to the caller's account. * * If a send hook is registered for the caller, the corresponding function * will be called with `userData` and empty `operatorData`. See {IERC777Sender}. * * @custom:emits a {Burned} event. * * @custom:requirements * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata userData) external override(IERC777); /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external override(IERC777) view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * @custom:emits an {AuthorizedOperator} event. * * @custom:requirements * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external override(IERC777); /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * @custom:emits a {RevokedOperator} event. * * @custom:requirements * - `operator` cannot be calling address. */ function revokeOperator(address operator) external override(IERC777); /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external override(IERC777) view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `userData` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * @custom:emits a {Sent} event. * * @custom:requirements * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external override(IERC777); /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `userData` and `operatorData`. See {IERC777Sender}. * * @custom:emits a {Burned} event. * * @custom:requirements * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external override(IERC777); /************************************************************************** * SuperToken custom token functions *************************************************************************/ /** * @dev Mint new tokens for the account * If `userData` is not empty, the `tokensReceived` hook is invoked according to ERC777 semantics. * * @custom:modifiers * - onlySelf */ function selfMint( address account, uint256 amount, bytes memory userData ) external; /** * @dev Burn existing tokens for the account * If `userData` is not empty, the `tokensToSend` hook is invoked according to ERC777 semantics. * * @custom:modifiers * - onlySelf */ function selfBurn( address account, uint256 amount, bytes memory userData ) external; /** * @dev Transfer `amount` tokens from the `sender` to `recipient`. * If `spender` isn't the same as `sender`, checks if `spender` has allowance to * spend tokens of `sender`. * * @custom:modifiers * - onlySelf */ function selfTransferFrom( address sender, address spender, address recipient, uint256 amount ) external; /** * @dev Give `spender`, `amount` allowance to spend the tokens of * `account`. * * @custom:modifiers * - onlySelf */ function selfApproveFor( address account, address spender, uint256 amount ) external; /************************************************************************** * SuperToken extra functions *************************************************************************/ /** * @dev Transfer all available balance from `msg.sender` to `recipient` */ function transferAll(address recipient) external; /************************************************************************** * ERC20 wrapping *************************************************************************/ /** * @dev Return the underlying token contract * @return tokenAddr Underlying token address */ function getUnderlyingToken() external view returns(address tokenAddr); /** * @dev Return the underlying token decimals * @return underlyingDecimals Underlying token decimals */ function getUnderlyingDecimals() external view returns (uint8 underlyingDecimals); /** * @dev Return the underlying token conversion rate * @param amount Number of tokens to be upgraded (in 18 decimals) * @return underlyingAmount The underlying token amount after scaling * @return adjustedAmount The super token amount after scaling */ function toUnderlyingAmount(uint256 amount) external view returns (uint256 underlyingAmount, uint256 adjustedAmount); /** * @dev Upgrade ERC20 to SuperToken. * @param amount Number of tokens to be upgraded (in 18 decimals) * * @custom:note It will use `transferFrom` to get tokens. Before calling this * function you should `approve` this contract */ function upgrade(uint256 amount) external; /** * @dev Upgrade ERC20 to SuperToken and transfer immediately * @param to The account to receive upgraded tokens * @param amount Number of tokens to be upgraded (in 18 decimals) * @param userData User data for the TokensRecipient callback * * @custom:note It will use `transferFrom` to get tokens. Before calling this * function you should `approve` this contract * * @custom:warning * - there is potential of reentrancy IF the "to" account is a registered ERC777 recipient. * @custom:requirements * - if `userData` is NOT empty AND `to` is a contract, it MUST be a registered ERC777 recipient * otherwise it reverts. */ function upgradeTo(address to, uint256 amount, bytes calldata userData) external; /** * @dev Token upgrade event * @param account Account where tokens are upgraded to * @param amount Amount of tokens upgraded (in 18 decimals) */ event TokenUpgraded( address indexed account, uint256 amount ); /** * @dev Downgrade SuperToken to ERC20. * @dev It will call transfer to send tokens * @param amount Number of tokens to be downgraded */ function downgrade(uint256 amount) external; /** * @dev Downgrade SuperToken to ERC20 and transfer immediately * @param to The account to receive downgraded tokens * @param amount Number of tokens to be downgraded (in 18 decimals) */ function downgradeTo(address to, uint256 amount) external; /** * @dev Token downgrade event * @param account Account whose tokens are downgraded * @param amount Amount of tokens downgraded */ event TokenDowngraded( address indexed account, uint256 amount ); /************************************************************************** * Batch Operations *************************************************************************/ /** * @dev Perform ERC20 approve by host contract. * @param account The account owner to be approved. * @param spender The spender of account owner's funds. * @param amount Number of tokens to be approved. * * @custom:modifiers * - onlyHost */ function operationApprove( address account, address spender, uint256 amount ) external; function operationIncreaseAllowance( address account, address spender, uint256 addedValue ) external; function operationDecreaseAllowance( address account, address spender, uint256 subtractedValue ) external; /** * @dev Perform ERC20 transferFrom by host contract. * @param account The account to spend sender's funds. * @param spender The account where the funds is sent from. * @param recipient The recipient of the funds. * @param amount Number of tokens to be transferred. * * @custom:modifiers * - onlyHost */ function operationTransferFrom( address account, address spender, address recipient, uint256 amount ) external; /** * @dev Perform ERC777 send by host contract. * @param spender The account where the funds is sent from. * @param recipient The recipient of the funds. * @param amount Number of tokens to be transferred. * @param userData Arbitrary user inputted data * * @custom:modifiers * - onlyHost */ function operationSend( address spender, address recipient, uint256 amount, bytes memory userData ) external; /** * @dev Upgrade ERC20 to SuperToken by host contract. * @param account The account to be changed. * @param amount Number of tokens to be upgraded (in 18 decimals) * * @custom:modifiers * - onlyHost */ function operationUpgrade(address account, uint256 amount) external; /** * @dev Downgrade ERC20 to SuperToken by host contract. * @param account The account to be changed. * @param amount Number of tokens to be downgraded (in 18 decimals) * * @custom:modifiers * - onlyHost */ function operationDowngrade(address account, uint256 amount) external; /** * @dev Upgrade ERC20 to SuperToken by host contract and transfer immediately. * @param account The account to be changed. * @param to The account to receive upgraded tokens * @param amount Number of tokens to be upgraded (in 18 decimals) * * @custom:modifiers * - onlyHost */ function operationUpgradeTo(address account, address to, uint256 amount) external; /** * @dev Downgrade ERC20 to SuperToken by host contract and transfer immediately. * @param account The account to be changed. * @param to The account to receive downgraded tokens * @param amount Number of tokens to be downgraded (in 18 decimals) * * @custom:modifiers * - onlyHost */ function operationDowngradeTo(address account, address to, uint256 amount) external; // Flow NFT events /** * @dev Constant Outflow NFT proxy created event * @param constantOutflowNFT constant outflow nft address */ event ConstantOutflowNFTCreated( IConstantOutflowNFT indexed constantOutflowNFT ); /** * @dev Constant Inflow NFT proxy created event * @param constantInflowNFT constant inflow nft address */ event ConstantInflowNFTCreated( IConstantInflowNFT indexed constantInflowNFT ); /** * @dev Pool Admin NFT proxy created event * @param poolAdminNFT pool admin nft address */ event PoolAdminNFTCreated( IPoolAdminNFT indexed poolAdminNFT ); /** * @dev Pool Member NFT proxy created event * @param poolMemberNFT pool member nft address */ event PoolMemberNFTCreated( IPoolMemberNFT indexed poolMemberNFT ); /************************************************************************** * Function modifiers for access control and parameter validations * * While they cannot be explicitly stated in function definitions, they are * listed in function definition comments instead for clarity. * * NOTE: solidity-coverage not supporting it *************************************************************************/ /// @dev The msg.sender must be the contract itself //modifier onlySelf() virtual }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperToken } from "./ISuperToken.sol"; /** * @title SuperApp interface * @author Superfluid * @dev Be aware of the app being jailed, when the word permitted is used. */ interface ISuperApp { /** * @dev Callback before a new agreement is created. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass * arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Only revert with a "reason" is permitted. */ function beforeAgreementCreated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is created. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Only revert with a "reason" is permitted. */ function afterAgreementCreated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); /** * @dev Callback before a new agreement is updated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass * arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Only revert with a "reason" is permitted. */ function beforeAgreementUpdated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is updated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Only revert with a "reason" is permitted. */ function afterAgreementUpdated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); /** * @dev Callback before a new agreement is terminated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass arbitary information to * the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Revert is not permitted. */ function beforeAgreementTerminated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is terminated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Revert is not permitted. */ function afterAgreementTerminated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; /** * @title Super agreement interface * @author Superfluid */ interface ISuperAgreement { /** * @dev Get the type of the agreement class */ function agreementType() external view returns (bytes32); /** * @dev Calculate the real-time balance for the account of this agreement class * @param account Account the state belongs to * @param time Time used for the calculation * @return dynamicBalance Dynamic balance portion of real-time balance of this agreement * @return deposit Account deposit amount of this agreement * @return owedDeposit Account owed deposit amount of this agreement */ function realtimeBalanceOf( ISuperfluidToken token, address account, uint256 time ) external view returns ( int256 dynamicBalance, uint256 deposit, uint256 owedDeposit ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.11; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; interface IFlowNFTBase is IERC721Metadata { // FlowNFTData struct storage packing: // b = bits // WORD 1: | superToken | FREE // | 160b | 96b // WORD 2: | flowSender | FREE // | 160b | 96b // WORD 3: | flowReceiver | flowStartDate | FREE // | 160b | 32b | 64b struct FlowNFTData { address superToken; address flowSender; address flowReceiver; uint32 flowStartDate; } /************************************************************************** * Custom Errors *************************************************************************/ error CFA_NFT_APPROVE_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0xa3352582 error CFA_NFT_APPROVE_TO_CALLER(); // 0xd3c77329 error CFA_NFT_APPROVE_TO_CURRENT_OWNER(); // 0xe4790b25 error CFA_NFT_INVALID_TOKEN_ID(); // 0xeab95e3b error CFA_NFT_ONLY_SUPER_TOKEN_FACTORY(); // 0xebb7505b error CFA_NFT_TRANSFER_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0x2551d606 error CFA_NFT_TRANSFER_FROM_INCORRECT_OWNER(); // 0x5a26c744 error CFA_NFT_TRANSFER_IS_NOT_ALLOWED(); // 0xaa747eca error CFA_NFT_TRANSFER_TO_ZERO_ADDRESS(); // 0xde06d21e /************************************************************************** * Events *************************************************************************/ /// @notice Informs third-party platforms that NFT metadata should be updated /// @dev This event comes from https://eips.ethereum.org/EIPS/eip-4906 /// @param tokenId the id of the token that should have its metadata updated event MetadataUpdate(uint256 tokenId); /************************************************************************** * View *************************************************************************/ /// @notice An external function for querying flow data by `tokenId`` /// @param tokenId the token id /// @return flowData the flow data associated with `tokenId` function flowDataByTokenId( uint256 tokenId ) external view returns (FlowNFTData memory flowData); /// @notice An external function for computing the deterministic tokenId /// @dev tokenId = uint256(keccak256(abi.encode(block.chainId, superToken, flowSender, flowReceiver))) /// @param superToken the super token /// @param flowSender the flow sender /// @param flowReceiver the flow receiver /// @return tokenId the tokenId function getTokenId( address superToken, address flowSender, address flowReceiver ) external view returns (uint256); /************************************************************************** * Write *************************************************************************/ function initialize( string memory nftName, string memory nftSymbol ) external; // initializer; function triggerMetadataUpdate(uint256 tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.11; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { IFlowNFTBase } from "./IFlowNFTBase.sol"; interface IConstantOutflowNFT is IFlowNFTBase { /************************************************************************** * Custom Errors *************************************************************************/ error COF_NFT_INVALID_SUPER_TOKEN(); // 0x6de98774 error COF_NFT_MINT_TO_AND_FLOW_RECEIVER_SAME(); // 0x0d1d1161 error COF_NFT_MINT_TO_ZERO_ADDRESS(); // 0x43d05e51 error COF_NFT_ONLY_CONSTANT_INFLOW(); // 0xa495a718 error COF_NFT_ONLY_FLOW_AGREEMENTS(); // 0xd367b64f error COF_NFT_TOKEN_ALREADY_EXISTS(); // 0xe2480183 /************************************************************************** * Write Functions *************************************************************************/ /// @notice The onCreate function is called when a new flow is created. /// @param token the super token passed from the CFA (flowVars) /// @param flowSender the flow sender /// @param flowReceiver the flow receiver function onCreate(ISuperfluidToken token, address flowSender, address flowReceiver) external; /// @notice The onUpdate function is called when a flow is updated. /// @param token the super token passed from the CFA (flowVars) /// @param flowSender the flow sender /// @param flowReceiver the flow receiver function onUpdate(ISuperfluidToken token, address flowSender, address flowReceiver) external; /// @notice The onDelete function is called when a flow is deleted. /// @param token the super token passed from the CFA (flowVars) /// @param flowSender the flow sender /// @param flowReceiver the flow receiver function onDelete(ISuperfluidToken token, address flowSender, address flowReceiver) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.11; import { IFlowNFTBase } from "./IFlowNFTBase.sol"; interface IConstantInflowNFT is IFlowNFTBase { /************************************************************************** * Custom Errors *************************************************************************/ error CIF_NFT_ONLY_CONSTANT_OUTFLOW(); // 0xe81ef57a /************************************************************************** * Write Functions *************************************************************************/ /// @notice The mint function emits the "mint" `Transfer` event. /// @dev We don't modify storage as this is handled in ConstantOutflowNFT.sol and this function's sole purpose /// is to inform clients that search for events. /// @param to the flow receiver (inflow NFT receiver) /// @param newTokenId the new token id function mint(address to, uint256 newTokenId) external; /// @notice This burn function emits the "burn" `Transfer` event. /// @dev We don't modify storage as this is handled in ConstantOutflowNFT.sol and this function's sole purpose /// is to inform clients that search for events. /// @param tokenId desired token id to burn function burn(uint256 tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; /** * @title Super app definitions library * @author Superfluid */ library SuperAppDefinitions { /************************************************************************** / App manifest config word /**************************************************************************/ /* * App level is a way to allow the app to whitelist what other app it can * interact with (aka. composite app feature). * * For more details, refer to the technical paper of superfluid protocol. */ uint256 constant internal APP_LEVEL_MASK = 0xFF; // The app is at the final level, hence it doesn't want to interact with any other app uint256 constant internal APP_LEVEL_FINAL = 1 << 0; // The app is at the second level, it may interact with other final level apps if whitelisted uint256 constant internal APP_LEVEL_SECOND = 1 << 1; function getAppCallbackLevel(uint256 configWord) internal pure returns (uint8) { return uint8(configWord & APP_LEVEL_MASK); } uint256 constant internal APP_JAIL_BIT = 1 << 15; function isAppJailed(uint256 configWord) internal pure returns (bool) { return (configWord & SuperAppDefinitions.APP_JAIL_BIT) > 0; } /************************************************************************** / Callback implementation bit masks /**************************************************************************/ uint256 constant internal AGREEMENT_CALLBACK_NOOP_BITMASKS = 0xFF << 32; uint256 constant internal BEFORE_AGREEMENT_CREATED_NOOP = 1 << (32 + 0); uint256 constant internal AFTER_AGREEMENT_CREATED_NOOP = 1 << (32 + 1); uint256 constant internal BEFORE_AGREEMENT_UPDATED_NOOP = 1 << (32 + 2); uint256 constant internal AFTER_AGREEMENT_UPDATED_NOOP = 1 << (32 + 3); uint256 constant internal BEFORE_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 4); uint256 constant internal AFTER_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 5); /************************************************************************** / App Jail Reasons /**************************************************************************/ uint256 constant internal APP_RULE_NO_REVERT_ON_TERMINATION_CALLBACK = 10; uint256 constant internal APP_RULE_NO_CRITICAL_SENDER_ACCOUNT = 11; uint256 constant internal APP_RULE_NO_CRITICAL_RECEIVER_ACCOUNT = 12; uint256 constant internal APP_RULE_CTX_IS_READONLY = 20; uint256 constant internal APP_RULE_CTX_IS_NOT_CLEAN = 21; uint256 constant internal APP_RULE_CTX_IS_MALFORMATED = 22; uint256 constant internal APP_RULE_COMPOSITE_APP_IS_NOT_WHITELISTED = 30; uint256 constant internal APP_RULE_COMPOSITE_APP_IS_JAILED = 31; uint256 constant internal APP_RULE_MAX_APP_LEVEL_REACHED = 40; // Validate configWord cleaness for future compatibility, or else may introduce undefined future behavior function isConfigWordClean(uint256 configWord) internal pure returns (bool) { return (configWord & ~(APP_LEVEL_MASK | APP_JAIL_BIT | AGREEMENT_CALLBACK_NOOP_BITMASKS)) == uint256(0); } } /** * @title Context definitions library * @author Superfluid */ library ContextDefinitions { /************************************************************************** / Call info /**************************************************************************/ // app level uint256 constant internal CALL_INFO_APP_LEVEL_MASK = 0xFF; // call type uint256 constant internal CALL_INFO_CALL_TYPE_SHIFT = 32; uint256 constant internal CALL_INFO_CALL_TYPE_MASK = 0xF << CALL_INFO_CALL_TYPE_SHIFT; uint8 constant internal CALL_INFO_CALL_TYPE_AGREEMENT = 1; uint8 constant internal CALL_INFO_CALL_TYPE_APP_ACTION = 2; uint8 constant internal CALL_INFO_CALL_TYPE_APP_CALLBACK = 3; function decodeCallInfo(uint256 callInfo) internal pure returns (uint8 appCallbackLevel, uint8 callType) { appCallbackLevel = uint8(callInfo & CALL_INFO_APP_LEVEL_MASK); callType = uint8((callInfo & CALL_INFO_CALL_TYPE_MASK) >> CALL_INFO_CALL_TYPE_SHIFT); } function encodeCallInfo(uint8 appCallbackLevel, uint8 callType) internal pure returns (uint256 callInfo) { return uint256(appCallbackLevel) | (uint256(callType) << CALL_INFO_CALL_TYPE_SHIFT); } } /** * @title Flow Operator definitions library * @author Superfluid */ library FlowOperatorDefinitions { uint8 constant internal AUTHORIZE_FLOW_OPERATOR_CREATE = uint8(1) << 0; uint8 constant internal AUTHORIZE_FLOW_OPERATOR_UPDATE = uint8(1) << 1; uint8 constant internal AUTHORIZE_FLOW_OPERATOR_DELETE = uint8(1) << 2; uint8 constant internal AUTHORIZE_FULL_CONTROL = AUTHORIZE_FLOW_OPERATOR_CREATE | AUTHORIZE_FLOW_OPERATOR_UPDATE | AUTHORIZE_FLOW_OPERATOR_DELETE; uint8 constant internal REVOKE_FLOW_OPERATOR_CREATE = ~(uint8(1) << 0); uint8 constant internal REVOKE_FLOW_OPERATOR_UPDATE = ~(uint8(1) << 1); uint8 constant internal REVOKE_FLOW_OPERATOR_DELETE = ~(uint8(1) << 2); function isPermissionsClean(uint8 permissions) internal pure returns (bool) { return ( permissions & ~(AUTHORIZE_FLOW_OPERATOR_CREATE | AUTHORIZE_FLOW_OPERATOR_UPDATE | AUTHORIZE_FLOW_OPERATOR_DELETE) ) == uint8(0); } } /** * @title Batch operation library * @author Superfluid */ library BatchOperation { /** * @dev ERC20.approve batch operation type * * Call spec: * ISuperToken(target).operationApprove( * abi.decode(data, (address spender, uint256 amount)) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_APPROVE = 1; /** * @dev ERC20.transferFrom batch operation type * * Call spec: * ISuperToken(target).operationTransferFrom( * abi.decode(data, (address sender, address recipient, uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_TRANSFER_FROM = 2; /** * @dev ERC777.send batch operation type * * Call spec: * ISuperToken(target).operationSend( * abi.decode(data, (address recipient, uint256 amount, bytes userData) * ) */ uint32 constant internal OPERATION_TYPE_ERC777_SEND = 3; /** * @dev ERC20.increaseAllowance batch operation type * * Call spec: * ISuperToken(target).operationIncreaseAllowance( * abi.decode(data, (address account, address spender, uint256 addedValue)) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_INCREASE_ALLOWANCE = 4; /** * @dev ERC20.decreaseAllowance batch operation type * * Call spec: * ISuperToken(target).operationDecreaseAllowance( * abi.decode(data, (address account, address spender, uint256 subtractedValue)) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_DECREASE_ALLOWANCE = 5; /** * @dev SuperToken.upgrade batch operation type * * Call spec: * ISuperToken(target).operationUpgrade( * abi.decode(data, (uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_SUPERTOKEN_UPGRADE = 1 + 100; /** * @dev SuperToken.downgrade batch operation type * * Call spec: * ISuperToken(target).operationDowngrade( * abi.decode(data, (uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_SUPERTOKEN_DOWNGRADE = 2 + 100; /** * @dev SuperToken.upgradeTo batch operation type * * Call spec: * ISuperToken(target).operationUpgradeTo( * abi.decode(data, (address to, uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_SUPERTOKEN_UPGRADE_TO = 3 + 100; /** * @dev SuperToken.downgradeTo batch operation type * * Call spec: * ISuperToken(target).operationDowngradeTo( * abi.decode(data, (address to, uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_SUPERTOKEN_DOWNGRADE_TO = 4 + 100; /** * @dev Superfluid.callAgreement batch operation type * * Call spec: * callAgreement( * ISuperAgreement(target)), * abi.decode(data, (bytes callData, bytes userData) * ) */ uint32 constant internal OPERATION_TYPE_SUPERFLUID_CALL_AGREEMENT = 1 + 200; /** * @dev Superfluid.callAppAction batch operation type * * Call spec: * callAppAction( * ISuperApp(target)), * data * ) */ uint32 constant internal OPERATION_TYPE_SUPERFLUID_CALL_APP_ACTION = 2 + 200; /** * @dev DMZForwarder.forwardCall batch operation type * * Call spec: * forwardCall( * target, * data * ) */ uint32 constant internal OPERATION_TYPE_SIMPLE_FORWARD_CALL = 1 + 300; /** * @dev DMZForwarder.forward2771Call batch operation type * * Call spec: * forward2771Call( * target, * msgSender, * data * ) * * NOTE: In the context of this operation, the `DZMForwarder` contract acts as the * _trusted forwarder_ which must be trusted by the _recipient contract_ (operation target). * It shall do so by dynamically looking up the DMZForwarder used by the host, like this: * * function isTrustedForwarder(address forwarder) public view returns(bool) { * return forwarder == address(host.DMZ_FORWARDER()); * } * * If used in the context of a `forwardBatchCall`, we effectively have a chaining/nesting * of ERC-2771 calls where the host acts as _recipient contract_ of the enveloping 2771 call * and the DMZForwarder acts as the _trusted forwarder_ of the nested 2771 call(s). * That's why `msgSender` could be either the actual `msg.sender` (if using `batchCall`) * or the relayed sender address (if using `forwardBatchCall`). */ uint32 constant internal OPERATION_TYPE_ERC2771_FORWARD_CALL = 2 + 300; } /** * @title Superfluid governance configs library * @author Superfluid */ library SuperfluidGovernanceConfigs { bytes32 constant internal SUPERFLUID_REWARD_ADDRESS_CONFIG_KEY = keccak256("org.superfluid-finance.superfluid.rewardAddress"); bytes32 constant internal CFAV1_PPP_CONFIG_KEY = keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1.PPPConfiguration"); bytes32 constant internal SUPERTOKEN_MINIMUM_DEPOSIT_KEY = keccak256("org.superfluid-finance.superfluid.superTokenMinimumDeposit"); function getTrustedForwarderConfigKey(address forwarder) internal pure returns (bytes32) { return keccak256(abi.encode( "org.superfluid-finance.superfluid.trustedForwarder", forwarder)); } function getAppRegistrationConfigKey(address deployer, string memory registrationKey) internal pure returns (bytes32) { return keccak256(abi.encode( "org.superfluid-finance.superfluid.appWhiteListing.registrationKey", deployer, registrationKey)); } function getAppFactoryConfigKey(address factory) internal pure returns (bytes32) { return keccak256(abi.encode( "org.superfluid-finance.superfluid.appWhiteListing.factory", factory)); } function decodePPPConfig(uint256 pppConfig) internal pure returns (uint256 liquidationPeriod, uint256 patricianPeriod) { liquidationPeriod = (pppConfig >> 32) & type(uint32).max; patricianPeriod = pppConfig & type(uint32).max; } }
// SPDX-License-Identifier: AGPLv3 pragma solidity >=0.8.4; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { ISuperfluidToken } from "../../superfluid/ISuperfluidToken.sol"; /** * @dev The interface for any super token pool regardless of the distribution schemes. */ interface ISuperfluidPool is IERC20 { // Custom Errors error SUPERFLUID_POOL_INVALID_TIME(); // 0x83c35016 error SUPERFLUID_POOL_NO_POOL_MEMBERS(); // 0xe10f405a error SUPERFLUID_POOL_NO_ZERO_ADDRESS(); // 0x54eb6ee6 error SUPERFLUID_POOL_NOT_POOL_ADMIN_OR_GDA(); // 0x1c5fbdcb error SUPERFLUID_POOL_NOT_GDA(); // 0xfcbe3f9e error SUPERFLUID_POOL_TRANSFER_UNITS_NOT_ALLOWED(); // 0x2285efba error SUPERFLUID_POOL_SELF_TRANSFER_NOT_ALLOWED(); // 0xceddc0be // Events event MemberUnitsUpdated( ISuperfluidToken indexed token, address indexed member, uint128 oldUnits, uint128 newUnits ); event DistributionClaimed( ISuperfluidToken indexed token, address indexed member, int256 claimedAmount, int256 totalClaimed ); /// @notice A boolean indicating whether pool members can transfer their units function transferabilityForUnitsOwner() external view returns (bool); /// @notice A boolean indicating whether addresses other than the pool admin can distribute via the pool function distributionFromAnyAddress() external view returns (bool); /// @notice The pool admin /// @dev The admin is the creator of the pool and has permissions to update member units /// and is the recipient of the adjustment flow rate function admin() external view returns (address); /// @notice The SuperToken for the pool function superToken() external view returns (ISuperfluidToken); /// @notice The total units of the pool function getTotalUnits() external view returns (uint128); /// @notice The total number of units of connected members function getTotalConnectedUnits() external view returns (uint128); /// @notice The total number of units of disconnected members function getTotalDisconnectedUnits() external view returns (uint128); /// @notice The total number of units for `memberAddr` /// @param memberAddr The address of the member function getUnits(address memberAddr) external view returns (uint128); /// @notice The total flow rate of the pool function getTotalFlowRate() external view returns (int96); /// @notice The flow rate of the connected members function getTotalConnectedFlowRate() external view returns (int96); /// @notice The flow rate of the disconnected members function getTotalDisconnectedFlowRate() external view returns (int96); /// @notice The balance of all the disconnected members at `time` /// @param time The time to query function getDisconnectedBalance(uint32 time) external view returns (int256 balance); /// @notice The total amount received by `memberAddr` in the pool /// @param memberAddr The address of the member /// @return totalAmountReceived The total amount received by the member function getTotalAmountReceivedByMember(address memberAddr) external view returns (uint256 totalAmountReceived); /// @notice The flow rate a member is receiving from the pool /// @param memberAddr The address of the member function getMemberFlowRate(address memberAddr) external view returns (int96); /// @notice The claimable balance for `memberAddr` at `time` in the pool /// @param memberAddr The address of the member /// @param time The time to query function getClaimable(address memberAddr, uint32 time) external view returns (int256); /// @notice The claimable balance for `memberAddr` at `block.timestamp` in the pool /// @param memberAddr The address of the member function getClaimableNow(address memberAddr) external view returns (int256 claimableBalance, uint256 timestamp); /// @notice Sets `memberAddr` ownedUnits to `newUnits` /// @param memberAddr The address of the member /// @param newUnits The new units for the member function updateMemberUnits(address memberAddr, uint128 newUnits) external returns (bool); /// @notice Claims the claimable balance for `memberAddr` at `block.timestamp` /// @param memberAddr The address of the member function claimAll(address memberAddr) external returns (bool); /// @notice Claims the claimable balance for `msg.sender` at `block.timestamp` function claimAll() external returns (bool); /// @notice Increases the allowance of `spender` by `addedValue` /// @param spender The address of the spender /// @param addedValue The amount to increase the allowance by /// @return true if successful function increaseAllowance(address spender, uint256 addedValue) external returns (bool); /// @notice Decreases the allowance of `spender` by `subtractedValue` /// @param spender The address of the spender /// @param subtractedValue The amount to decrease the allowance by /// @return true if successful function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >=0.8.4; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; interface IPoolNFTBase is IERC721Metadata { error POOL_NFT_APPROVE_TO_CALLER(); // 0x9212b333 error POOL_NFT_ONLY_SUPER_TOKEN_FACTORY(); // 0x1fd7e3d8 error POOL_NFT_INVALID_TOKEN_ID(); // 0x09275994 error POOL_NFT_APPROVE_TO_CURRENT_OWNER(); // 0x020226d3 error POOL_NFT_APPROVE_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0x1e82f255 error POOL_NFT_NOT_REGISTERED_POOL(); // 0x6421912e error POOL_NFT_TRANSFER_NOT_ALLOWED(); // 0x432fb160 error POOL_NFT_TRANSFER_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0x4028ee0e /// @notice Informs third-party platforms that NFT metadata should be updated /// @dev This event comes from https://eips.ethereum.org/EIPS/eip-4906 /// @param tokenId the id of the token that should have its metadata updated event MetadataUpdate(uint256 tokenId); function initialize(string memory nftName, string memory nftSymbol) external; // initializer; function triggerMetadataUpdate(uint256 tokenId) external; /// @notice Gets the token id /// @dev For PoolAdminNFT, `account` is admin and for PoolMemberNFT, `account` is member function getTokenId(address pool, address account) external view returns (uint256 tokenId); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.11; import { IPoolNFTBase } from "./IPoolNFTBase.sol"; interface IPoolMemberNFT is IPoolNFTBase { // PoolMemberNFTData struct storage packing: // b = bits // WORD 1: | pool | FREE // | 160b | 96b // WORD 2: | member | FREE // | 160b | 96b // WORD 3: | units | FREE // | 128b | 128b struct PoolMemberNFTData { address pool; address member; uint128 units; } /// Errors /// error POOL_MEMBER_NFT_NO_ZERO_POOL(); error POOL_MEMBER_NFT_NO_ZERO_MEMBER(); error POOL_MEMBER_NFT_NO_UNITS(); error POOL_MEMBER_NFT_HAS_UNITS(); function onCreate(address pool, address member) external; function onUpdate(address pool, address member) external; function onDelete(address pool, address member) external; /// View Functions /// function poolMemberDataByTokenId(uint256 tokenId) external view returns (PoolMemberNFTData memory data); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.11; import { IPoolNFTBase } from "./IPoolNFTBase.sol"; interface IPoolAdminNFT is IPoolNFTBase { // PoolAdminNFTData struct storage packing: // b = bits // WORD 1: | pool | FREE // | 160b | 96b // WORD 2: | admin | FREE // | 160b | 96b struct PoolAdminNFTData { address pool; address admin; } /// Write Functions /// function mint(address pool) external; function poolAdminDataByTokenId(uint256 tokenId) external view returns (PoolAdminNFTData memory data); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >=0.8.4; import { ISuperAgreement } from "../../superfluid/ISuperAgreement.sol"; import { ISuperfluidToken } from "../../superfluid/ISuperfluidToken.sol"; import { ISuperfluidPool } from "../../agreements/gdav1/ISuperfluidPool.sol"; struct PoolConfig { /// @dev if true, the pool members can transfer their owned units /// else, only the pool admin can manipulate the units for pool members bool transferabilityForUnitsOwner; /// @dev if true, anyone can execute distributions via the pool /// else, only the pool admin can execute distributions via the pool bool distributionFromAnyAddress; } /** * @title General Distribution Agreement interface * @author Superfluid */ abstract contract IGeneralDistributionAgreementV1 is ISuperAgreement { // Custom Errors error GDA_DISTRIBUTE_FOR_OTHERS_NOT_ALLOWED(); // 0xf67d263e error GDA_DISTRIBUTE_FROM_ANY_ADDRESS_NOT_ALLOWED(); // 0x7761a5e5 error GDA_FLOW_DOES_NOT_EXIST(); // 0x29f4697e error GDA_NON_CRITICAL_SENDER(); // 0x666f381d error GDA_INSUFFICIENT_BALANCE(); // 0x33115c3f error GDA_NO_NEGATIVE_FLOW_RATE(); // 0x15f25663 error GDA_ADMIN_CANNOT_BE_POOL(); // 0x9ab88a26 error GDA_NOT_POOL_ADMIN(); // 0x3a87e565 error GDA_NO_ZERO_ADDRESS_ADMIN(); // 0x82c5d837 error GDA_ONLY_SUPER_TOKEN_POOL(); // 0x90028c37 // Events event InstantDistributionUpdated( ISuperfluidToken indexed token, ISuperfluidPool indexed pool, address indexed distributor, address operator, uint256 requestedAmount, uint256 actualAmount, bytes userData ); event FlowDistributionUpdated( ISuperfluidToken indexed token, ISuperfluidPool indexed pool, address indexed distributor, // operator's have permission to liquidate critical flows // on behalf of others address operator, int96 oldFlowRate, int96 newDistributorToPoolFlowRate, int96 newTotalDistributionFlowRate, address adjustmentFlowRecipient, int96 adjustmentFlowRate, bytes userData ); event PoolCreated(ISuperfluidToken indexed token, address indexed admin, ISuperfluidPool pool); event PoolConnectionUpdated( ISuperfluidToken indexed token, ISuperfluidPool indexed pool, address indexed account, bool connected, bytes userData ); event BufferAdjusted( ISuperfluidToken indexed token, ISuperfluidPool indexed pool, address indexed from, int256 bufferDelta, uint256 newBufferAmount, uint256 totalBufferAmount ); /// @dev ISuperAgreement.agreementType implementation function agreementType() external pure override returns (bytes32) { return keccak256("org.superfluid-finance.agreements.GeneralDistributionAgreement.v1"); } /// @dev Gets the GDA net flow rate of `account` for `token`. /// @param token The token address /// @param account The account address /// @return net flow rate function getNetFlow(ISuperfluidToken token, address account) external view virtual returns (int96); /// @notice Gets the GDA flow rate of `from` to `to` for `token`. /// @dev This is primarily used to get the flow distribution flow rate from a distributor to a pool or the /// adjustment flow rate of a pool. /// @param token The token address /// @param from The sender address /// @param to The receiver address (the pool) /// @return flow rate function getFlowRate(ISuperfluidToken token, address from, ISuperfluidPool to) external view virtual returns (int96); /// @dev Gets the GDA flow data between `from` and `to` of `token` /// @param token The token address /// @param from The sender address /// @param to The receiver address /// @return lastUpdated The timestamp of when the flow was last updated /// @return flowRate The flow rate /// @return deposit The amount of deposit the flow function getFlow(ISuperfluidToken token, address from, ISuperfluidPool to) external view virtual returns (uint256 lastUpdated, int96 flowRate, uint256 deposit); /// @dev Gets the aggregated GDA flow info of `account` for `token` /// @param token The token address /// @param account The account address /// @return timestamp The timestamp of when the flow was last updated for account /// @return flowRate The net flow rate of token for account /// @return deposit The sum of all deposits for account's flows function getAccountFlowInfo(ISuperfluidToken token, address account) external view virtual returns (uint256 timestamp, int96 flowRate, uint256 deposit); /// @notice Executes an optimistic estimation of what the actual flow distribution flow rate may be. /// The actual flow distribution flow rate is the flow rate that will be sent from `from`. /// NOTE: this is only precise in an atomic transaction. DO NOT rely on this if querying off-chain. /// @dev The difference between the requested flow rate and the actual flow rate is the adjustment flow rate, /// this adjustment flow rate goes to the pool admin. /// @param token The token address /// @param from The sender address /// @param to The pool address /// @param requestedFlowRate The requested flow rate /// @return actualFlowRate and totalDistributionFlowRate function estimateFlowDistributionActualFlowRate( ISuperfluidToken token, address from, ISuperfluidPool to, int96 requestedFlowRate ) external view virtual returns (int96 actualFlowRate, int96 totalDistributionFlowRate); /// @notice Executes an optimistic estimation of what the actual amount distributed may be. /// The actual amount distributed is the amount that will be sent from `from`. /// NOTE: this is only precise in an atomic transaction. DO NOT rely on this if querying off-chain. /// @dev The difference between the requested amount and the actual amount is the adjustment amount. /// @param token The token address /// @param from The sender address /// @param to The pool address /// @param requestedAmount The requested amount /// @return actualAmount function estimateDistributionActualAmount( ISuperfluidToken token, address from, ISuperfluidPool to, uint256 requestedAmount ) external view virtual returns (uint256 actualAmount); /// @notice Gets the adjustment flow rate of `pool` for `token`. /// @param pool The pool address /// @return adjustment flow rate function getPoolAdjustmentFlowRate(address pool) external view virtual returns (int96); //////////////////////////////////////////////////////////////////////////////// // Pool Operations //////////////////////////////////////////////////////////////////////////////// /// @notice Creates a new pool for `token` where the admin is `admin`. /// @param token The token address /// @param admin The admin of the pool /// @param poolConfig The pool configuration (see PoolConfig struct) function createPool(ISuperfluidToken token, address admin, PoolConfig memory poolConfig) external virtual returns (ISuperfluidPool pool); function updateMemberUnits(ISuperfluidPool pool, address memberAddress, uint128 newUnits, bytes calldata ctx) external virtual returns (bytes memory newCtx); function claimAll(ISuperfluidPool pool, address memberAddress, bytes calldata ctx) external virtual returns (bytes memory newCtx); /// @notice Connects `msg.sender` to `pool`. /// @dev This is used to connect a pool to the GDA. /// @param pool The pool address /// @param ctx Context bytes (see ISuperfluid.sol for Context struct) /// @return newCtx the new context bytes function connectPool(ISuperfluidPool pool, bytes calldata ctx) external virtual returns (bytes memory newCtx); /// @notice Disconnects `msg.sender` from `pool`. /// @dev This is used to disconnect a pool from the GDA. /// @param pool The pool address /// @param ctx Context bytes (see ISuperfluidPoolAdmin for Context struct) /// @return newCtx the new context bytes function disconnectPool(ISuperfluidPool pool, bytes calldata ctx) external virtual returns (bytes memory newCtx); /// @notice Checks whether `account` is a pool. /// @param token The token address /// @param account The account address /// @return true if `account` is a pool function isPool(ISuperfluidToken token, address account) external view virtual returns (bool); /// Check if an address is connected to the pool function isMemberConnected(ISuperfluidPool pool, address memberAddr) external view virtual returns (bool); /// Get pool adjustment flow information: (recipient, flowHash, flowRate) function getPoolAdjustmentFlowInfo(ISuperfluidPool pool) external view virtual returns (address, bytes32, int96); //////////////////////////////////////////////////////////////////////////////// // Agreement Operations //////////////////////////////////////////////////////////////////////////////// /// @notice Tries to distribute `requestedAmount` of `token` from `from` to `pool`. /// @dev NOTE: The actual amount distributed may differ. /// @param token The token address /// @param from The sender address /// @param pool The pool address /// @param requestedAmount The requested amount /// @param ctx Context bytes (see ISuperfluidPool for Context struct) /// @return newCtx the new context bytes function distribute( ISuperfluidToken token, address from, ISuperfluidPool pool, uint256 requestedAmount, bytes calldata ctx ) external virtual returns (bytes memory newCtx); /// @notice Tries to distributeFlow `requestedFlowRate` of `token` from `from` to `pool`. /// @dev NOTE: The actual distribution flow rate may differ. /// @param token The token address /// @param from The sender address /// @param pool The pool address /// @param requestedFlowRate The requested flow rate /// @param ctx Context bytes (see ISuperfluidPool for Context struct) /// @return newCtx the new context bytes function distributeFlow( ISuperfluidToken token, address from, ISuperfluidPool pool, int96 requestedFlowRate, bytes calldata ctx ) external virtual returns (bytes memory newCtx); //////////////////////////////////////////////////////////////////////////////// // Solvency Functions //////////////////////////////////////////////////////////////////////////////// /** * @dev Returns whether it is the patrician period based on host.getNow() * @param account The account we are interested in * @return isCurrentlyPatricianPeriod Whether it is currently the patrician period dictated by governance * @return timestamp The value of host.getNow() */ function isPatricianPeriodNow(ISuperfluidToken token, address account) external view virtual returns (bool isCurrentlyPatricianPeriod, uint256 timestamp); /** * @dev Returns whether it is the patrician period based on timestamp * @param account The account we are interested in * @param timestamp The timestamp we are interested in observing the result of isPatricianPeriod * @return bool Whether it is currently the patrician period dictated by governance */ function isPatricianPeriod(ISuperfluidToken token, address account, uint256 timestamp) public view virtual returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol"; import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol"; /** * @title Instant Distribution Agreement interface * @author Superfluid * * @notice * - A publisher can create as many as indices as possibly identifiable with `indexId`. * - `indexId` is deliberately limited to 32 bits, to avoid the chance for sha-3 collision. * Despite knowing sha-3 collision is only theoretical. * - A publisher can create a subscription to an index for any subscriber. * - A subscription consists of: * - The index it subscribes to. * - Number of units subscribed. * - An index consists of: * - Current value as `uint128 indexValue`. * - Total units of the approved subscriptions as `uint128 totalUnitsApproved`. * - Total units of the non approved subscription as `uint128 totalUnitsPending`. * - A publisher can update an index with a new value that doesn't decrease. * - A publisher can update a subscription with any number of units. * - A publisher or a subscriber can delete a subscription and reset its units to zero. * - A subscriber must approve the index in order to receive distributions from the publisher * each time the index is updated. * - The amount distributed is $$\Delta{index} * units$$ * - Distributions to a non approved subscription stays in the publisher's deposit until: * - the subscriber approves the subscription (side effect), * - the publisher updates the subscription (side effect), * - the subscriber deletes the subscription even if it is never approved (side effect), * - or the subscriber can explicitly claim them. */ abstract contract IInstantDistributionAgreementV1 is ISuperAgreement { /************************************************************************** * Errors *************************************************************************/ error IDA_INDEX_SHOULD_GROW(); // 0xcfdca725 error IDA_OPERATION_NOT_ALLOWED(); // 0x92da6d17 error IDA_INDEX_ALREADY_EXISTS(); // 0x5c02a517 error IDA_INDEX_DOES_NOT_EXIST(); // 0xedeaa63b error IDA_SUBSCRIPTION_DOES_NOT_EXIST(); // 0xb6c8c980 error IDA_SUBSCRIPTION_ALREADY_APPROVED(); // 0x3eb2f849 error IDA_SUBSCRIPTION_IS_NOT_APPROVED(); // 0x37412573 error IDA_INSUFFICIENT_BALANCE(); // 0x16e759bb error IDA_ZERO_ADDRESS_SUBSCRIBER(); // 0xc90a4674 /// @dev ISuperAgreement.agreementType implementation function agreementType() external override pure returns (bytes32) { return keccak256("org.superfluid-finance.agreements.InstantDistributionAgreement.v1"); } /************************************************************************** * Index operations *************************************************************************/ /** * @dev Create a new index for the publisher * @param token Super token address * @param indexId Id of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * None */ function createIndex( ISuperfluidToken token, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index created event * @param token Super token address * @param publisher Index creator and publisher * @param indexId The specified indexId of the newly created index * @param userData The user provided data */ event IndexCreated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, bytes userData); /** * @dev Query the data of a index * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @return exist Does the index exist * @return indexValue Value of the current index * @return totalUnitsApproved Total units approved for the index * @return totalUnitsPending Total units pending approval for the index */ function getIndex( ISuperfluidToken token, address publisher, uint32 indexId) external view virtual returns( bool exist, uint128 indexValue, uint128 totalUnitsApproved, uint128 totalUnitsPending); /** * @dev Calculate actual distribution amount * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param amount The amount of tokens desired to be distributed * @return actualAmount The amount to be distributed after ensuring no rounding errors * @return newIndexValue The index value given the desired amount of tokens to be distributed */ function calculateDistribution( ISuperfluidToken token, address publisher, uint32 indexId, uint256 amount) external view virtual returns( uint256 actualAmount, uint128 newIndexValue); /** * @dev Update index value of an index * @param token Super token address * @param indexId Id of the index * @param indexValue Value of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * None */ function updateIndex( ISuperfluidToken token, uint32 indexId, uint128 indexValue, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index updated event * @param token Super token address * @param publisher Index updater and publisher * @param indexId The specified indexId of the updated index * @param oldIndexValue The previous index value * @param newIndexValue The updated index value * @param totalUnitsPending The total units pending when the indexValue was updated * @param totalUnitsApproved The total units approved when the indexValue was updated * @param userData The user provided data */ event IndexUpdated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, uint128 oldIndexValue, uint128 newIndexValue, uint128 totalUnitsPending, uint128 totalUnitsApproved, bytes userData); /** * @dev Distribute tokens through the index * @param token Super token address * @param indexId Id of the index * @param amount The amount of tokens desired to be distributed * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:note * - This is a convenient version of updateIndex. It adds to the index * a delta that equals to `amount / totalUnits` * - The actual amount distributed could be obtained via * `calculateDistribution`. This is due to precision error with index * value and units data range * * @custom:callbacks * None */ function distribute( ISuperfluidToken token, uint32 indexId, uint256 amount, bytes calldata ctx) external virtual returns(bytes memory newCtx); /************************************************************************** * Subscription operations *************************************************************************/ /** * @dev Approve the subscription of an index * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - if subscription exist * - AgreementCreated callback to the publisher: * - agreementId is for the subscription * - if subscription does not exist * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function approveSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index subscribed event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The approved subscriber * @param userData The user provided data */ event IndexSubscribed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, bytes userData); /** * @dev Subscription approved event * @param token Super token address * @param subscriber The approved subscriber * @param publisher Index publisher * @param indexId The specified indexId * @param userData The user provided data */ event SubscriptionApproved( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, bytes userData); /** * @notice Revoke the subscription of an index * @dev "Unapproves" the subscription and moves approved units to pending * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function revokeSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index unsubscribed event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The unsubscribed subscriber * @param userData The user provided data */ event IndexUnsubscribed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, bytes userData); /** * @dev Subscription approved event * @param token Super token address * @param subscriber The approved subscriber * @param publisher Index publisher * @param indexId The specified indexId * @param userData The user provided data */ event SubscriptionRevoked( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, bytes userData); /** * @dev Update the nuber of units of a subscription * @param token Super token address * @param indexId Id of the index * @param subscriber The subscriber of the index * @param units Number of units of the subscription * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - if subscription exist * - AgreementCreated callback to the subscriber: * - agreementId is for the subscription * - if subscription does not exist * - AgreementUpdated callback to the subscriber: * - agreementId is for the subscription */ function updateSubscription( ISuperfluidToken token, uint32 indexId, address subscriber, uint128 units, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index units updated event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The subscriber units updated * @param units The new units amount * @param userData The user provided data */ event IndexUnitsUpdated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, uint128 units, bytes userData); /** * @dev Subscription units updated event * @param token Super token address * @param subscriber The subscriber units updated * @param indexId The specified indexId * @param publisher Index publisher * @param units The new units amount * @param userData The user provided data */ event SubscriptionUnitsUpdated( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, uint128 units, bytes userData); /** * @dev Get data of a subscription * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param subscriber The subscriber of the index * @return exist Does the subscription exist? * @return approved Is the subscription approved? * @return units Units of the suscription * @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription */ function getSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber) external view virtual returns( bool exist, bool approved, uint128 units, uint256 pendingDistribution ); /** * @notice Get data of a subscription by agreement ID * @dev indexId (agreementId) is the keccak256 hash of encodePacked("publisher", publisher, indexId) * @param token Super token address * @param agreementId The agreement ID * @return publisher The publisher of the index * @return indexId Id of the index * @return approved Is the subscription approved? * @return units Units of the suscription * @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription */ function getSubscriptionByID( ISuperfluidToken token, bytes32 agreementId) external view virtual returns( address publisher, uint32 indexId, bool approved, uint128 units, uint256 pendingDistribution ); /** * @dev List subscriptions of an user * @param token Super token address * @param subscriber The subscriber's address * @return publishers Publishers of the subcriptions * @return indexIds Indexes of the subscriptions * @return unitsList Units of the subscriptions */ function listSubscriptions( ISuperfluidToken token, address subscriber) external view virtual returns( address[] memory publishers, uint32[] memory indexIds, uint128[] memory unitsList); /** * @dev Delete the subscription of an user * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param subscriber The subscriber's address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - if the subscriber called it * - AgreementTerminated callback to the publsiher: * - agreementId is for the subscription * - if the publisher called it * - AgreementTerminated callback to the subscriber: * - agreementId is for the subscription */ function deleteSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Claim pending distributions * @param token Super token address * @param publisher The publisher of the index * @param indexId Id of the index * @param subscriber The subscriber's address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:note The subscription should not be approved yet * * @custom:callbacks * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function claim( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Index distribution claimed event * @param token Super token address * @param publisher Index publisher * @param indexId The specified indexId * @param subscriber The subscriber units updated * @param amount The pending amount claimed */ event IndexDistributionClaimed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, uint256 amount); /** * @dev Subscription distribution claimed event * @param token Super token address * @param subscriber The subscriber units updated * @param publisher Index publisher * @param indexId The specified indexId * @param amount The pending amount claimed */ event SubscriptionDistributionClaimed( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, uint256 amount); }
// SPDX-License-Identifier: MIT pragma solidity >= 0.8.11; import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol"; import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol"; /** * @title Constant Flow Agreement interface * @author Superfluid */ abstract contract IConstantFlowAgreementV1 is ISuperAgreement { /************************************************************************** * Errors *************************************************************************/ error CFA_ACL_NO_SENDER_CREATE(); // 0x4b993136 error CFA_ACL_NO_SENDER_UPDATE(); // 0xedfa0d3b error CFA_ACL_OPERATOR_NO_CREATE_PERMISSIONS(); // 0xa3eab6ac error CFA_ACL_OPERATOR_NO_UPDATE_PERMISSIONS(); // 0xac434b5f error CFA_ACL_OPERATOR_NO_DELETE_PERMISSIONS(); // 0xe30f1bff error CFA_ACL_FLOW_RATE_ALLOWANCE_EXCEEDED(); // 0xa0645c1f error CFA_ACL_UNCLEAN_PERMISSIONS(); // 0x7939d66c error CFA_ACL_NO_SENDER_FLOW_OPERATOR(); // 0xb0ed394d error CFA_ACL_NO_NEGATIVE_ALLOWANCE(); // 0x86e0377d error CFA_FLOW_ALREADY_EXISTS(); // 0x801b6863 error CFA_FLOW_DOES_NOT_EXIST(); // 0x5a32bf24 error CFA_INSUFFICIENT_BALANCE(); // 0xea76c9b3 error CFA_ZERO_ADDRESS_SENDER(); // 0x1ce9b067 error CFA_ZERO_ADDRESS_RECEIVER(); // 0x78e02b2a error CFA_HOOK_OUT_OF_GAS(); // 0x9f76430b error CFA_DEPOSIT_TOO_BIG(); // 0x752c2b9c error CFA_FLOW_RATE_TOO_BIG(); // 0x0c9c55c1 error CFA_NON_CRITICAL_SENDER(); // 0xce11b5d1 error CFA_INVALID_FLOW_RATE(); // 0x91acad16 error CFA_NO_SELF_FLOW(); // 0xa47338ef /// @dev ISuperAgreement.agreementType implementation function agreementType() external override pure returns (bytes32) { return keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1"); } /** * @notice Get the maximum flow rate allowed with the deposit * @dev The deposit is clipped and rounded down * @param deposit Deposit amount used for creating the flow * @return flowRate The maximum flow rate */ function getMaximumFlowRateFromDeposit( ISuperfluidToken token, uint256 deposit) external view virtual returns (int96 flowRate); /** * @notice Get the deposit required for creating the flow * @dev Calculates the deposit based on the liquidationPeriod and flowRate * @param flowRate Flow rate to be tested * @return deposit The deposit amount based on flowRate and liquidationPeriod * @custom:note * - if calculated deposit (flowRate * liquidationPeriod) is less * than the minimum deposit, we use the minimum deposit otherwise * we use the calculated deposit */ function getDepositRequiredForFlowRate( ISuperfluidToken token, int96 flowRate) external view virtual returns (uint256 deposit); /** * @dev Returns whether it is the patrician period based on host.getNow() * @param account The account we are interested in * @return isCurrentlyPatricianPeriod Whether it is currently the patrician period dictated by governance * @return timestamp The value of host.getNow() */ function isPatricianPeriodNow( ISuperfluidToken token, address account) external view virtual returns (bool isCurrentlyPatricianPeriod, uint256 timestamp); /** * @dev Returns whether it is the patrician period based on timestamp * @param account The account we are interested in * @param timestamp The timestamp we are interested in observing the result of isPatricianPeriod * @return bool Whether it is currently the patrician period dictated by governance */ function isPatricianPeriod( ISuperfluidToken token, address account, uint256 timestamp ) public view virtual returns (bool); /** * @dev msgSender from `ctx` updates permissions for the `flowOperator` with `flowRateAllowance` * @param token Super token address * @param flowOperator The permission grantee address * @param permissions A bitmask representation of the granted permissions * @param flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function updateFlowOperatorPermissions( ISuperfluidToken token, address flowOperator, uint8 permissions, int96 flowRateAllowance, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice msgSender from `ctx` increases flow rate allowance for the `flowOperator` by `addedFlowRateAllowance` * @dev if `addedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE * @param token Super token address * @param flowOperator The permission grantee address * @param addedFlowRateAllowance The flow rate allowance delta * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * @return newCtx The new context bytes */ function increaseFlowRateAllowance( ISuperfluidToken token, address flowOperator, int96 addedFlowRateAllowance, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev msgSender from `ctx` decreases flow rate allowance for the `flowOperator` by `subtractedFlowRateAllowance` * @dev if `subtractedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE * @param token Super token address * @param flowOperator The permission grantee address * @param subtractedFlowRateAllowance The flow rate allowance delta * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * @return newCtx The new context bytes */ function decreaseFlowRateAllowance( ISuperfluidToken token, address flowOperator, int96 subtractedFlowRateAllowance, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev msgSender from `ctx` increases flow rate allowance for the `flowOperator` by `addedFlowRateAllowance` * @dev if `addedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE * @param token Super token address * @param flowOperator The permission grantee address * @param permissionsToAdd A bitmask representation of the granted permissions to add as a delta * @param addedFlowRateAllowance The flow rate allowance delta * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * @return newCtx The new context bytes */ function increaseFlowRateAllowanceWithPermissions( ISuperfluidToken token, address flowOperator, uint8 permissionsToAdd, int96 addedFlowRateAllowance, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev msgSender from `ctx` decreases flow rate allowance for the `flowOperator` by `subtractedFlowRateAllowance` * @dev if `subtractedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE * @param token Super token address * @param flowOperator The permission grantee address * @param permissionsToRemove A bitmask representation of the granted permissions to remove as a delta * @param subtractedFlowRateAllowance The flow rate allowance delta * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * @return newCtx The new context bytes */ function decreaseFlowRateAllowanceWithPermissions( ISuperfluidToken token, address flowOperator, uint8 permissionsToRemove, int96 subtractedFlowRateAllowance, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev msgSender from `ctx` grants `flowOperator` all permissions with flowRateAllowance as type(int96).max * @param token Super token address * @param flowOperator The permission grantee address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function authorizeFlowOperatorWithFullControl( ISuperfluidToken token, address flowOperator, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice msgSender from `ctx` revokes `flowOperator` create/update/delete permissions * @dev `permissions` and `flowRateAllowance` will both be set to 0 * @param token Super token address * @param flowOperator The permission grantee address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function revokeFlowOperatorWithFullControl( ISuperfluidToken token, address flowOperator, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Get the permissions of a flow operator between `sender` and `flowOperator` for `token` * @param token Super token address * @param sender The permission granter address * @param flowOperator The permission grantee address * @return flowOperatorId The keccak256 hash of encoded string "flowOperator", sender and flowOperator * @return permissions A bitmask representation of the granted permissions * @return flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) */ function getFlowOperatorData( ISuperfluidToken token, address sender, address flowOperator ) public view virtual returns ( bytes32 flowOperatorId, uint8 permissions, int96 flowRateAllowance ); /** * @notice Get flow operator using flowOperatorId * @param token Super token address * @param flowOperatorId The keccak256 hash of encoded string "flowOperator", sender and flowOperator * @return permissions A bitmask representation of the granted permissions * @return flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) */ function getFlowOperatorDataByID( ISuperfluidToken token, bytes32 flowOperatorId ) external view virtual returns ( uint8 permissions, int96 flowRateAllowance ); /** * @notice Create a flow betwen ctx.msgSender and receiver * @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver * @param token Super token address * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - AgreementCreated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * @custom:note * - A deposit is taken as safety margin for the solvency agents * - A extra gas fee may be taken to pay for solvency agent liquidations */ function createFlow( ISuperfluidToken token, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Create a flow between sender and receiver * @dev A flow created by an approved flow operator (see above for details on callbacks) * @param token Super token address * @param sender Flow sender address (has granted permissions) * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function createFlowByOperator( ISuperfluidToken token, address sender, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Update the flow rate between ctx.msgSender and receiver * @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver * @param token Super token address * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - AgreementUpdated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * @custom:note * - Only the flow sender may update the flow rate * - Even if the flow rate is zero, the flow is not deleted * from the system * - Deposit amount will be adjusted accordingly * - No new gas fee is charged */ function updateFlow( ISuperfluidToken token, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Update a flow between sender and receiver * @dev A flow updated by an approved flow operator (see above for details on callbacks) * @param token Super token address * @param sender Flow sender address (has granted permissions) * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function updateFlowByOperator( ISuperfluidToken token, address sender, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev Get the flow data between `sender` and `receiver` of `token` * @param token Super token address * @param sender Flow sender * @param receiver Flow receiver * @return timestamp Timestamp of when the flow is updated * @return flowRate The flow rate * @return deposit The amount of deposit the flow * @return owedDeposit The amount of owed deposit of the flow */ function getFlow( ISuperfluidToken token, address sender, address receiver ) external view virtual returns ( uint256 timestamp, int96 flowRate, uint256 deposit, uint256 owedDeposit ); /** * @notice Get flow data using agreementId * @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver * @param token Super token address * @param agreementId The agreement ID * @return timestamp Timestamp of when the flow is updated * @return flowRate The flow rate * @return deposit The deposit amount of the flow * @return owedDeposit The owed deposit amount of the flow */ function getFlowByID( ISuperfluidToken token, bytes32 agreementId ) external view virtual returns ( uint256 timestamp, int96 flowRate, uint256 deposit, uint256 owedDeposit ); /** * @dev Get the aggregated flow info of the account * @param token Super token address * @param account Account for the query * @return timestamp Timestamp of when a flow was last updated for account * @return flowRate The net flow rate of token for account * @return deposit The sum of all deposits for account's flows * @return owedDeposit The sum of all owed deposits for account's flows */ function getAccountFlowInfo( ISuperfluidToken token, address account ) external view virtual returns ( uint256 timestamp, int96 flowRate, uint256 deposit, uint256 owedDeposit); /** * @dev Get the net flow rate of the account * @param token Super token address * @param account Account for the query * @return flowRate Net flow rate */ function getNetFlow( ISuperfluidToken token, address account ) external view virtual returns (int96 flowRate); /** * @notice Delete the flow between sender and receiver * @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver * @param token Super token address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * @param receiver Flow receiver address * * @custom:callbacks * - AgreementTerminated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * @custom:note * - Both flow sender and receiver may delete the flow * - If Sender account is insolvent or in critical state, a solvency agent may * also terminate the agreement * - Gas fee may be returned to the sender */ function deleteFlow( ISuperfluidToken token, address sender, address receiver, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Delete the flow between sender and receiver * @dev A flow deleted by an approved flow operator (see above for details on callbacks) * @param token Super token address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * @param receiver Flow receiver address */ function deleteFlowByOperator( ISuperfluidToken token, address sender, address receiver, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev Flow operator updated event * @param token Super token address * @param sender Flow sender address * @param flowOperator Flow operator address * @param permissions Octo bitmask representation of permissions * @param flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) */ event FlowOperatorUpdated( ISuperfluidToken indexed token, address indexed sender, address indexed flowOperator, uint8 permissions, int96 flowRateAllowance ); /** * @dev Flow updated event * @param token Super token address * @param sender Flow sender address * @param receiver Flow recipient address * @param flowRate Flow rate in amount per second for this flow * @param totalSenderFlowRate Total flow rate in amount per second for the sender * @param totalReceiverFlowRate Total flow rate in amount per second for the receiver * @param userData The user provided data * */ event FlowUpdated( ISuperfluidToken indexed token, address indexed sender, address indexed receiver, int96 flowRate, int256 totalSenderFlowRate, int256 totalReceiverFlowRate, bytes userData ); /** * @dev Flow updated extension event * @param flowOperator Flow operator address - the Context.msgSender * @param deposit The deposit amount for the stream */ event FlowUpdatedExtension( address indexed flowOperator, uint256 deposit ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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) { return a + b; } /** * @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) { 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) { return a * b; } /** * @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. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @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) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message 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, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * 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, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/IERC1820Registry.sol) pragma solidity ^0.8.0; /** * @dev Interface of the global ERC1820 Registry, as defined in the * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register * implementers for interfaces in this registry, as well as query support. * * Implementers may be shared by multiple accounts, and can also implement more * than a single interface for each account. Contracts can implement interfaces * for themselves, but externally-owned accounts (EOA) must delegate this to a * contract. * * {IERC165} interfaces can also be queried via the registry. * * For an in-depth explanation and source code analysis, see the EIP text. */ interface IERC1820Registry { event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer); event ManagerChanged(address indexed account, address indexed newManager); /** * @dev Sets `newManager` as the manager for `account`. A manager of an * account is able to set interface implementers for it. * * By default, each account is its own manager. Passing a value of `0x0` in * `newManager` will reset the manager to this initial state. * * Emits a {ManagerChanged} event. * * Requirements: * * - the caller must be the current manager for `account`. */ function setManager(address account, address newManager) external; /** * @dev Returns the manager for `account`. * * See {setManager}. */ function getManager(address account) external view returns (address); /** * @dev Sets the `implementer` contract as ``account``'s implementer for * `interfaceHash`. * * `account` being the zero address is an alias for the caller's address. * The zero address can also be used in `implementer` to remove an old one. * * See {interfaceHash} to learn how these are created. * * Emits an {InterfaceImplementerSet} event. * * Requirements: * * - the caller must be the current manager for `account`. * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not * end in 28 zeroes). * - `implementer` must implement {IERC1820Implementer} and return true when * queried for support, unless `implementer` is the caller. See * {IERC1820Implementer-canImplementInterfaceForAddress}. */ function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external; /** * @dev Returns the implementer of `interfaceHash` for `account`. If no such * implementer is registered, returns the zero address. * * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28 * zeroes), `account` will be queried for support of it. * * `account` being the zero address is an alias for the caller's address. */ function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address); /** * @dev Returns the interface hash for an `interfaceName`, as defined in the * corresponding * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP]. */ function interfaceHash(string calldata interfaceName) external pure returns (bytes32); /** * @notice Updates the cache with whether the contract implements an ERC165 interface or not. * @param account Address of the contract for which to update the cache. * @param interfaceId ERC165 interface for which to update the cache. */ function updateERC165Cache(address account, bytes4 interfaceId) external; /** * @notice Checks whether a contract implements an ERC165 interface or not. * If the result is not cached a direct lookup on the contract address is performed. * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling * {updateERC165Cache} with the contract address. * @param account Address of the contract to check. * @param interfaceId ERC165 interface to check. * @return True if `account` implements `interfaceId`, false otherwise. */ function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool); /** * @notice Checks whether a contract implements an ERC165 interface or not without using or updating the cache. * @param account Address of the contract to check. * @param interfaceId ERC165 interface to check. * @return True if `account` implements `interfaceId`, false otherwise. */ function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Sender.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777TokensSender standard as defined in the EIP. * * {IERC777} Token holders can be notified of operations performed on their * tokens by having a contract implement this interface (contract holders can be * their own implementer) and registering it on the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry]. * * See {IERC1820Registry} and {ERC1820Implementer}. */ interface IERC777Sender { /** * @dev Called by an {IERC777} token contract whenever a registered holder's * (`from`) tokens are about to be moved or destroyed. The type of operation * is conveyed by `to` being the zero address or not. * * This call occurs _before_ the token contract's state is updated, so * {IERC777-balanceOf}, etc., can be used to query the pre-operation state. * * This function may revert to prevent the operation from being executed. */ function tokensToSend( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP. * * Accounts can be notified of {IERC777} tokens being sent to them by having a * contract implement this interface (contract holders can be their own * implementer) and registering it on the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry]. * * See {IERC1820Registry} and {ERC1820Implementer}. */ interface IERC777Recipient { /** * @dev Called by an {IERC777} token contract whenever tokens are being * moved or created into a registered account (`to`). The type of operation * is conveyed by `from` being the zero address or not. * * This call occurs _after_ the token contract's state is updated, so * {IERC777-balanceOf}, etc., can be used to query the post-operation state. * * This function may revert to prevent the operation from being executed. */ function tokensReceived( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC777/IERC777.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777Token standard as defined in the EIP. * * This contract uses the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let * token holders and recipients react to token movements by using setting implementers * for the associated interfaces in said registry. See {IERC1820Registry} and * {ERC1820Implementer}. */ interface IERC777 { /** * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`. * * Note that some additional user `data` and `operatorData` can be logged in the event. */ event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); /** * @dev Emitted when `operator` destroys `amount` tokens from `account`. * * Note that some additional user `data` and `operatorData` can be logged in the event. */ event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); /** * @dev Emitted when `operator` is made operator for `tokenHolder`. */ event AuthorizedOperator(address indexed operator, address indexed tokenHolder); /** * @dev Emitted when `operator` is revoked its operator status for `tokenHolder`. */ event RevokedOperator(address indexed operator, address indexed tokenHolder); /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * For most token contracts, this value will equal 1. */ function granularity() external view returns (uint256); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address owner) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send(address recipient, uint256 amount, bytes calldata data) external; /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply. * * If a send hook is registered for the caller, the corresponding function * will be called with `data` and empty `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata data) external; /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * Emits an {AuthorizedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external; /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * Emits a {RevokedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function revokeOperator(address operator) external; /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `data` and `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external; event Sent( address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ISuperfluid","name":"host","type":"address"},{"internalType":"contract IConstantOutflowNFT","name":"constantOutflowNFT","type":"address"},{"internalType":"contract IConstantInflowNFT","name":"constantInflowNFT","type":"address"},{"internalType":"contract IPoolAdminNFT","name":"poolAdminNFT","type":"address"},{"internalType":"contract IPoolMemberNFT","name":"poolMemberNFT","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"SF_TOKEN_AGREEMENT_ALREADY_EXISTS","type":"error"},{"inputs":[],"name":"SF_TOKEN_AGREEMENT_DOES_NOT_EXIST","type":"error"},{"inputs":[],"name":"SF_TOKEN_BURN_INSUFFICIENT_BALANCE","type":"error"},{"inputs":[],"name":"SF_TOKEN_MOVE_INSUFFICIENT_BALANCE","type":"error"},{"inputs":[],"name":"SF_TOKEN_ONLY_HOST","type":"error"},{"inputs":[],"name":"SF_TOKEN_ONLY_LISTED_AGREEMENT","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_APPROVE_FROM_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_APPROVE_TO_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_INFLATIONARY_DEFLATIONARY_NOT_SUPPORTED","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_MINT_TO_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_NFT_PROXY_ADDRESS_CHANGED","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_NOT_ERC777_TOKENS_RECIPIENT","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_NO_UNDERLYING_TOKEN","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_ONLY_ADMIN","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_ONLY_GOV_OWNER","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_ONLY_SELF","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"SUPER_TOKEN_TRANSFER_TO_ZERO_ADDRESS","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agreementClass","type":"address"},{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"bytes32[]","name":"data","type":"bytes32[]"}],"name":"AgreementCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agreementClass","type":"address"},{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"penaltyAccount","type":"address"},{"indexed":true,"internalType":"address","name":"rewardAccount","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"AgreementLiquidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"liquidatorAccount","type":"address"},{"indexed":true,"internalType":"address","name":"agreementClass","type":"address"},{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"penaltyAccount","type":"address"},{"indexed":true,"internalType":"address","name":"bondAccount","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bailoutAmount","type":"uint256"}],"name":"AgreementLiquidatedBy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agreementClass","type":"address"},{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"liquidatorAccount","type":"address"},{"indexed":true,"internalType":"address","name":"targetAccount","type":"address"},{"indexed":false,"internalType":"address","name":"rewardAmountReceiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"indexed":false,"internalType":"int256","name":"targetAccountBalanceDelta","type":"int256"},{"indexed":false,"internalType":"bytes","name":"liquidationTypeData","type":"bytes"}],"name":"AgreementLiquidatedV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agreementClass","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"slotId","type":"uint256"}],"name":"AgreementStateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agreementClass","type":"address"},{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"AgreementTerminated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"agreementClass","type":"address"},{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"bytes32[]","name":"data","type":"bytes32[]"}],"name":"AgreementUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"AuthorizedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bailoutAccount","type":"address"},{"indexed":false,"internalType":"uint256","name":"bailoutAmount","type":"uint256"}],"name":"Bailout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"uuid","type":"bytes32"},{"indexed":false,"internalType":"address","name":"codeAddress","type":"address"}],"name":"CodeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IConstantInflowNFT","name":"constantInflowNFT","type":"address"}],"name":"ConstantInflowNFTCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IConstantOutflowNFT","name":"constantOutflowNFT","type":"address"}],"name":"ConstantOutflowNFTCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPoolAdminNFT","name":"poolAdminNFT","type":"address"}],"name":"PoolAdminNFTCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPoolMemberNFT","name":"poolMemberNFT","type":"address"}],"name":"PoolMemberNFTCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenHolder","type":"address"}],"name":"RevokedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"Sent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenDowngraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CONSTANT_INFLOW_NFT","outputs":[{"internalType":"contract IConstantInflowNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONSTANT_OUTFLOW_NFT","outputs":[{"internalType":"contract IConstantOutflowNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_ADMIN_NFT","outputs":[{"internalType":"contract IPoolAdminNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_MEMBER_NFT","outputs":[{"internalType":"contract IPoolMemberNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"authorizeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"castrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes32[]","name":"data","type":"bytes32[]"}],"name":"createAgreement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"downgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"downgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAccountActiveAgreements","outputs":[{"internalType":"contract ISuperAgreement[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agreementClass","type":"address"},{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"dataLength","type":"uint256"}],"name":"getAgreementData","outputs":[{"internalType":"bytes32[]","name":"data","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"agreementClass","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"slotId","type":"uint256"},{"internalType":"uint256","name":"dataLength","type":"uint256"}],"name":"getAgreementStateSlot","outputs":[{"internalType":"bytes32[]","name":"slotData","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCodeAddress","outputs":[{"internalType":"address","name":"codeAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHost","outputs":[{"internalType":"address","name":"host","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnderlyingDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnderlyingToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"granularity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"underlyingToken","type":"address"},{"internalType":"uint8","name":"underlyingDecimals","type":"uint8"},{"internalType":"string","name":"n","type":"string"},{"internalType":"string","name":"s","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"underlyingToken","type":"address"},{"internalType":"uint8","name":"underlyingDecimals","type":"uint8"},{"internalType":"string","name":"n","type":"string"},{"internalType":"string","name":"s","type":"string"},{"internalType":"address","name":"admin","type":"address"}],"name":"initializeWithAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"isAccountCritical","outputs":[{"internalType":"bool","name":"isCritical","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAccountCriticalNow","outputs":[{"internalType":"bool","name":"isCritical","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"isAccountSolvent","outputs":[{"internalType":"bool","name":"isSolvent","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAccountSolventNow","outputs":[{"internalType":"bool","name":"isSolvent","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"tokenHolder","type":"address"}],"name":"isOperatorFor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes","name":"liquidationTypeData","type":"bytes"},{"internalType":"address","name":"liquidatorAccount","type":"address"},{"internalType":"bool","name":"useDefaultRewardAccount","type":"bool"},{"internalType":"address","name":"targetAccount","type":"address"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"int256","name":"targetAccountBalanceDelta","type":"int256"}],"name":"makeLiquidationPayoutsV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"operationApprove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"operationDecreaseAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"operationDowngrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"operationDowngradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"operationIncreaseAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"operationSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"operationTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"operationUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"operationUpgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"operatorBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"operatorData","type":"bytes"}],"name":"operatorSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"realtimeBalanceOf","outputs":[{"internalType":"int256","name":"availableBalance","type":"int256"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"uint256","name":"owedDeposit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"realtimeBalanceOfNow","outputs":[{"internalType":"int256","name":"availableBalance","type":"int256"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"uint256","name":"owedDeposit","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"revokeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"selfApproveFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"selfBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"selfMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"selfTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"send","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"int256","name":"delta","type":"int256"}],"name":"settleBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"dataLength","type":"uint256"}],"name":"terminateAgreement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"toUnderlyingAmount","outputs":[{"internalType":"uint256","name":"underlyingAmount","type":"uint256"},{"internalType":"uint256","name":"adjustedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"transferAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes32[]","name":"data","type":"bytes32[]"}],"name":"updateAgreementData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"slotId","type":"uint256"},{"internalType":"bytes32[]","name":"slotData","type":"bytes32[]"}],"name":"updateAgreementStateSlot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"updateCode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61012060405234801561001157600080fd5b5060405161524638038061524683398101604081905261003091610140565b6001600160a01b0380861660805284811660a081905284821660c0528382166101005290821660e0526040517fcf554eb342edf010a94e07701ae91e99e90b769f649f03aeb1153654ddd43c0190600090a26040516001600160a01b038416907f8837af285f4d380af9227df9ebafa13d992b487fa6d7a4366bd4154576085b8990600090a26040516001600160a01b038316907feb87fb34067547f3dc0b85096c3da73c99d4fbb08ff41212b8d7c0b5008b42e690600090a26040516001600160a01b038216907fc1050c54a299c837fe281a2623c29ec8e34b455daef48760b6a29f4b6cc9906090600090a250505050506101b5565b6001600160a01b038116811461013d57600080fd5b50565b600080600080600060a0868803121561015857600080fd5b855161016381610128565b602087015190955061017481610128565b604087015190945061018581610128565b606087015190935061019681610128565b60808701519092506101a781610128565b809150509295509295909350565b60805160a05160c05160e05161010051614fac61029a600039600061083e015260006109c2015260008181610688015261163101526000818161099b01526115940152600081816104ea01528181610c9e01528181610d0d0152818161102d015281816110bd015281816111ed015281816112bc015281816114d30152818161167c015281816116f101528181611839015281816119e401528181611ac301528181611eb401528181611f7e015281816120160152818161207e01528181612106015281816129b601528181612a4d01528181613b410152613d800152614fac6000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80636c2d9f2f11610220578063b84cdd4a11610130578063dd62ed3e116100b8578063ef43d2c611610087578063ef43d2c614610996578063f5a8b4dd146109bd578063fad8b32a146109e4578063fc673c4f146109f7578063fe9d930314610a0a57600080fd5b8063dd62ed3e1461090b578063eb3537cc14610944578063ec0d634314610972578063ee719bc81461098557600080fd5b8063ca0c1e7f116100ff578063ca0c1e7f146108ac578063ca789464146108bf578063cf97256d146108d2578063d95b6371146108e5578063d9d078d6146108f857600080fd5b8063b84cdd4a14610860578063bb0d196e14610873578063c68d428314610886578063c780fd821461089957600080fd5b806395d89b41116101b3578063a1b2bf8b11610182578063a1b2bf8b146107ed578063a3a7e7f314610800578063a457c2d714610813578063a9059cbb14610826578063b20db1ac1461083957600080fd5b806395d89b41146107b75780639903ad38146107bf5780639bd9bbc6146107c75780639d876741146107da57600080fd5b806383ba2525116101ef57806383ba25251461076c5780638f2839701461077f57806392081a4714610792578063959b8c3f146107a457600080fd5b80636c2d9f2f1461072b5780636e9960c31461073e57806370a082311461074657806379359f6f1461075957600080fd5b8063386fa2211161031b5780634b61cc33116102ae578063556f0dc71161027d578063556f0dc7146106d85780635b9d09cc146106df57806362aa5287146106f257806362ad1b831461070557806366a12fb61461071857600080fd5b80634b61cc33146106635780634c5c0c851461068357806350d75d25146106aa57806352d1902d146106b257600080fd5b806345977d03116102ea57806345977d0314610617578063469519541461062a57806347ba7ad11461063d5780634b2763b31461065057600080fd5b8063386fa221146105cb57806339509351146105de57806341b706be146105f157806342fe09801461060457600080fd5b80631863e8091161039e578063245887fc1161036d578063245887fc146105355780632704839714610548578063282a050b1461055b5780632ec8eec714610583578063313ce567146105b657600080fd5b80631863e809146104c25780631ae88ffc146104d557806320bc4425146104e857806323b872dd1461052257600080fd5b806311bcc81e116103da57806311bcc81e1461047757806312a6a3f81461048a57806316d055d61461049d57806318160ddd146104b057600080fd5b806306e485381461040c57806306fdde031461042a578063090c415e1461043f578063095ea7b314610454575b600080fd5b610414610a1d565b6040516104219190613f9a565b60405180910390f35b610432610a2e565b6040516104219190614036565b61045261044d3660046140a9565b610ac0565b005b610467610462366004614104565b610b73565b6040519015158152602001610421565b610452610485366004614130565b610b8a565b610452610498366004614149565b610bb9565b6104526104ab366004614194565b610c9c565b6003545b604051908152602001610421565b6104526104d03660046142a8565b610cf8565b6104526104e336600461433a565b61102b565b7f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610421565b61046761053036600461433a565b6110a5565b610452610543366004614104565b6110bb565b61045261055636600461437b565b611134565b61056e610569366004614130565b6111d0565b60408051928352602083019190915201610421565b61059661059136600461439d565b6111e5565b604080519485526020850193909352918301526060820152608001610421565b60125b60405160ff9091168152602001610421565b6104146105d936600461439d565b611288565b6104676105ec366004614104565b61132b565b6104526105ff366004614194565b611367565b610452610612366004614411565b611393565b610452610625366004614130565b611474565b61045261063836600461439d565b6114a0565b61045261064b36600461433a565b61167a565b61045261065e36600461433a565b6116ef565b6106766106713660046144a7565b611771565b60405161042191906144ed565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b61050a6117b6565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb00196104b4565b60016104b4565b6104526106ed366004614525565b6117e0565b61045261070036600461433a565b611837565b610452610713366004614574565b61188b565b61045261072636600461433a565b611939565b610676610739366004614616565b611959565b61050a61199b565b6104b461075436600461439d565b6119b3565b61046761076736600461439d565b6119dc565b61045261077a366004614104565b611a64565b61045261078d36600461439d565b611a90565b600e54600160a01b900460ff166105b9565b6104526107b236600461439d565b611b84565b610432611bd5565b610452611be4565b6104526107d5366004614525565b611ca6565b6104526107e836600461464b565b611cfa565b6104526107fb366004614149565b611d40565b61045261080e36600461439d565b611dea565b610467610821366004614104565b611dfe565b610467610834366004614104565b611e4d565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b61046761086e366004614104565b611e5b565b61046761088136600461439d565b611eac565b61045261089436600461464b565b611f34565b6104526108a736600461433a565b611f7c565b6104526108ba3660046146a3565b612014565b6104526108cd366004614104565b61207c565b6104526108e0366004614104565b6120f1565b6104676108f336600461470e565b6121da565b610467610906366004614104565b6121e8565b6104b461091936600461470e565b6001600160a01b03918216600090815260116020908152604080832093909416825291909152205490565b610957610952366004614104565b612202565b60408051938452602084019290925290820152606001610421565b610452610980366004614747565b612336565b600e546001600160a01b031661050a565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b6104526109f236600461439d565b61240d565b610452610a053660046147f1565b61245e565b610452610a18366004614837565b6124ff565b6060610a296012612550565b905090565b6060600f8054610a3d90614875565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6990614875565b8015610ab65780601f10610a8b57610100808354040283529160200191610ab6565b820191906000526020600020905b815481529060010190602001808311610a9957829003601f168201915b5050505050905090565b6000338585604051602001610ad7939291906148af565b604051602081830303815290604052805190602001209050610b2c818484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506125b692505050565b6040518481526001600160a01b0386169033907f30f416fa68fca014a0f334464c64b000ba53e99b6d2afdea9d5ca756372d59859060200160405180910390a35050505050565b6000610b803384846125ee565b5060015b92915050565b610bb633333384604051806020016040528060008152506040518060200160405280600081525061269d565b50565b6040513390600090610bd190839087906020016148f8565b60408051601f1981840301815291905280516020909101209050610bf5818461285d565b15610c135760405163782a90fb60e11b815260040160405180910390fd5b610c50818585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506125b692505050565b816001600160a01b03167f770ea40a13a4644573ed785e5c7116890709947918747febc5add46feb531e2d868686604051610c8d93929190614935565b60405180910390a25050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610ce55760405163c51efddd60e01b815260040160405180910390fd5b610cf184848484612891565b5050505050565b604051632329212160e21b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638ca4848490602401602060405180830381865afa158015610d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d809190614976565b610d9d5760405163327fd99160e21b815260040160405180910390fd5b6000610da76129b1565b90506001600160a01b038116610dba5750845b600085610dc75786610dc9565b815b905060008313610e9757610ddc836149a9565b610de585612af6565b14610df257610df26149c5565b610dfb84612af6565b6001600160a01b03821660009081526002602052604081208054909190610e239084906149db565b90915550506001600160a01b03851660009081526002602052604081208054859290610e509084906149db565b92505081905550806001600160a01b0316856001600160a01b0316600080516020614f2a83398151915286604051610e8a91815260200190565b60405180910390a3610fc3565b8515610ea557610ea56149c5565b82610eaf85612af6565b610eb991906149db565b6001600160a01b03831660009081526002602052604081208054909190610ee1908490614a03565b90915550610ef0905084612af6565b6001600160a01b03881660009081526002602052604081208054909190610f189084906149db565b90915550506001600160a01b03851660009081526002602052604081208054859290610f459084906149db565b92505081905550866001600160a01b0316826001600160a01b0316600080516020614f2a83398151915286604051610f7f91815260200190565b60405180910390a3846001600160a01b0316826001600160a01b0316600080516020614f2a83398151915285604051610fba91815260200190565b60405180910390a35b846001600160a01b0316876001600160a01b0316336001600160a01b03167fb8381a3ce157650e06186e3e8f4dd4dc29236f2688b6eed1893d0a60d7c6386f8c8589898f604051611018959493929190614a23565b60405180910390a4505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146110745760405163c51efddd60e01b815260040160405180910390fd5b6110a0338484846040518060200160405280600081525060405180602001604052806000815250612b64565b505050565b60006110b333858585612891565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146111045760405163c51efddd60e01b815260040160405180910390fd5b61113033838484604051806020016040528060008152506040518060200160405280600081525061269d565b5050565b604051339060009061114c90839086906020016148f8565b60405160208183030381529060405280519060200120905061116e818461285d565b61118b5760405163dae1880960e01b815260040160405180910390fd5b6111958184612d17565b60405184815233907f71a63dc095de07aa5512ad57a7596a39516317e316981a1cd71000057be1537b9060200160405180910390a250505050565b6000806111dc83612d30565b91509150915091565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190614a56565b90506112798582612202565b91979096509094509092509050565b6001600160a01b038181166000908152600160205260409081902054905163c56a069d60e01b8152901960048201526060917f0000000000000000000000000000000000000000000000000000000000000000169063c56a069d90602401600060405180830381865afa158015611303573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190614a6f565b3360008181526011602090815260408083206001600160a01b03871684529091528120549091610b80918590611362908690614b1b565b6125ee565b33301461138757604051630fff4cc960e31b815260040160405180910390fd5b610cf183858484612891565b600054610100900460ff16158080156113b35750600054600160ff909116105b806113cd5750303b1580156113cd575060005460ff166001145b6113f25760405162461bcd60e51b81526004016113e990614b2e565b60405180910390fd5b6000805460ff191660011790558015611415576000805461ff0019166101001790555b6114258787878787876000612dec565b801561146b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b610bb6333333846040518060200160405280600081525060405180602001604052806000815250612b64565b60006114b8600080516020614ee08339815191525490565b905060006001600160a01b038216156114d157816114f3565b7f00000000000000000000000000000000000000000000000000000000000000005b9050336001600160a01b0382161461151e57604051630484acab60e01b815260040160405180910390fd5b61152783612eb4565b826001600160a01b031663ef43d2c66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611565573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115899190614b7c565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614158061165c5750826001600160a01b0316634c5c0c856040518163ffffffff1660e01b8152600401602060405180830381865afa158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190614b7c565b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614155b156110a05760405163ef1b6ddf60e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146116c35760405163c51efddd60e01b815260040160405180910390fd5b6110a033848484604051806020016040528060008152506040518060200160405280600081525061269d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146117385760405163c51efddd60e01b815260040160405180910390fd5b6001600160a01b038084166000908152601160209081526040808320938616835292905220546110a09084908490611362908590614b1b565b6060600085858560405160200161178a939291906148af565b6040516020818303038152906040528051906020012090506117ac81846130ee565b9695505050505050565b6000610a297f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6118313333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250612b64915050565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146118805760405163c51efddd60e01b815260040160405180910390fd5b6110a08383836125ee565b336118986012828a613175565b6118b55760405163f7f0222760e01b815260040160405180910390fd5b61192f8189898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a90819084018382808284376000920191909152506001925061321e915050565b5050505050505050565b33301461188057604051630fff4cc960e31b815260040160405180910390fd5b6060600084846040516020016119709291906148f8565b60405160208183030381529060405280519060200120905061199281846130ee565b95945050505050565b6000610a29600080516020614ee08339815191525490565b6000806119bf836111e5565b5050509050600081126119d257806119d5565b60005b9392505050565b6000610b84827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a40573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614a56565b61113033338484604051806020016040528060008152506040518060200160405280600081525061269d565b6000611aa8600080516020614ee08339815191525490565b905060006001600160a01b03821615611ac15781611ae3565b7f00000000000000000000000000000000000000000000000000000000000000005b9050336001600160a01b03821614611b0e57604051630484acab60e01b815260040160405180910390fd5b6000611b26600080516020614ee08339815191525490565b9050611b3e84600080516020614ee083398151915255565b836001600160a01b0316816001600160a01b03167f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f60405160405180910390a350505050565b33611b9160128284613297565b806001600160a01b0316826001600160a01b03167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a35050565b606060108054610a3d90614875565b600054610100900460ff1615808015611c045750600054600160ff909116105b80611c1e5750303b158015611c1e575060005460ff166001145b611c3a5760405162461bcd60e51b81526004016113e990614b2e565b6000805460ff191660011790558015611c5d576000805461ff0019166101001790555b8015610bb6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b6118313333868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292506001915061321e9050565b333014611d1a57604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a09133918691869190151590869061339b565b6040513390600090611d5890839087906020016148f8565b604051602081830303815290604052805190602001209050611dad818585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506125b692505050565b336001600160a01b03167f0c4c547b3a4fcaa5be8353b3111472b124155bccc86de811d4a481c9e6e9faca868686604051610c8d93929190614935565b611130333383611df9336119b3565b612891565b6000610b803384611362856040518060600160405280602a8152602001614f00602a91393360009081526011602090815260408083206001600160a01b038d1684529091529020549190613468565b60006119d533338585612891565b600080600080611e6b8686612202565b9250925092506000611e93828411611e84576000612af6565b611e8e8385614b99565b612af6565b611e9d90856149db565b60001315979650505050505050565b6000610b84827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f10573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190614a56565b333014611f5457604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a0913391869186919015159081908790613494565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314611fc55760405163c51efddd60e01b815260040160405180910390fd5b6110a08383611362846040518060600160405280602a8152602001614f00602a91396001600160a01b03808a166000908152601160209081526040808320938c16835292905220549190613468565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331461205d5760405163c51efddd60e01b815260040160405180910390fd5b611831338585858560405180602001604052806000815250600161321e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146120c55760405163c51efddd60e01b815260040160405180910390fd5b611130338384846040518060200160405280600081525060405180602001604052806000815250612b64565b604051632329212160e21b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638ca4848490602401602060405180830381865afa158015612155573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121799190614976565b6121965760405163327fd99160e21b815260040160405180910390fd5b6001600160a01b0382166000908152600260205260409020546121ba9082906149db565b6001600160a01b0390921660009081526002602052604090209190915550565b60006119d560128484613175565b6000806121f58484612202565b5050600013949350505050565b6001600160a01b03821660009081526002602052604081205490808061222786611288565b905060005b815181101561232d57600080600084848151811061224c5761224c614bac565b60209081029190910101516040516326cb922f60e21b81523060048201526001600160a01b038c81166024830152604482018c905290911690639b2e48bc90606401606060405180830381865afa1580156122ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122cf9190614bc2565b919450925090506122e08288614b1b565b96506122ec8187614b1b565b95506123098183116122ff576000612af6565b611e8e8284614b99565b612313848a6149db565b61231d9190614a03565b975050505080600101905061222c565b50509250925092565b600054610100900460ff16158080156123565750600054600160ff909116105b806123705750303b158015612370575060005460ff166001145b61238c5760405162461bcd60e51b81526004016113e990614b2e565b6000805460ff1916600117905580156123af576000805461ff0019166101001790555b6123be88888888888888612dec565b801561192f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050565b3361241a60128284613562565b806001600160a01b0316826001600160a01b03167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a35050565b3361246b60128289613175565b6124885760405163f7f0222760e01b815260040160405180910390fd5b61146b8188898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525061269d92505050565b6110a03333338686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805160208101909152908152925061269d915050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156125aa57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161258c575b50505050509050919050565b60005b81518110156110a05760008282815181106125d6576125d6614bac565b602090810291909101015184830155506001016125b9565b6001600160a01b03831661261557604051638163862760e01b815260040160405180910390fd5b6001600160a01b03821661263c576040516337c1c09d60e21b815260040160405180910390fd5b6001600160a01b0383811660008181526011602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600e546001600160a01b03166126c657604051637bce7b2b60e11b815260040160405180910390fd5b6000806126d285612d30565b915091506126e9888883875160001415888861339b565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127569190614a56565b600e54909150612770906001600160a01b0316888561365a565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127dd9190614a56565b905060006127eb8284614b99565b905080851461280d57604051631c7c26d360e31b815260040160405180910390fd5b896001600160a01b03167f3bc27981aebbb57f9247dc00fde9d6cd91e4b230083fec3238fedbcba1f9ab3d8560405161284891815260200190565b60405180910390a25050505050505050505050565b6000805b828110156128875783810154801561287e57600192505050610b84565b50600101612861565b5060009392505050565b60006001600160a01b0384166128ba5760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b0383166128e15760405163e219bd3960e01b815260040160405180910390fd5b60003390506129128186868660405180602001604052806000815250604051806020016040528060008152506136bd565b846001600160a01b0316866001600160a01b0316146129a5576129a58587611362866040518060600160405280602d8152602001614f4a602d9139601160008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020546134689092919063ffffffff16565b50600195945050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663289b3c0d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190614b7c565b604051638369a0f160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301527f9f60ae461adf056670e03ae602566409933242392cb06744f5747c9f38b05d09604483015291925090821690638369a0f190606401602060405180830381865afa158015612acc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af09190614b7c565b91505090565b60006001600160ff1b03821115612b605760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016113e9565b5090565b600e546001600160a01b0316612b8d57604051637bce7b2b60e11b815260040160405180910390fd5b600080612b9985612d30565b600e546040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612bea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0e9190614a56565b600e54909150612c29906001600160a01b031689308661375c565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612c72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c969190614a56565b90506000612ca48383614b99565b9050808514612cc657604051631c7c26d360e31b815260040160405180910390fd5b8651612cdc908c908b9087901515808c8c613494565b886001600160a01b03167f25ca84076773b0455db53621c459ddc84fe40840e4932a62706a032566f399df8560405161284891815260200190565b60005b818110156110a057600083820155600101612d1a565b600e54600090819081906012600160a01b90910460ff161015612d8f57600e54612d6590600160a01b900460ff166012614bf0565b612d7090600a614cf0565b9050612d7c8185614cff565b9250612d888184614d21565b9150612de6565b600e546012600160a01b90910460ff161115612ddf57600e54612dbe90601290600160a01b900460ff16614bf0565b612dc990600a614cf0565b9050612dd58185614d21565b9250839150612de6565b8391508192505b50915091565b600e805460ff8816600160a01b026001600160a81b03199091166001600160a01b038a1617179055600f612e21858783614d7f565b506010612e2f838583614d7f565b50612e4681600080516020614ee083398151915255565b612e4f30613794565b6040516000808252908190600080516020614f2a8339815191529060200160405180910390a36040516001600160a01b038216906000907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f908290a350505050505050565b6000612ede7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b031603612f345760405162461bcd60e51b815260206004820152601d60248201527f5555505350726f786961626c653a206e6f742075706772616461626c6500000060448201526064016113e9565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f969190614a56565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb0019146130105760405162461bcd60e51b815260206004820152602360248201527f5555505350726f786961626c653a206e6f7420636f6d70617469626c65206c6f60448201526267696360e81b60648201526084016113e9565b6001600160a01b03811630036130685760405162461bcd60e51b815260206004820152601960248201527f5555505350726f786961626c653a2070726f7879206c6f6f700000000000000060448201526064016113e9565b613090817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fe011bc04c286c344a8fcbb8de77f953da762c3e25d8cdea984147fc4168a5dcc7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb0019604080519182526001600160a01b038416602083015201611c9b565b6060816001600160401b03811115613108576131086141e5565b604051908082528060200260200182016040528015613131578160200160208202803683370190505b50905060005b8281101561316e5760008185015490508083838151811061315a5761315a614bac565b602090810291909101015250600101613137565b5092915050565b6000816001600160a01b0316836001600160a01b031614806131e457506001600160a01b038316600090815260018501602052604090205460ff1680156131e457506001600160a01b03808316600090815260038601602090815260408083209387168352929052205460ff16155b806110b357506001600160a01b03808316600090815260028601602090815260408083209387168352929052205460ff1690509392505050565b6001600160a01b0386166132455760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b03851661326c5760405163e219bd3960e01b815260040160405180910390fd5b61327a8787878787876138c2565b6132888787878787876136bd565b61146b878787878787876139e9565b806001600160a01b0316826001600160a01b03160361330e5760405162461bcd60e51b815260206004820152602d60248201527f4552433737374f70657261746f72733a20617574686f72697a696e672073656c60448201526c331030b99037b832b930ba37b960991b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff1615613364576001600160a01b03918216600090815260039390930160209081526040808520929093168452529020805460ff19169055565b6001600160a01b0380831660009081526002850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b0385166133c257604051632e8aac6160e21b815260040160405180910390fd5b82156133d7576133d7868660008786866138c2565b6133e18585613b39565b846001600160a01b0316866001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a409886858560405161342893929190614e3e565b60405180910390a36040518481526000906001600160a01b03871690600080516020614f2a833981519152906020015b60405180910390a3505050505050565b6000818484111561348c5760405162461bcd60e51b81526004016113e99190614036565b505050900390565b6001600160a01b0386166134bb57604051630d24315760e01b815260040160405180910390fd5b6134c58686613c49565b83156134db576134db87600088888686896139e9565b856001600160a01b0316876001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d87858560405161352293929190614e3e565b60405180910390a36040518581526001600160a01b03871690600090600080516020614f2a8339815191529060200160405180910390a350505050505050565b336001600160a01b038216036135cd5760405162461bcd60e51b815260206004820152602a60248201527f4552433737374f70657261746f72733a207265766f6b696e672073656c662061604482015269399037b832b930ba37b960b11b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff1615613627576001600160a01b0380831660009081526003850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b03918216600090815260029390930160209081526040808520929093168452529020805460ff19169055565b6040516001600160a01b0383166024820152604481018290526110a090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613ca3565b6136d085856136cb86612af6565b613d78565b836001600160a01b0316856001600160a01b0316876001600160a01b03167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc8261467798786868660405161372193929190614e3e565b60405180910390a4836001600160a01b0316856001600160a01b0316600080516020614f2a8339815191528560405161345891815260200190565b6040516001600160a01b03808516602483015283166044820152606481018290526118319085906323b872dd60e01b90608401613686565b6040516329965a1d60e01b81526001600160a01b03821660048201527fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce21770546024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b15801561381557600080fd5b505af1158015613829573d6000803e3d6000fd5b50506040516329965a1d60e01b81526001600160a01b03841660048201527faea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a6024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b1580156138ae57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b60405163555ddc6560e11b81526001600160a01b03861660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa158015613943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139679190614b7c565b90506001600160a01b0381161561146b57604051633ad5cbc160e11b81526001600160a01b038216906375ab9782906139ae908a908a908a908a908a908a90600401614e69565b600060405180830381600087803b1580156139c857600080fd5b505af11580156139dc573d6000803e3d6000fd5b5050505050505050505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa158015613a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8e9190614b7c565b90506001600160a01b03811615613b0a576040516223de2960e01b81526001600160a01b038216906223de2990613ad3908b908b908b908b908b908b90600401614e69565b600060405180830381600087803b158015613aed57600080fd5b505af1158015613b01573d6000803e3d6000fd5b5050505061192f565b811561192f576001600160a01b0386163b1561192f5760405163fe737d0560e01b815260040160405180910390fd5b6000613bc1837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b9d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109529190614a56565b50509050613bce82612af6565b811215613bee5760405163043b37d160e21b815260040160405180910390fd5b613bf782612af6565b6001600160a01b038416600090815260026020526040902054613c1a9190614a03565b6001600160a01b038416600090815260026020526040902055600354613c41908390614b99565b600355505050565b613c5281612af6565b6001600160a01b038316600090815260026020526040902054613c7591906149db565b6001600160a01b038316600090815260026020526040902055600354613c9c908290614b1b565b6003555050565b6000613cf8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e779092919063ffffffff16565b9050805160001480613d19575080806020019051810190613d199190614976565b6110a05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016113e9565b6000613ddc847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b9d573d6000803e3d6000fd5b5050905081811215613e0157604051632f4cb94160e01b815260040160405180910390fd5b6001600160a01b038416600090815260026020526040902054613e25908390614a03565b6001600160a01b038086166000908152600260205260408082209390935590851681522054613e559083906149db565b6001600160a01b03909316600090815260026020526040902092909255505050565b60606110b3848460008585600080866001600160a01b03168587604051613e9e9190614ec3565b60006040518083038185875af1925050503d8060008114613edb576040519150601f19603f3d011682016040523d82523d6000602084013e613ee0565b606091505b5091509150613ef187838387613efc565b979650505050505050565b60608315613f6b578251600003613f64576001600160a01b0385163b613f645760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016113e9565b50816110b3565b6110b38383815115613f805781518083602001fd5b8060405162461bcd60e51b81526004016113e99190614036565b602080825282518282018190526000918401906040840190835b81811015613fdb5783516001600160a01b0316835260209384019390920191600101613fb4565b509095945050505050565b60005b83811015614001578181015183820152602001613fe9565b50506000910152565b60008151808452614022816020860160208601613fe6565b601f01601f19169290920160200192915050565b6020815260006119d5602083018461400a565b6001600160a01b0381168114610bb657600080fd5b60008083601f84011261407057600080fd5b5081356001600160401b0381111561408757600080fd5b6020830191508360208260051b85010111156140a257600080fd5b9250929050565b600080600080606085870312156140bf57600080fd5b84356140ca81614049565b93506020850135925060408501356001600160401b038111156140ec57600080fd5b6140f88782880161405e565b95989497509550505050565b6000806040838503121561411757600080fd5b823561412281614049565b946020939093013593505050565b60006020828403121561414257600080fd5b5035919050565b60008060006040848603121561415e57600080fd5b8335925060208401356001600160401b0381111561417b57600080fd5b6141878682870161405e565b9497909650939450505050565b600080600080608085870312156141aa57600080fd5b84356141b581614049565b935060208501356141c581614049565b925060408501356141d581614049565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614223576142236141e5565b604052919050565b600082601f83011261423c57600080fd5b81356001600160401b03811115614255576142556141e5565b614268601f8201601f19166020016141fb565b81815284602083860101111561427d57600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114610bb657600080fd5b600080600080600080600060e0888a0312156142c357600080fd5b8735965060208801356001600160401b038111156142e057600080fd5b6142ec8a828b0161422b565b96505060408801356142fd81614049565b9450606088013561430d8161429a565b9350608088013561431d81614049565b9699959850939692959460a0840135945060c09093013592915050565b60008060006060848603121561434f57600080fd5b833561435a81614049565b9250602084013561436a81614049565b929592945050506040919091013590565b6000806040838503121561438e57600080fd5b50508035926020909101359150565b6000602082840312156143af57600080fd5b81356119d581614049565b803560ff811681146143cb57600080fd5b919050565b60008083601f8401126143e257600080fd5b5081356001600160401b038111156143f957600080fd5b6020830191508360208285010111156140a257600080fd5b6000806000806000806080878903121561442a57600080fd5b863561443581614049565b9550614443602088016143ba565b945060408701356001600160401b0381111561445e57600080fd5b61446a89828a016143d0565b90955093505060608701356001600160401b0381111561448957600080fd5b61449589828a016143d0565b979a9699509497509295939492505050565b600080600080608085870312156144bd57600080fd5b84356144c881614049565b935060208501356144d881614049565b93969395505050506040820135916060013590565b602080825282518282018190526000918401906040840190835b81811015613fdb578351835260209384019390920191600101614507565b6000806000806060858703121561453b57600080fd5b843561454681614049565b93506020850135925060408501356001600160401b0381111561456857600080fd5b6140f8878288016143d0565b600080600080600080600060a0888a03121561458f57600080fd5b873561459a81614049565b965060208801356145aa81614049565b95506040880135945060608801356001600160401b038111156145cc57600080fd5b6145d88a828b016143d0565b90955093505060808801356001600160401b038111156145f757600080fd5b6146038a828b016143d0565b989b979a50959850939692959293505050565b60008060006060848603121561462b57600080fd5b833561463681614049565b95602085013595506040909401359392505050565b60008060006060848603121561466057600080fd5b833561466b81614049565b92506020840135915060408401356001600160401b0381111561468d57600080fd5b6146998682870161422b565b9150509250925092565b600080600080608085870312156146b957600080fd5b84356146c481614049565b935060208501356146d481614049565b92506040850135915060608501356001600160401b038111156146f657600080fd5b6147028782880161422b565b91505092959194509250565b6000806040838503121561472157600080fd5b823561472c81614049565b9150602083013561473c81614049565b809150509250929050565b600080600080600080600060a0888a03121561476257600080fd5b873561476d81614049565b965061477b602089016143ba565b955060408801356001600160401b0381111561479657600080fd5b6147a28a828b016143d0565b90965094505060608801356001600160401b038111156147c157600080fd5b6147cd8a828b016143d0565b90945092505060808801356147e181614049565b8091505092959891949750929550565b6000806000806000806080878903121561480a57600080fd5b863561481581614049565b95506020870135945060408701356001600160401b0381111561445e57600080fd5b60008060006040848603121561484c57600080fd5b8335925060208401356001600160401b0381111561486957600080fd5b614187868287016143d0565b600181811c9082168061488957607f821691505b6020821081036148a957634e487b7160e01b600052602260045260246000fd5b50919050565b6080808252600e908201526d41677265656d656e74537461746560901b60a08201526001600160a01b039384166020820152919092166040820152606081019190915260c00190565b6060808252600d908201526c41677265656d656e744461746160981b60808201526001600160a01b03929092166020830152604082015260a00190565b838152604060208201819052810182905260006001600160fb1b0383111561495c57600080fd5b8260051b8085606085013791909101606001949350505050565b60006020828403121561498857600080fd5b81516119d58161429a565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b82016149be576149be614993565b5060000390565b634e487b7160e01b600052600160045260246000fd5b80820182811260008312801582168215821617156149fb576149fb614993565b505092915050565b818103600083128015838313168383128216171561316e5761316e614993565b85815260018060a01b038516602082015283604082015282606082015260a060808201526000613ef160a083018461400a565b600060208284031215614a6857600080fd5b5051919050565b600060208284031215614a8157600080fd5b81516001600160401b03811115614a9757600080fd5b8201601f81018413614aa857600080fd5b80516001600160401b03811115614ac157614ac16141e5565b8060051b614ad1602082016141fb565b91825260208184018101929081019087841115614aed57600080fd5b6020850194505b83851015613ef15784519250614b0983614049565b82825260209485019490910190614af4565b80820180821115610b8457610b84614993565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b600060208284031215614b8e57600080fd5b81516119d581614049565b81810381811115610b8457610b84614993565b634e487b7160e01b600052603260045260246000fd5b600080600060608486031215614bd757600080fd5b5050815160208301516040909301519094929350919050565b60ff8281168282160390811115610b8457610b84614993565b6001815b6001841115614c4457808504811115614c2857614c28614993565b6001841615614c3657908102905b60019390931c928002614c0d565b935093915050565b600082614c5b57506001610b84565b81614c6857506000610b84565b8160018114614c7e5760028114614c8857614ca4565b6001915050610b84565b60ff841115614c9957614c99614993565b50506001821b610b84565b5060208310610133831016604e8410600b8410161715614cc7575081810a610b84565b614cd46000198484614c09565b8060001904821115614ce857614ce8614993565b029392505050565b60006119d560ff841683614c4c565b600082614d1c57634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610b8457610b84614993565b601f8211156110a057806000526020600020601f840160051c81016020851015614d5f5750805b601f840160051c820191505b81811015610cf15760008155600101614d6b565b6001600160401b03831115614d9657614d966141e5565b614daa83614da48354614875565b83614d38565b6000601f841160018114614dde5760008515614dc65750838201355b600019600387901b1c1916600186901b178355610cf1565b600083815260209020601f19861690835b82811015614e0f5786850135825560209485019460019092019101614def565b5086821015614e2c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b838152606060208201526000614e57606083018561400a565b82810360408401526117ac818561400a565b6001600160a01b0387811682528681166020830152851660408201526060810184905260c060808201819052600090614ea49083018561400a565b82810360a0840152614eb6818561400a565b9998505050505050505050565b60008251614ed5818460208701613fe6565b919091019291505056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035375706572546f6b656e3a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5375706572546f6b656e3a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365a2646970667358221220519e9e812043dd9a3636890af9dde938734418c6c5ae526cb7acfedbb3e1313364736f6c634300081a00330000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe7000000000000000000000000fc00dee8a980110c5608a823a5b3af38726354560000000000000000000000001497440b4e92dc4ca0f76223b28c20cb9cb8a0f1000000000000000000000000a4806df890e5212c2879628b4c3b07341f881ed50000000000000000000000004821ef52bd6c822c079340b8c11eae1062ff13c2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104075760003560e01c80636c2d9f2f11610220578063b84cdd4a11610130578063dd62ed3e116100b8578063ef43d2c611610087578063ef43d2c614610996578063f5a8b4dd146109bd578063fad8b32a146109e4578063fc673c4f146109f7578063fe9d930314610a0a57600080fd5b8063dd62ed3e1461090b578063eb3537cc14610944578063ec0d634314610972578063ee719bc81461098557600080fd5b8063ca0c1e7f116100ff578063ca0c1e7f146108ac578063ca789464146108bf578063cf97256d146108d2578063d95b6371146108e5578063d9d078d6146108f857600080fd5b8063b84cdd4a14610860578063bb0d196e14610873578063c68d428314610886578063c780fd821461089957600080fd5b806395d89b41116101b3578063a1b2bf8b11610182578063a1b2bf8b146107ed578063a3a7e7f314610800578063a457c2d714610813578063a9059cbb14610826578063b20db1ac1461083957600080fd5b806395d89b41146107b75780639903ad38146107bf5780639bd9bbc6146107c75780639d876741146107da57600080fd5b806383ba2525116101ef57806383ba25251461076c5780638f2839701461077f57806392081a4714610792578063959b8c3f146107a457600080fd5b80636c2d9f2f1461072b5780636e9960c31461073e57806370a082311461074657806379359f6f1461075957600080fd5b8063386fa2211161031b5780634b61cc33116102ae578063556f0dc71161027d578063556f0dc7146106d85780635b9d09cc146106df57806362aa5287146106f257806362ad1b831461070557806366a12fb61461071857600080fd5b80634b61cc33146106635780634c5c0c851461068357806350d75d25146106aa57806352d1902d146106b257600080fd5b806345977d03116102ea57806345977d0314610617578063469519541461062a57806347ba7ad11461063d5780634b2763b31461065057600080fd5b8063386fa221146105cb57806339509351146105de57806341b706be146105f157806342fe09801461060457600080fd5b80631863e8091161039e578063245887fc1161036d578063245887fc146105355780632704839714610548578063282a050b1461055b5780632ec8eec714610583578063313ce567146105b657600080fd5b80631863e809146104c25780631ae88ffc146104d557806320bc4425146104e857806323b872dd1461052257600080fd5b806311bcc81e116103da57806311bcc81e1461047757806312a6a3f81461048a57806316d055d61461049d57806318160ddd146104b057600080fd5b806306e485381461040c57806306fdde031461042a578063090c415e1461043f578063095ea7b314610454575b600080fd5b610414610a1d565b6040516104219190613f9a565b60405180910390f35b610432610a2e565b6040516104219190614036565b61045261044d3660046140a9565b610ac0565b005b610467610462366004614104565b610b73565b6040519015158152602001610421565b610452610485366004614130565b610b8a565b610452610498366004614149565b610bb9565b6104526104ab366004614194565b610c9c565b6003545b604051908152602001610421565b6104526104d03660046142a8565b610cf8565b6104526104e336600461433a565b61102b565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe75b6040516001600160a01b039091168152602001610421565b61046761053036600461433a565b6110a5565b610452610543366004614104565b6110bb565b61045261055636600461437b565b611134565b61056e610569366004614130565b6111d0565b60408051928352602083019190915201610421565b61059661059136600461439d565b6111e5565b604080519485526020850193909352918301526060820152608001610421565b60125b60405160ff9091168152602001610421565b6104146105d936600461439d565b611288565b6104676105ec366004614104565b61132b565b6104526105ff366004614194565b611367565b610452610612366004614411565b611393565b610452610625366004614130565b611474565b61045261063836600461439d565b6114a0565b61045261064b36600461433a565b61167a565b61045261065e36600461433a565b6116ef565b6106766106713660046144a7565b611771565b60405161042191906144ed565b61050a7f0000000000000000000000001497440b4e92dc4ca0f76223b28c20cb9cb8a0f181565b61050a6117b6565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb00196104b4565b60016104b4565b6104526106ed366004614525565b6117e0565b61045261070036600461433a565b611837565b610452610713366004614574565b61188b565b61045261072636600461433a565b611939565b610676610739366004614616565b611959565b61050a61199b565b6104b461075436600461439d565b6119b3565b61046761076736600461439d565b6119dc565b61045261077a366004614104565b611a64565b61045261078d36600461439d565b611a90565b600e54600160a01b900460ff166105b9565b6104526107b236600461439d565b611b84565b610432611bd5565b610452611be4565b6104526107d5366004614525565b611ca6565b6104526107e836600461464b565b611cfa565b6104526107fb366004614149565b611d40565b61045261080e36600461439d565b611dea565b610467610821366004614104565b611dfe565b610467610834366004614104565b611e4d565b61050a7f000000000000000000000000a4806df890e5212c2879628b4c3b07341f881ed581565b61046761086e366004614104565b611e5b565b61046761088136600461439d565b611eac565b61045261089436600461464b565b611f34565b6104526108a736600461433a565b611f7c565b6104526108ba3660046146a3565b612014565b6104526108cd366004614104565b61207c565b6104526108e0366004614104565b6120f1565b6104676108f336600461470e565b6121da565b610467610906366004614104565b6121e8565b6104b461091936600461470e565b6001600160a01b03918216600090815260116020908152604080832093909416825291909152205490565b610957610952366004614104565b612202565b60408051938452602084019290925290820152606001610421565b610452610980366004614747565b612336565b600e546001600160a01b031661050a565b61050a7f000000000000000000000000fc00dee8a980110c5608a823a5b3af387263545681565b61050a7f0000000000000000000000004821ef52bd6c822c079340b8c11eae1062ff13c281565b6104526109f236600461439d565b61240d565b610452610a053660046147f1565b61245e565b610452610a18366004614837565b6124ff565b6060610a296012612550565b905090565b6060600f8054610a3d90614875565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6990614875565b8015610ab65780601f10610a8b57610100808354040283529160200191610ab6565b820191906000526020600020905b815481529060010190602001808311610a9957829003601f168201915b5050505050905090565b6000338585604051602001610ad7939291906148af565b604051602081830303815290604052805190602001209050610b2c818484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506125b692505050565b6040518481526001600160a01b0386169033907f30f416fa68fca014a0f334464c64b000ba53e99b6d2afdea9d5ca756372d59859060200160405180910390a35050505050565b6000610b803384846125ee565b5060015b92915050565b610bb633333384604051806020016040528060008152506040518060200160405280600081525061269d565b50565b6040513390600090610bd190839087906020016148f8565b60408051601f1981840301815291905280516020909101209050610bf5818461285d565b15610c135760405163782a90fb60e11b815260040160405180910390fd5b610c50818585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506125b692505050565b816001600160a01b03167f770ea40a13a4644573ed785e5c7116890709947918747febc5add46feb531e2d868686604051610c8d93929190614935565b60405180910390a25050505050565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b03163314610ce55760405163c51efddd60e01b815260040160405180910390fd5b610cf184848484612891565b5050505050565b604051632329212160e21b81523360048201527f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031690638ca4848490602401602060405180830381865afa158015610d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d809190614976565b610d9d5760405163327fd99160e21b815260040160405180910390fd5b6000610da76129b1565b90506001600160a01b038116610dba5750845b600085610dc75786610dc9565b815b905060008313610e9757610ddc836149a9565b610de585612af6565b14610df257610df26149c5565b610dfb84612af6565b6001600160a01b03821660009081526002602052604081208054909190610e239084906149db565b90915550506001600160a01b03851660009081526002602052604081208054859290610e509084906149db565b92505081905550806001600160a01b0316856001600160a01b0316600080516020614f2a83398151915286604051610e8a91815260200190565b60405180910390a3610fc3565b8515610ea557610ea56149c5565b82610eaf85612af6565b610eb991906149db565b6001600160a01b03831660009081526002602052604081208054909190610ee1908490614a03565b90915550610ef0905084612af6565b6001600160a01b03881660009081526002602052604081208054909190610f189084906149db565b90915550506001600160a01b03851660009081526002602052604081208054859290610f459084906149db565b92505081905550866001600160a01b0316826001600160a01b0316600080516020614f2a83398151915286604051610f7f91815260200190565b60405180910390a3846001600160a01b0316826001600160a01b0316600080516020614f2a83398151915285604051610fba91815260200190565b60405180910390a35b846001600160a01b0316876001600160a01b0316336001600160a01b03167fb8381a3ce157650e06186e3e8f4dd4dc29236f2688b6eed1893d0a60d7c6386f8c8589898f604051611018959493929190614a23565b60405180910390a4505050505050505050565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031633146110745760405163c51efddd60e01b815260040160405180910390fd5b6110a0338484846040518060200160405280600081525060405180602001604052806000815250612b64565b505050565b60006110b333858585612891565b949350505050565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031633146111045760405163c51efddd60e01b815260040160405180910390fd5b61113033838484604051806020016040528060008152506040518060200160405280600081525061269d565b5050565b604051339060009061114c90839086906020016148f8565b60405160208183030381529060405280519060200120905061116e818461285d565b61118b5760405163dae1880960e01b815260040160405180910390fd5b6111958184612d17565b60405184815233907f71a63dc095de07aa5512ad57a7596a39516317e316981a1cd71000057be1537b9060200160405180910390a250505050565b6000806111dc83612d30565b91509150915091565b6000806000807f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190614a56565b90506112798582612202565b91979096509094509092509050565b6001600160a01b038181166000908152600160205260409081902054905163c56a069d60e01b8152901960048201526060917f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe7169063c56a069d90602401600060405180830381865afa158015611303573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b849190810190614a6f565b3360008181526011602090815260408083206001600160a01b03871684529091528120549091610b80918590611362908690614b1b565b6125ee565b33301461138757604051630fff4cc960e31b815260040160405180910390fd5b610cf183858484612891565b600054610100900460ff16158080156113b35750600054600160ff909116105b806113cd5750303b1580156113cd575060005460ff166001145b6113f25760405162461bcd60e51b81526004016113e990614b2e565b60405180910390fd5b6000805460ff191660011790558015611415576000805461ff0019166101001790555b6114258787878787876000612dec565b801561146b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b610bb6333333846040518060200160405280600081525060405180602001604052806000815250612b64565b60006114b8600080516020614ee08339815191525490565b905060006001600160a01b038216156114d157816114f3565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe75b9050336001600160a01b0382161461151e57604051630484acab60e01b815260040160405180910390fd5b61152783612eb4565b826001600160a01b031663ef43d2c66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611565573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115899190614b7c565b6001600160a01b03167f000000000000000000000000fc00dee8a980110c5608a823a5b3af38726354566001600160a01b031614158061165c5750826001600160a01b0316634c5c0c856040518163ffffffff1660e01b8152600401602060405180830381865afa158015611602573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116269190614b7c565b6001600160a01b03167f0000000000000000000000001497440b4e92dc4ca0f76223b28c20cb9cb8a0f16001600160a01b031614155b156110a05760405163ef1b6ddf60e01b815260040160405180910390fd5b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031633146116c35760405163c51efddd60e01b815260040160405180910390fd5b6110a033848484604051806020016040528060008152506040518060200160405280600081525061269d565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031633146117385760405163c51efddd60e01b815260040160405180910390fd5b6001600160a01b038084166000908152601160209081526040808320938616835292905220546110a09084908490611362908590614b1b565b6060600085858560405160200161178a939291906148af565b6040516020818303038152906040528051906020012090506117ac81846130ee565b9695505050505050565b6000610a297f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6118313333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250612b64915050565b50505050565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031633146118805760405163c51efddd60e01b815260040160405180910390fd5b6110a08383836125ee565b336118986012828a613175565b6118b55760405163f7f0222760e01b815260040160405180910390fd5b61192f8189898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a90819084018382808284376000920191909152506001925061321e915050565b5050505050505050565b33301461188057604051630fff4cc960e31b815260040160405180910390fd5b6060600084846040516020016119709291906148f8565b60405160208183030381529060405280519060200120905061199281846130ee565b95945050505050565b6000610a29600080516020614ee08339815191525490565b6000806119bf836111e5565b5050509050600081126119d257806119d5565b60005b9392505050565b6000610b84827f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a40573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614a56565b61113033338484604051806020016040528060008152506040518060200160405280600081525061269d565b6000611aa8600080516020614ee08339815191525490565b905060006001600160a01b03821615611ac15781611ae3565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe75b9050336001600160a01b03821614611b0e57604051630484acab60e01b815260040160405180910390fd5b6000611b26600080516020614ee08339815191525490565b9050611b3e84600080516020614ee083398151915255565b836001600160a01b0316816001600160a01b03167f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f60405160405180910390a350505050565b33611b9160128284613297565b806001600160a01b0316826001600160a01b03167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a35050565b606060108054610a3d90614875565b600054610100900460ff1615808015611c045750600054600160ff909116105b80611c1e5750303b158015611c1e575060005460ff166001145b611c3a5760405162461bcd60e51b81526004016113e990614b2e565b6000805460ff191660011790558015611c5d576000805461ff0019166101001790555b8015610bb6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b6118313333868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250604080516020810190915290815292506001915061321e9050565b333014611d1a57604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a09133918691869190151590869061339b565b6040513390600090611d5890839087906020016148f8565b604051602081830303815290604052805190602001209050611dad818585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506125b692505050565b336001600160a01b03167f0c4c547b3a4fcaa5be8353b3111472b124155bccc86de811d4a481c9e6e9faca868686604051610c8d93929190614935565b611130333383611df9336119b3565b612891565b6000610b803384611362856040518060600160405280602a8152602001614f00602a91393360009081526011602090815260408083206001600160a01b038d1684529091529020549190613468565b60006119d533338585612891565b600080600080611e6b8686612202565b9250925092506000611e93828411611e84576000612af6565b611e8e8385614b99565b612af6565b611e9d90856149db565b60001315979650505050505050565b6000610b84827f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f10573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190614a56565b333014611f5457604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a0913391869186919015159081908790613494565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b03163314611fc55760405163c51efddd60e01b815260040160405180910390fd5b6110a08383611362846040518060600160405280602a8152602001614f00602a91396001600160a01b03808a166000908152601160209081526040808320938c16835292905220549190613468565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b0316331461205d5760405163c51efddd60e01b815260040160405180910390fd5b611831338585858560405180602001604052806000815250600161321e565b7f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031633146120c55760405163c51efddd60e01b815260040160405180910390fd5b611130338384846040518060200160405280600081525060405180602001604052806000815250612b64565b604051632329212160e21b81523360048201527f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031690638ca4848490602401602060405180830381865afa158015612155573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121799190614976565b6121965760405163327fd99160e21b815260040160405180910390fd5b6001600160a01b0382166000908152600260205260409020546121ba9082906149db565b6001600160a01b0390921660009081526002602052604090209190915550565b60006119d560128484613175565b6000806121f58484612202565b5050600013949350505050565b6001600160a01b03821660009081526002602052604081205490808061222786611288565b905060005b815181101561232d57600080600084848151811061224c5761224c614bac565b60209081029190910101516040516326cb922f60e21b81523060048201526001600160a01b038c81166024830152604482018c905290911690639b2e48bc90606401606060405180830381865afa1580156122ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122cf9190614bc2565b919450925090506122e08288614b1b565b96506122ec8187614b1b565b95506123098183116122ff576000612af6565b611e8e8284614b99565b612313848a6149db565b61231d9190614a03565b975050505080600101905061222c565b50509250925092565b600054610100900460ff16158080156123565750600054600160ff909116105b806123705750303b158015612370575060005460ff166001145b61238c5760405162461bcd60e51b81526004016113e990614b2e565b6000805460ff1916600117905580156123af576000805461ff0019166101001790555b6123be88888888888888612dec565b801561192f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050565b3361241a60128284613562565b806001600160a01b0316826001600160a01b03167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a35050565b3361246b60128289613175565b6124885760405163f7f0222760e01b815260040160405180910390fd5b61146b8188898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525061269d92505050565b6110a03333338686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805160208101909152908152925061269d915050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156125aa57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161258c575b50505050509050919050565b60005b81518110156110a05760008282815181106125d6576125d6614bac565b602090810291909101015184830155506001016125b9565b6001600160a01b03831661261557604051638163862760e01b815260040160405180910390fd5b6001600160a01b03821661263c576040516337c1c09d60e21b815260040160405180910390fd5b6001600160a01b0383811660008181526011602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600e546001600160a01b03166126c657604051637bce7b2b60e11b815260040160405180910390fd5b6000806126d285612d30565b915091506126e9888883875160001415888861339b565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127569190614a56565b600e54909150612770906001600160a01b0316888561365a565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127dd9190614a56565b905060006127eb8284614b99565b905080851461280d57604051631c7c26d360e31b815260040160405180910390fd5b896001600160a01b03167f3bc27981aebbb57f9247dc00fde9d6cd91e4b230083fec3238fedbcba1f9ab3d8560405161284891815260200190565b60405180910390a25050505050505050505050565b6000805b828110156128875783810154801561287e57600192505050610b84565b50600101612861565b5060009392505050565b60006001600160a01b0384166128ba5760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b0383166128e15760405163e219bd3960e01b815260040160405180910390fd5b60003390506129128186868660405180602001604052806000815250604051806020016040528060008152506136bd565b846001600160a01b0316866001600160a01b0316146129a5576129a58587611362866040518060600160405280602d8152602001614f4a602d9139601160008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020546134689092919063ffffffff16565b50600195945050505050565b6000807f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031663289b3c0d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a369190614b7c565b604051638369a0f160e01b81526001600160a01b037f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe7811660048301523060248301527f9f60ae461adf056670e03ae602566409933242392cb06744f5747c9f38b05d09604483015291925090821690638369a0f190606401602060405180830381865afa158015612acc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af09190614b7c565b91505090565b60006001600160ff1b03821115612b605760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016113e9565b5090565b600e546001600160a01b0316612b8d57604051637bce7b2b60e11b815260040160405180910390fd5b600080612b9985612d30565b600e546040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612bea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0e9190614a56565b600e54909150612c29906001600160a01b031689308661375c565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612c72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c969190614a56565b90506000612ca48383614b99565b9050808514612cc657604051631c7c26d360e31b815260040160405180910390fd5b8651612cdc908c908b9087901515808c8c613494565b886001600160a01b03167f25ca84076773b0455db53621c459ddc84fe40840e4932a62706a032566f399df8560405161284891815260200190565b60005b818110156110a057600083820155600101612d1a565b600e54600090819081906012600160a01b90910460ff161015612d8f57600e54612d6590600160a01b900460ff166012614bf0565b612d7090600a614cf0565b9050612d7c8185614cff565b9250612d888184614d21565b9150612de6565b600e546012600160a01b90910460ff161115612ddf57600e54612dbe90601290600160a01b900460ff16614bf0565b612dc990600a614cf0565b9050612dd58185614d21565b9250839150612de6565b8391508192505b50915091565b600e805460ff8816600160a01b026001600160a81b03199091166001600160a01b038a1617179055600f612e21858783614d7f565b506010612e2f838583614d7f565b50612e4681600080516020614ee083398151915255565b612e4f30613794565b6040516000808252908190600080516020614f2a8339815191529060200160405180910390a36040516001600160a01b038216906000907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f908290a350505050505050565b6000612ede7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b031603612f345760405162461bcd60e51b815260206004820152601d60248201527f5555505350726f786961626c653a206e6f742075706772616461626c6500000060448201526064016113e9565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f969190614a56565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb0019146130105760405162461bcd60e51b815260206004820152602360248201527f5555505350726f786961626c653a206e6f7420636f6d70617469626c65206c6f60448201526267696360e81b60648201526084016113e9565b6001600160a01b03811630036130685760405162461bcd60e51b815260206004820152601960248201527f5555505350726f786961626c653a2070726f7879206c6f6f700000000000000060448201526064016113e9565b613090817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fe011bc04c286c344a8fcbb8de77f953da762c3e25d8cdea984147fc4168a5dcc7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb0019604080519182526001600160a01b038416602083015201611c9b565b6060816001600160401b03811115613108576131086141e5565b604051908082528060200260200182016040528015613131578160200160208202803683370190505b50905060005b8281101561316e5760008185015490508083838151811061315a5761315a614bac565b602090810291909101015250600101613137565b5092915050565b6000816001600160a01b0316836001600160a01b031614806131e457506001600160a01b038316600090815260018501602052604090205460ff1680156131e457506001600160a01b03808316600090815260038601602090815260408083209387168352929052205460ff16155b806110b357506001600160a01b03808316600090815260028601602090815260408083209387168352929052205460ff1690509392505050565b6001600160a01b0386166132455760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b03851661326c5760405163e219bd3960e01b815260040160405180910390fd5b61327a8787878787876138c2565b6132888787878787876136bd565b61146b878787878787876139e9565b806001600160a01b0316826001600160a01b03160361330e5760405162461bcd60e51b815260206004820152602d60248201527f4552433737374f70657261746f72733a20617574686f72697a696e672073656c60448201526c331030b99037b832b930ba37b960991b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff1615613364576001600160a01b03918216600090815260039390930160209081526040808520929093168452529020805460ff19169055565b6001600160a01b0380831660009081526002850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b0385166133c257604051632e8aac6160e21b815260040160405180910390fd5b82156133d7576133d7868660008786866138c2565b6133e18585613b39565b846001600160a01b0316866001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a409886858560405161342893929190614e3e565b60405180910390a36040518481526000906001600160a01b03871690600080516020614f2a833981519152906020015b60405180910390a3505050505050565b6000818484111561348c5760405162461bcd60e51b81526004016113e99190614036565b505050900390565b6001600160a01b0386166134bb57604051630d24315760e01b815260040160405180910390fd5b6134c58686613c49565b83156134db576134db87600088888686896139e9565b856001600160a01b0316876001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d87858560405161352293929190614e3e565b60405180910390a36040518581526001600160a01b03871690600090600080516020614f2a8339815191529060200160405180910390a350505050505050565b336001600160a01b038216036135cd5760405162461bcd60e51b815260206004820152602a60248201527f4552433737374f70657261746f72733a207265766f6b696e672073656c662061604482015269399037b832b930ba37b960b11b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff1615613627576001600160a01b0380831660009081526003850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b03918216600090815260029390930160209081526040808520929093168452529020805460ff19169055565b6040516001600160a01b0383166024820152604481018290526110a090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613ca3565b6136d085856136cb86612af6565b613d78565b836001600160a01b0316856001600160a01b0316876001600160a01b03167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc8261467798786868660405161372193929190614e3e565b60405180910390a4836001600160a01b0316856001600160a01b0316600080516020614f2a8339815191528560405161345891815260200190565b6040516001600160a01b03808516602483015283166044820152606481018290526118319085906323b872dd60e01b90608401613686565b6040516329965a1d60e01b81526001600160a01b03821660048201527fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce21770546024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b15801561381557600080fd5b505af1158015613829573d6000803e3d6000fd5b50506040516329965a1d60e01b81526001600160a01b03841660048201527faea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a6024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b1580156138ae57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b60405163555ddc6560e11b81526001600160a01b03861660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa158015613943573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139679190614b7c565b90506001600160a01b0381161561146b57604051633ad5cbc160e11b81526001600160a01b038216906375ab9782906139ae908a908a908a908a908a908a90600401614e69565b600060405180830381600087803b1580156139c857600080fd5b505af11580156139dc573d6000803e3d6000fd5b5050505050505050505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa158015613a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a8e9190614b7c565b90506001600160a01b03811615613b0a576040516223de2960e01b81526001600160a01b038216906223de2990613ad3908b908b908b908b908b908b90600401614e69565b600060405180830381600087803b158015613aed57600080fd5b505af1158015613b01573d6000803e3d6000fd5b5050505061192f565b811561192f576001600160a01b0386163b1561192f5760405163fe737d0560e01b815260040160405180910390fd5b6000613bc1837f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b9d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109529190614a56565b50509050613bce82612af6565b811215613bee5760405163043b37d160e21b815260040160405180910390fd5b613bf782612af6565b6001600160a01b038416600090815260026020526040902054613c1a9190614a03565b6001600160a01b038416600090815260026020526040902055600354613c41908390614b99565b600355505050565b613c5281612af6565b6001600160a01b038316600090815260026020526040902054613c7591906149db565b6001600160a01b038316600090815260026020526040902055600354613c9c908290614b1b565b6003555050565b6000613cf8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e779092919063ffffffff16565b9050805160001480613d19575080806020019051810190613d199190614976565b6110a05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016113e9565b6000613ddc847f0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe76001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b9d573d6000803e3d6000fd5b5050905081811215613e0157604051632f4cb94160e01b815260040160405180910390fd5b6001600160a01b038416600090815260026020526040902054613e25908390614a03565b6001600160a01b038086166000908152600260205260408082209390935590851681522054613e559083906149db565b6001600160a01b03909316600090815260026020526040902092909255505050565b60606110b3848460008585600080866001600160a01b03168587604051613e9e9190614ec3565b60006040518083038185875af1925050503d8060008114613edb576040519150601f19603f3d011682016040523d82523d6000602084013e613ee0565b606091505b5091509150613ef187838387613efc565b979650505050505050565b60608315613f6b578251600003613f64576001600160a01b0385163b613f645760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016113e9565b50816110b3565b6110b38383815115613f805781518083602001fd5b8060405162461bcd60e51b81526004016113e99190614036565b602080825282518282018190526000918401906040840190835b81811015613fdb5783516001600160a01b0316835260209384019390920191600101613fb4565b509095945050505050565b60005b83811015614001578181015183820152602001613fe9565b50506000910152565b60008151808452614022816020860160208601613fe6565b601f01601f19169290920160200192915050565b6020815260006119d5602083018461400a565b6001600160a01b0381168114610bb657600080fd5b60008083601f84011261407057600080fd5b5081356001600160401b0381111561408757600080fd5b6020830191508360208260051b85010111156140a257600080fd5b9250929050565b600080600080606085870312156140bf57600080fd5b84356140ca81614049565b93506020850135925060408501356001600160401b038111156140ec57600080fd5b6140f88782880161405e565b95989497509550505050565b6000806040838503121561411757600080fd5b823561412281614049565b946020939093013593505050565b60006020828403121561414257600080fd5b5035919050565b60008060006040848603121561415e57600080fd5b8335925060208401356001600160401b0381111561417b57600080fd5b6141878682870161405e565b9497909650939450505050565b600080600080608085870312156141aa57600080fd5b84356141b581614049565b935060208501356141c581614049565b925060408501356141d581614049565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715614223576142236141e5565b604052919050565b600082601f83011261423c57600080fd5b81356001600160401b03811115614255576142556141e5565b614268601f8201601f19166020016141fb565b81815284602083860101111561427d57600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114610bb657600080fd5b600080600080600080600060e0888a0312156142c357600080fd5b8735965060208801356001600160401b038111156142e057600080fd5b6142ec8a828b0161422b565b96505060408801356142fd81614049565b9450606088013561430d8161429a565b9350608088013561431d81614049565b9699959850939692959460a0840135945060c09093013592915050565b60008060006060848603121561434f57600080fd5b833561435a81614049565b9250602084013561436a81614049565b929592945050506040919091013590565b6000806040838503121561438e57600080fd5b50508035926020909101359150565b6000602082840312156143af57600080fd5b81356119d581614049565b803560ff811681146143cb57600080fd5b919050565b60008083601f8401126143e257600080fd5b5081356001600160401b038111156143f957600080fd5b6020830191508360208285010111156140a257600080fd5b6000806000806000806080878903121561442a57600080fd5b863561443581614049565b9550614443602088016143ba565b945060408701356001600160401b0381111561445e57600080fd5b61446a89828a016143d0565b90955093505060608701356001600160401b0381111561448957600080fd5b61449589828a016143d0565b979a9699509497509295939492505050565b600080600080608085870312156144bd57600080fd5b84356144c881614049565b935060208501356144d881614049565b93969395505050506040820135916060013590565b602080825282518282018190526000918401906040840190835b81811015613fdb578351835260209384019390920191600101614507565b6000806000806060858703121561453b57600080fd5b843561454681614049565b93506020850135925060408501356001600160401b0381111561456857600080fd5b6140f8878288016143d0565b600080600080600080600060a0888a03121561458f57600080fd5b873561459a81614049565b965060208801356145aa81614049565b95506040880135945060608801356001600160401b038111156145cc57600080fd5b6145d88a828b016143d0565b90955093505060808801356001600160401b038111156145f757600080fd5b6146038a828b016143d0565b989b979a50959850939692959293505050565b60008060006060848603121561462b57600080fd5b833561463681614049565b95602085013595506040909401359392505050565b60008060006060848603121561466057600080fd5b833561466b81614049565b92506020840135915060408401356001600160401b0381111561468d57600080fd5b6146998682870161422b565b9150509250925092565b600080600080608085870312156146b957600080fd5b84356146c481614049565b935060208501356146d481614049565b92506040850135915060608501356001600160401b038111156146f657600080fd5b6147028782880161422b565b91505092959194509250565b6000806040838503121561472157600080fd5b823561472c81614049565b9150602083013561473c81614049565b809150509250929050565b600080600080600080600060a0888a03121561476257600080fd5b873561476d81614049565b965061477b602089016143ba565b955060408801356001600160401b0381111561479657600080fd5b6147a28a828b016143d0565b90965094505060608801356001600160401b038111156147c157600080fd5b6147cd8a828b016143d0565b90945092505060808801356147e181614049565b8091505092959891949750929550565b6000806000806000806080878903121561480a57600080fd5b863561481581614049565b95506020870135945060408701356001600160401b0381111561445e57600080fd5b60008060006040848603121561484c57600080fd5b8335925060208401356001600160401b0381111561486957600080fd5b614187868287016143d0565b600181811c9082168061488957607f821691505b6020821081036148a957634e487b7160e01b600052602260045260246000fd5b50919050565b6080808252600e908201526d41677265656d656e74537461746560901b60a08201526001600160a01b039384166020820152919092166040820152606081019190915260c00190565b6060808252600d908201526c41677265656d656e744461746160981b60808201526001600160a01b03929092166020830152604082015260a00190565b838152604060208201819052810182905260006001600160fb1b0383111561495c57600080fd5b8260051b8085606085013791909101606001949350505050565b60006020828403121561498857600080fd5b81516119d58161429a565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b82016149be576149be614993565b5060000390565b634e487b7160e01b600052600160045260246000fd5b80820182811260008312801582168215821617156149fb576149fb614993565b505092915050565b818103600083128015838313168383128216171561316e5761316e614993565b85815260018060a01b038516602082015283604082015282606082015260a060808201526000613ef160a083018461400a565b600060208284031215614a6857600080fd5b5051919050565b600060208284031215614a8157600080fd5b81516001600160401b03811115614a9757600080fd5b8201601f81018413614aa857600080fd5b80516001600160401b03811115614ac157614ac16141e5565b8060051b614ad1602082016141fb565b91825260208184018101929081019087841115614aed57600080fd5b6020850194505b83851015613ef15784519250614b0983614049565b82825260209485019490910190614af4565b80820180821115610b8457610b84614993565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b600060208284031215614b8e57600080fd5b81516119d581614049565b81810381811115610b8457610b84614993565b634e487b7160e01b600052603260045260246000fd5b600080600060608486031215614bd757600080fd5b5050815160208301516040909301519094929350919050565b60ff8281168282160390811115610b8457610b84614993565b6001815b6001841115614c4457808504811115614c2857614c28614993565b6001841615614c3657908102905b60019390931c928002614c0d565b935093915050565b600082614c5b57506001610b84565b81614c6857506000610b84565b8160018114614c7e5760028114614c8857614ca4565b6001915050610b84565b60ff841115614c9957614c99614993565b50506001821b610b84565b5060208310610133831016604e8410600b8410161715614cc7575081810a610b84565b614cd46000198484614c09565b8060001904821115614ce857614ce8614993565b029392505050565b60006119d560ff841683614c4c565b600082614d1c57634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610b8457610b84614993565b601f8211156110a057806000526020600020601f840160051c81016020851015614d5f5750805b601f840160051c820191505b81811015610cf15760008155600101614d6b565b6001600160401b03831115614d9657614d966141e5565b614daa83614da48354614875565b83614d38565b6000601f841160018114614dde5760008515614dc65750838201355b600019600387901b1c1916600186901b178355610cf1565b600083815260209020601f19861690835b82811015614e0f5786850135825560209485019460019092019101614def565b5086821015614e2c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b838152606060208201526000614e57606083018561400a565b82810360408401526117ac818561400a565b6001600160a01b0387811682528681166020830152851660408201526060810184905260c060808201819052600090614ea49083018561400a565b82810360a0840152614eb6818561400a565b9998505050505050505050565b60008251614ed5818460208701613fe6565b919091019291505056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035375706572546f6b656e3a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5375706572546f6b656e3a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365a2646970667358221220519e9e812043dd9a3636890af9dde938734418c6c5ae526cb7acfedbb3e1313364736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe7000000000000000000000000fc00dee8a980110c5608a823a5b3af38726354560000000000000000000000001497440b4e92dc4ca0f76223b28c20cb9cb8a0f1000000000000000000000000a4806df890e5212c2879628b4c3b07341f881ed50000000000000000000000004821ef52bd6c822c079340b8c11eae1062ff13c2
-----Decoded View---------------
Arg [0] : host (address): 0x2dFe937cD98Ab92e59cF3139138f18c823a4efE7
Arg [1] : constantOutflowNFT (address): 0xfC00dEE8a980110c5608A823a5B3af3872635456
Arg [2] : constantInflowNFT (address): 0x1497440B4E92DC4ca0F76223b28C20Cb9cB8a0f1
Arg [3] : poolAdminNFT (address): 0xA4806Df890e5212c2879628B4c3B07341F881ed5
Arg [4] : poolMemberNFT (address): 0x4821Ef52bD6C822C079340b8C11EaE1062fF13c2
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000002dfe937cd98ab92e59cf3139138f18c823a4efe7
Arg [1] : 000000000000000000000000fc00dee8a980110c5608a823a5b3af3872635456
Arg [2] : 0000000000000000000000001497440b4e92dc4ca0f76223b28c20cb9cb8a0f1
Arg [3] : 000000000000000000000000a4806df890e5212c2879628b4c3b07341f881ed5
Arg [4] : 0000000000000000000000004821ef52bd6c822c079340b8c11eae1062ff13c2
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
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.