Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
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,
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";
// placeholder types needed as an intermediate step before complete removal of FlowNFTs
// solhint-disable-next-line no-empty-blocks
interface IConstantOutflowNFT {}
// solhint-disable-next-line no-empty-blocks
interface IConstantInflowNFT {}
/**
* @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 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);
}
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 { 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 { 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 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;
/**
* @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;
/**
* @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":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
61012060405234801561001157600080fd5b5060405161507d38038061507d833981016040819052610030916100d8565b6001600160a01b0380861660805284811660a05283811660c05282811661010081905290821660e0526040517feb87fb34067547f3dc0b85096c3da73c99d4fbb08ff41212b8d7c0b5008b42e690600090a26040516001600160a01b038216907fc1050c54a299c837fe281a2623c29ec8e34b455daef48760b6a29f4b6cc9906090600090a2505050505061014d565b6001600160a01b03811681146100d557600080fd5b50565b600080600080600060a086880312156100f057600080fd5b85516100fb816100c0565b602087015190955061010c816100c0565b604087015190945061011d816100c0565b606087015190935061012e816100c0565b608087015190925061013f816100c0565b809150509295509295909350565b60805160a05160c05160e05161010051614e59610224600039600061083e015260006109c2015260006106880152600061099b0152600081816104ea01528181610c9e01528181610d0d0152818161102d015281816110bd015281816111ed015281816112bc015281816114d3015281816115290152818161159e015281816116e6015281816118910152818161197001528181611d6101528181611e2b01528181611ec301528181611f2b01528181611fb301528181612863015281816128fa015281816139ee0152613c2d0152614e596000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80636c2d9f2f11610220578063b84cdd4a11610130578063dd62ed3e116100b8578063ef43d2c611610087578063ef43d2c614610996578063f5a8b4dd146109bd578063fad8b32a146109e4578063fc673c4f146109f7578063fe9d930314610a0a57600080fd5b8063dd62ed3e1461090b578063eb3537cc14610944578063ec0d634314610972578063ee719bc81461098557600080fd5b8063ca0c1e7f116100ff578063ca0c1e7f146108ac578063ca789464146108bf578063cf97256d146108d2578063d95b6371146108e5578063d9d078d6146108f857600080fd5b8063b84cdd4a14610860578063bb0d196e14610873578063c68d428314610886578063c780fd821461089957600080fd5b806395d89b41116101b3578063a1b2bf8b11610182578063a1b2bf8b146107ed578063a3a7e7f314610800578063a457c2d714610813578063a9059cbb14610826578063b20db1ac1461083957600080fd5b806395d89b41146107b75780639903ad38146107bf5780639bd9bbc6146107c75780639d876741146107da57600080fd5b806383ba2525116101ef57806383ba25251461076c5780638f2839701461077f57806392081a4714610792578063959b8c3f146107a457600080fd5b80636c2d9f2f1461072b5780636e9960c31461073e57806370a082311461074657806379359f6f1461075957600080fd5b8063386fa2211161031b5780634b61cc33116102ae578063556f0dc71161027d578063556f0dc7146106d85780635b9d09cc146106df57806362aa5287146106f257806362ad1b831461070557806366a12fb61461071857600080fd5b80634b61cc33146106635780634c5c0c851461068357806350d75d25146106aa57806352d1902d146106b257600080fd5b806345977d03116102ea57806345977d0314610617578063469519541461062a57806347ba7ad11461063d5780634b2763b31461065057600080fd5b8063386fa221146105cb57806339509351146105de57806341b706be146105f157806342fe09801461060457600080fd5b80631863e8091161039e578063245887fc1161036d578063245887fc146105355780632704839714610548578063282a050b1461055b5780632ec8eec714610583578063313ce567146105b657600080fd5b80631863e809146104c25780631ae88ffc146104d557806320bc4425146104e857806323b872dd1461052257600080fd5b806311bcc81e116103da57806311bcc81e1461047757806312a6a3f81461048a57806316d055d61461049d57806318160ddd146104b057600080fd5b806306e485381461040c57806306fdde031461042a578063090c415e1461043f578063095ea7b314610454575b600080fd5b610414610a1d565b6040516104219190613e47565b60405180910390f35b610432610a2e565b6040516104219190613ee3565b61045261044d366004613f56565b610ac0565b005b610467610462366004613fb1565b610b73565b6040519015158152602001610421565b610452610485366004613fdd565b610b8a565b610452610498366004613ff6565b610bb9565b6104526104ab366004614041565b610c9c565b6003545b604051908152602001610421565b6104526104d0366004614155565b610cf8565b6104526104e33660046141e7565b61102b565b7f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610421565b6104676105303660046141e7565b6110a5565b610452610543366004613fb1565b6110bb565b610452610556366004614228565b611134565b61056e610569366004613fdd565b6111d0565b60408051928352602083019190915201610421565b61059661059136600461424a565b6111e5565b604080519485526020850193909352918301526060820152608001610421565b60125b60405160ff9091168152602001610421565b6104146105d936600461424a565b611288565b6104676105ec366004613fb1565b61132b565b6104526105ff366004614041565b611367565b6104526106123660046142be565b611393565b610452610625366004613fdd565b611474565b61045261063836600461424a565b6114a0565b61045261064b3660046141e7565b611527565b61045261065e3660046141e7565b61159c565b610676610671366004614354565b61161e565b604051610421919061439a565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b61050a611663565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb00196104b4565b60016104b4565b6104526106ed3660046143d2565b61168d565b6104526107003660046141e7565b6116e4565b610452610713366004614421565b611738565b6104526107263660046141e7565b6117e6565b6106766107393660046144c3565b611806565b61050a611848565b6104b461075436600461424a565b611860565b61046761076736600461424a565b611889565b61045261077a366004613fb1565b611911565b61045261078d36600461424a565b61193d565b600e54600160a01b900460ff166105b9565b6104526107b236600461424a565b611a31565b610432611a82565b610452611a91565b6104526107d53660046143d2565b611b53565b6104526107e83660046144f8565b611ba7565b6104526107fb366004613ff6565b611bed565b61045261080e36600461424a565b611c97565b610467610821366004613fb1565b611cab565b610467610834366004613fb1565b611cfa565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b61046761086e366004613fb1565b611d08565b61046761088136600461424a565b611d59565b6104526108943660046144f8565b611de1565b6104526108a73660046141e7565b611e29565b6104526108ba366004614550565b611ec1565b6104526108cd366004613fb1565b611f29565b6104526108e0366004613fb1565b611f9e565b6104676108f33660046145bb565b612087565b610467610906366004613fb1565b612095565b6104b46109193660046145bb565b6001600160a01b03918216600090815260116020908152604080832093909416825291909152205490565b610957610952366004613fb1565b6120af565b60408051938452602084019290925290820152606001610421565b6104526109803660046145f4565b6121e3565b600e546001600160a01b031661050a565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b61050a7f000000000000000000000000000000000000000000000000000000000000000081565b6104526109f236600461424a565b6122ba565b610452610a0536600461469e565b61230b565b610452610a183660046146e4565b6123ac565b6060610a2960126123fd565b905090565b6060600f8054610a3d90614722565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6990614722565b8015610ab65780601f10610a8b57610100808354040283529160200191610ab6565b820191906000526020600020905b815481529060010190602001808311610a9957829003601f168201915b5050505050905090565b6000338585604051602001610ad79392919061475c565b604051602081830303815290604052805190602001209050610b2c8184848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061246392505050565b6040518481526001600160a01b0386169033907f30f416fa68fca014a0f334464c64b000ba53e99b6d2afdea9d5ca756372d59859060200160405180910390a35050505050565b6000610b8033848461249b565b5060015b92915050565b610bb633333384604051806020016040528060008152506040518060200160405280600081525061254a565b50565b6040513390600090610bd190839087906020016147a5565b60408051601f1981840301815291905280516020909101209050610bf5818461270a565b15610c135760405163782a90fb60e11b815260040160405180910390fd5b610c508185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061246392505050565b816001600160a01b03167f770ea40a13a4644573ed785e5c7116890709947918747febc5add46feb531e2d868686604051610c8d939291906147e2565b60405180910390a25050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314610ce55760405163c51efddd60e01b815260040160405180910390fd5b610cf18484848461273e565b5050505050565b604051632329212160e21b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638ca4848490602401602060405180830381865afa158015610d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d809190614823565b610d9d5760405163327fd99160e21b815260040160405180910390fd5b6000610da761285e565b90506001600160a01b038116610dba5750845b600085610dc75786610dc9565b815b905060008313610e9757610ddc83614856565b610de5856129a3565b14610df257610df2614872565b610dfb846129a3565b6001600160a01b03821660009081526002602052604081208054909190610e23908490614888565b90915550506001600160a01b03851660009081526002602052604081208054859290610e50908490614888565b92505081905550806001600160a01b0316856001600160a01b0316600080516020614dd783398151915286604051610e8a91815260200190565b60405180910390a3610fc3565b8515610ea557610ea5614872565b82610eaf856129a3565b610eb99190614888565b6001600160a01b03831660009081526002602052604081208054909190610ee19084906148b0565b90915550610ef09050846129a3565b6001600160a01b03881660009081526002602052604081208054909190610f18908490614888565b90915550506001600160a01b03851660009081526002602052604081208054859290610f45908490614888565b92505081905550866001600160a01b0316826001600160a01b0316600080516020614dd783398151915286604051610f7f91815260200190565b60405180910390a3846001600160a01b0316826001600160a01b0316600080516020614dd783398151915285604051610fba91815260200190565b60405180910390a35b846001600160a01b0316876001600160a01b0316336001600160a01b03167fb8381a3ce157650e06186e3e8f4dd4dc29236f2688b6eed1893d0a60d7c6386f8c8589898f6040516110189594939291906148d0565b60405180910390a4505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146110745760405163c51efddd60e01b815260040160405180910390fd5b6110a0338484846040518060200160405280600081525060405180602001604052806000815250612a11565b505050565b60006110b33385858561273e565b949350505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146111045760405163c51efddd60e01b815260040160405180910390fd5b61113033838484604051806020016040528060008152506040518060200160405280600081525061254a565b5050565b604051339060009061114c90839086906020016147a5565b60405160208183030381529060405280519060200120905061116e818461270a565b61118b5760405163dae1880960e01b815260040160405180910390fd5b6111958184612bc4565b60405184815233907f71a63dc095de07aa5512ad57a7596a39516317e316981a1cd71000057be1537b9060200160405180910390a250505050565b6000806111dc83612bdd565b91509150915091565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190614903565b905061127985826120af565b91979096509094509092509050565b6001600160a01b038181166000908152600160205260409081902054905163c56a069d60e01b8152901960048201526060917f0000000000000000000000000000000000000000000000000000000000000000169063c56a069d90602401600060405180830381865afa158015611303573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b84919081019061491c565b3360008181526011602090815260408083206001600160a01b03871684529091528120549091610b809185906113629086906149c8565b61249b565b33301461138757604051630fff4cc960e31b815260040160405180910390fd5b610cf18385848461273e565b600054610100900460ff16158080156113b35750600054600160ff909116105b806113cd5750303b1580156113cd575060005460ff166001145b6113f25760405162461bcd60e51b81526004016113e9906149db565b60405180910390fd5b6000805460ff191660011790558015611415576000805461ff0019166101001790555b6114258787878787876000612c99565b801561146b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b610bb6333333846040518060200160405280600081525060405180602001604052806000815250612a11565b60006114b8600080516020614d8d8339815191525490565b905060006001600160a01b038216156114d157816114f3565b7f00000000000000000000000000000000000000000000000000000000000000005b9050336001600160a01b0382161461151e57604051630484acab60e01b815260040160405180910390fd5b6110a083612d61565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146115705760405163c51efddd60e01b815260040160405180910390fd5b6110a033848484604051806020016040528060008152506040518060200160405280600081525061254a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633146115e55760405163c51efddd60e01b815260040160405180910390fd5b6001600160a01b038084166000908152601160209081526040808320938616835292905220546110a090849084906113629085906149c8565b606060008585856040516020016116379392919061475c565b6040516020818303038152906040528051906020012090506116598184612f9b565b9695505050505050565b6000610a297f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6116de3333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250612a11915050565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316331461172d5760405163c51efddd60e01b815260040160405180910390fd5b6110a083838361249b565b336117456012828a613022565b6117625760405163f7f0222760e01b815260040160405180910390fd5b6117dc8189898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600092019190915250600192506130cb915050565b5050505050505050565b33301461172d57604051630fff4cc960e31b815260040160405180910390fd5b60606000848460405160200161181d9291906147a5565b60405160208183030381529060405280519060200120905061183f8184612f9b565b95945050505050565b6000610a29600080516020614d8d8339815191525490565b60008061186c836111e5565b50505090506000811261187f5780611882565b60005b9392505050565b6000610b84827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614903565b61113033338484604051806020016040528060008152506040518060200160405280600081525061254a565b6000611955600080516020614d8d8339815191525490565b905060006001600160a01b0382161561196e5781611990565b7f00000000000000000000000000000000000000000000000000000000000000005b9050336001600160a01b038216146119bb57604051630484acab60e01b815260040160405180910390fd5b60006119d3600080516020614d8d8339815191525490565b90506119eb84600080516020614d8d83398151915255565b836001600160a01b0316816001600160a01b03167f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f60405160405180910390a350505050565b33611a3e60128284613144565b806001600160a01b0316826001600160a01b03167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a35050565b606060108054610a3d90614722565b600054610100900460ff1615808015611ab15750600054600160ff909116105b80611acb5750303b158015611acb575060005460ff166001145b611ae75760405162461bcd60e51b81526004016113e9906149db565b6000805460ff191660011790558015611b0a576000805461ff0019166101001790555b8015610bb6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b6116de3333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250600191506130cb9050565b333014611bc757604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a091339186918691901515908690613248565b6040513390600090611c0590839087906020016147a5565b604051602081830303815290604052805190602001209050611c5a8185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061246392505050565b336001600160a01b03167f0c4c547b3a4fcaa5be8353b3111472b124155bccc86de811d4a481c9e6e9faca868686604051610c8d939291906147e2565b611130333383611ca633611860565b61273e565b6000610b803384611362856040518060600160405280602a8152602001614dad602a91393360009081526011602090815260408083206001600160a01b038d1684529091529020549190613315565b60006118823333858561273e565b600080600080611d1886866120af565b9250925092506000611d40828411611d315760006129a3565b611d3b8385614a29565b6129a3565b611d4a9085614888565b60001315979650505050505050565b6000610b84827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dbd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190614903565b333014611e0157604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a0913391869186919015159081908790613341565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314611e725760405163c51efddd60e01b815260040160405180910390fd5b6110a08383611362846040518060600160405280602a8152602001614dad602a91396001600160a01b03808a166000908152601160209081526040808320938c16835292905220549190613315565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314611f0a5760405163c51efddd60e01b815260040160405180910390fd5b6116de33858585856040518060200160405280600081525060016130cb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163314611f725760405163c51efddd60e01b815260040160405180910390fd5b611130338384846040518060200160405280600081525060405180602001604052806000815250612a11565b604051632329212160e21b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690638ca4848490602401602060405180830381865afa158015612002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120269190614823565b6120435760405163327fd99160e21b815260040160405180910390fd5b6001600160a01b038216600090815260026020526040902054612067908290614888565b6001600160a01b0390921660009081526002602052604090209190915550565b600061188260128484613022565b6000806120a284846120af565b5050600013949350505050565b6001600160a01b0382166000908152600260205260408120549080806120d486611288565b905060005b81518110156121da5760008060008484815181106120f9576120f9614a3c565b60209081029190910101516040516326cb922f60e21b81523060048201526001600160a01b038c81166024830152604482018c905290911690639b2e48bc90606401606060405180830381865afa158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c9190614a52565b9194509250905061218d82886149c8565b965061219981876149c8565b95506121b68183116121ac5760006129a3565b611d3b8284614a29565b6121c0848a614888565b6121ca91906148b0565b97505050508060010190506120d9565b50509250925092565b600054610100900460ff16158080156122035750600054600160ff909116105b8061221d5750303b15801561221d575060005460ff166001145b6122395760405162461bcd60e51b81526004016113e9906149db565b6000805460ff19166001179055801561225c576000805461ff0019166101001790555b61226b88888888888888612c99565b80156117dc576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050565b336122c76012828461340f565b806001600160a01b0316826001600160a01b03167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a35050565b3361231860128289613022565b6123355760405163f7f0222760e01b815260040160405180910390fd5b61146b8188898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525061254a92505050565b6110a03333338686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805160208101909152908152925061254a915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561245757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612439575b50505050509050919050565b60005b81518110156110a057600082828151811061248357612483614a3c565b60209081029190910101518483015550600101612466565b6001600160a01b0383166124c257604051638163862760e01b815260040160405180910390fd5b6001600160a01b0382166124e9576040516337c1c09d60e21b815260040160405180910390fd5b6001600160a01b0383811660008181526011602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600e546001600160a01b031661257357604051637bce7b2b60e11b815260040160405180910390fd5b60008061257f85612bdd565b915091506125968888838751600014158888613248565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156125df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126039190614903565b600e5490915061261d906001600160a01b03168885613507565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268a9190614903565b905060006126988284614a29565b90508085146126ba57604051631c7c26d360e31b815260040160405180910390fd5b896001600160a01b03167f3bc27981aebbb57f9247dc00fde9d6cd91e4b230083fec3238fedbcba1f9ab3d856040516126f591815260200190565b60405180910390a25050505050505050505050565b6000805b828110156127345783810154801561272b57600192505050610b84565b5060010161270e565b5060009392505050565b60006001600160a01b0384166127675760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b03831661278e5760405163e219bd3960e01b815260040160405180910390fd5b60003390506127bf81868686604051806020016040528060008152506040518060200160405280600081525061356a565b846001600160a01b0316866001600160a01b031614612852576128528587611362866040518060600160405280602d8152602001614df7602d9139601160008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020546133159092919063ffffffff16565b50600195945050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663289b3c0d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e39190614a80565b604051638369a0f160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301527f9f60ae461adf056670e03ae602566409933242392cb06744f5747c9f38b05d09604483015291925090821690638369a0f190606401602060405180830381865afa158015612979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299d9190614a80565b91505090565b60006001600160ff1b03821115612a0d5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016113e9565b5090565b600e546001600160a01b0316612a3a57604051637bce7b2b60e11b815260040160405180910390fd5b600080612a4685612bdd565b600e546040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612a97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abb9190614903565b600e54909150612ad6906001600160a01b0316893086613609565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190614903565b90506000612b518383614a29565b9050808514612b7357604051631c7c26d360e31b815260040160405180910390fd5b8651612b89908c908b9087901515808c8c613341565b886001600160a01b03167f25ca84076773b0455db53621c459ddc84fe40840e4932a62706a032566f399df856040516126f591815260200190565b60005b818110156110a057600083820155600101612bc7565b600e54600090819081906012600160a01b90910460ff161015612c3c57600e54612c1290600160a01b900460ff166012614a9d565b612c1d90600a614b9d565b9050612c298185614bac565b9250612c358184614bce565b9150612c93565b600e546012600160a01b90910460ff161115612c8c57600e54612c6b90601290600160a01b900460ff16614a9d565b612c7690600a614b9d565b9050612c828185614bce565b9250839150612c93565b8391508192505b50915091565b600e805460ff8816600160a01b026001600160a81b03199091166001600160a01b038a1617179055600f612cce858783614c2c565b506010612cdc838583614c2c565b50612cf381600080516020614d8d83398151915255565b612cfc30613641565b6040516000808252908190600080516020614dd78339815191529060200160405180910390a36040516001600160a01b038216906000907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f908290a350505050505050565b6000612d8b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b031603612de15760405162461bcd60e51b815260206004820152601d60248201527f5555505350726f786961626c653a206e6f742075706772616461626c6500000060448201526064016113e9565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e439190614903565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb001914612ebd5760405162461bcd60e51b815260206004820152602360248201527f5555505350726f786961626c653a206e6f7420636f6d70617469626c65206c6f60448201526267696360e81b60648201526084016113e9565b6001600160a01b0381163003612f155760405162461bcd60e51b815260206004820152601960248201527f5555505350726f786961626c653a2070726f7879206c6f6f700000000000000060448201526064016113e9565b612f3d817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fe011bc04c286c344a8fcbb8de77f953da762c3e25d8cdea984147fc4168a5dcc7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb0019604080519182526001600160a01b038416602083015201611b48565b6060816001600160401b03811115612fb557612fb5614092565b604051908082528060200260200182016040528015612fde578160200160208202803683370190505b50905060005b8281101561301b5760008185015490508083838151811061300757613007614a3c565b602090810291909101015250600101612fe4565b5092915050565b6000816001600160a01b0316836001600160a01b0316148061309157506001600160a01b038316600090815260018501602052604090205460ff16801561309157506001600160a01b03808316600090815260038601602090815260408083209387168352929052205460ff16155b806110b357506001600160a01b03808316600090815260028601602090815260408083209387168352929052205460ff1690509392505050565b6001600160a01b0386166130f25760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b0385166131195760405163e219bd3960e01b815260040160405180910390fd5b61312787878787878761376f565b61313587878787878761356a565b61146b87878787878787613896565b806001600160a01b0316826001600160a01b0316036131bb5760405162461bcd60e51b815260206004820152602d60248201527f4552433737374f70657261746f72733a20617574686f72697a696e672073656c60448201526c331030b99037b832b930ba37b960991b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff1615613211576001600160a01b03918216600090815260039390930160209081526040808520929093168452529020805460ff19169055565b6001600160a01b0380831660009081526002850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b03851661326f57604051632e8aac6160e21b815260040160405180910390fd5b8215613284576132848686600087868661376f565b61328e85856139e6565b846001600160a01b0316866001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a40988685856040516132d593929190614ceb565b60405180910390a36040518481526000906001600160a01b03871690600080516020614dd7833981519152906020015b60405180910390a3505050505050565b600081848411156133395760405162461bcd60e51b81526004016113e99190613ee3565b505050900390565b6001600160a01b03861661336857604051630d24315760e01b815260040160405180910390fd5b6133728686613af6565b8315613388576133888760008888868689613896565b856001600160a01b0316876001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d8785856040516133cf93929190614ceb565b60405180910390a36040518581526001600160a01b03871690600090600080516020614dd78339815191529060200160405180910390a350505050505050565b336001600160a01b0382160361347a5760405162461bcd60e51b815260206004820152602a60248201527f4552433737374f70657261746f72733a207265766f6b696e672073656c662061604482015269399037b832b930ba37b960b11b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff16156134d4576001600160a01b0380831660009081526003850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b03918216600090815260029390930160209081526040808520929093168452529020805460ff19169055565b6040516001600160a01b0383166024820152604481018290526110a090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613b50565b61357d8585613578866129a3565b613c25565b836001600160a01b0316856001600160a01b0316876001600160a01b03167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc826146779878686866040516135ce93929190614ceb565b60405180910390a4836001600160a01b0316856001600160a01b0316600080516020614dd78339815191528560405161330591815260200190565b6040516001600160a01b03808516602483015283166044820152606481018290526116de9085906323b872dd60e01b90608401613533565b6040516329965a1d60e01b81526001600160a01b03821660048201527fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce21770546024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b1580156136c257600080fd5b505af11580156136d6573d6000803e3d6000fd5b50506040516329965a1d60e01b81526001600160a01b03841660048201527faea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a6024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b15801561375b57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b60405163555ddc6560e11b81526001600160a01b03861660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa1580156137f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138149190614a80565b90506001600160a01b0381161561146b57604051633ad5cbc160e11b81526001600160a01b038216906375ab97829061385b908a908a908a908a908a908a90600401614d16565b600060405180830381600087803b15801561387557600080fd5b505af1158015613889573d6000803e3d6000fd5b5050505050505050505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa158015613917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061393b9190614a80565b90506001600160a01b038116156139b7576040516223de2960e01b81526001600160a01b038216906223de2990613980908b908b908b908b908b908b90600401614d16565b600060405180830381600087803b15801561399a57600080fd5b505af11580156139ae573d6000803e3d6000fd5b505050506117dc565b81156117dc576001600160a01b0386163b156117dc5760405163fe737d0560e01b815260040160405180910390fd5b6000613a6e837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a4a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109529190614903565b50509050613a7b826129a3565b811215613a9b5760405163043b37d160e21b815260040160405180910390fd5b613aa4826129a3565b6001600160a01b038416600090815260026020526040902054613ac791906148b0565b6001600160a01b038416600090815260026020526040902055600354613aee908390614a29565b600355505050565b613aff816129a3565b6001600160a01b038316600090815260026020526040902054613b229190614888565b6001600160a01b038316600090815260026020526040902055600354613b499082906149c8565b6003555050565b6000613ba5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613d249092919063ffffffff16565b9050805160001480613bc6575080806020019051810190613bc69190614823565b6110a05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016113e9565b6000613c89847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a4a573d6000803e3d6000fd5b5050905081811215613cae57604051632f4cb94160e01b815260040160405180910390fd5b6001600160a01b038416600090815260026020526040902054613cd29083906148b0565b6001600160a01b038086166000908152600260205260408082209390935590851681522054613d02908390614888565b6001600160a01b03909316600090815260026020526040902092909255505050565b60606110b3848460008585600080866001600160a01b03168587604051613d4b9190614d70565b60006040518083038185875af1925050503d8060008114613d88576040519150601f19603f3d011682016040523d82523d6000602084013e613d8d565b606091505b5091509150613d9e87838387613da9565b979650505050505050565b60608315613e18578251600003613e11576001600160a01b0385163b613e115760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016113e9565b50816110b3565b6110b38383815115613e2d5781518083602001fd5b8060405162461bcd60e51b81526004016113e99190613ee3565b602080825282518282018190526000918401906040840190835b81811015613e885783516001600160a01b0316835260209384019390920191600101613e61565b509095945050505050565b60005b83811015613eae578181015183820152602001613e96565b50506000910152565b60008151808452613ecf816020860160208601613e93565b601f01601f19169290920160200192915050565b6020815260006118826020830184613eb7565b6001600160a01b0381168114610bb657600080fd5b60008083601f840112613f1d57600080fd5b5081356001600160401b03811115613f3457600080fd5b6020830191508360208260051b8501011115613f4f57600080fd5b9250929050565b60008060008060608587031215613f6c57600080fd5b8435613f7781613ef6565b93506020850135925060408501356001600160401b03811115613f9957600080fd5b613fa587828801613f0b565b95989497509550505050565b60008060408385031215613fc457600080fd5b8235613fcf81613ef6565b946020939093013593505050565b600060208284031215613fef57600080fd5b5035919050565b60008060006040848603121561400b57600080fd5b8335925060208401356001600160401b0381111561402857600080fd5b61403486828701613f0b565b9497909650939450505050565b6000806000806080858703121561405757600080fd5b843561406281613ef6565b9350602085013561407281613ef6565b9250604085013561408281613ef6565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156140d0576140d0614092565b604052919050565b600082601f8301126140e957600080fd5b81356001600160401b0381111561410257614102614092565b614115601f8201601f19166020016140a8565b81815284602083860101111561412a57600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114610bb657600080fd5b600080600080600080600060e0888a03121561417057600080fd5b8735965060208801356001600160401b0381111561418d57600080fd5b6141998a828b016140d8565b96505060408801356141aa81613ef6565b945060608801356141ba81614147565b935060808801356141ca81613ef6565b9699959850939692959460a0840135945060c09093013592915050565b6000806000606084860312156141fc57600080fd5b833561420781613ef6565b9250602084013561421781613ef6565b929592945050506040919091013590565b6000806040838503121561423b57600080fd5b50508035926020909101359150565b60006020828403121561425c57600080fd5b813561188281613ef6565b803560ff8116811461427857600080fd5b919050565b60008083601f84011261428f57600080fd5b5081356001600160401b038111156142a657600080fd5b602083019150836020828501011115613f4f57600080fd5b600080600080600080608087890312156142d757600080fd5b86356142e281613ef6565b95506142f060208801614267565b945060408701356001600160401b0381111561430b57600080fd5b61431789828a0161427d565b90955093505060608701356001600160401b0381111561433657600080fd5b61434289828a0161427d565b979a9699509497509295939492505050565b6000806000806080858703121561436a57600080fd5b843561437581613ef6565b9350602085013561438581613ef6565b93969395505050506040820135916060013590565b602080825282518282018190526000918401906040840190835b81811015613e885783518352602093840193909201916001016143b4565b600080600080606085870312156143e857600080fd5b84356143f381613ef6565b93506020850135925060408501356001600160401b0381111561441557600080fd5b613fa58782880161427d565b600080600080600080600060a0888a03121561443c57600080fd5b873561444781613ef6565b9650602088013561445781613ef6565b95506040880135945060608801356001600160401b0381111561447957600080fd5b6144858a828b0161427d565b90955093505060808801356001600160401b038111156144a457600080fd5b6144b08a828b0161427d565b989b979a50959850939692959293505050565b6000806000606084860312156144d857600080fd5b83356144e381613ef6565b95602085013595506040909401359392505050565b60008060006060848603121561450d57600080fd5b833561451881613ef6565b92506020840135915060408401356001600160401b0381111561453a57600080fd5b614546868287016140d8565b9150509250925092565b6000806000806080858703121561456657600080fd5b843561457181613ef6565b9350602085013561458181613ef6565b92506040850135915060608501356001600160401b038111156145a357600080fd5b6145af878288016140d8565b91505092959194509250565b600080604083850312156145ce57600080fd5b82356145d981613ef6565b915060208301356145e981613ef6565b809150509250929050565b600080600080600080600060a0888a03121561460f57600080fd5b873561461a81613ef6565b965061462860208901614267565b955060408801356001600160401b0381111561464357600080fd5b61464f8a828b0161427d565b90965094505060608801356001600160401b0381111561466e57600080fd5b61467a8a828b0161427d565b909450925050608088013561468e81613ef6565b8091505092959891949750929550565b600080600080600080608087890312156146b757600080fd5b86356146c281613ef6565b95506020870135945060408701356001600160401b0381111561430b57600080fd5b6000806000604084860312156146f957600080fd5b8335925060208401356001600160401b0381111561471657600080fd5b6140348682870161427d565b600181811c9082168061473657607f821691505b60208210810361475657634e487b7160e01b600052602260045260246000fd5b50919050565b6080808252600e908201526d41677265656d656e74537461746560901b60a08201526001600160a01b039384166020820152919092166040820152606081019190915260c00190565b6060808252600d908201526c41677265656d656e744461746160981b60808201526001600160a01b03929092166020830152604082015260a00190565b838152604060208201819052810182905260006001600160fb1b0383111561480957600080fd5b8260051b8085606085013791909101606001949350505050565b60006020828403121561483557600080fd5b815161188281614147565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b820161486b5761486b614840565b5060000390565b634e487b7160e01b600052600160045260246000fd5b80820182811260008312801582168215821617156148a8576148a8614840565b505092915050565b818103600083128015838313168383128216171561301b5761301b614840565b85815260018060a01b038516602082015283604082015282606082015260a060808201526000613d9e60a0830184613eb7565b60006020828403121561491557600080fd5b5051919050565b60006020828403121561492e57600080fd5b81516001600160401b0381111561494457600080fd5b8201601f8101841361495557600080fd5b80516001600160401b0381111561496e5761496e614092565b8060051b61497e602082016140a8565b9182526020818401810192908101908784111561499a57600080fd5b6020850194505b83851015613d9e57845192506149b683613ef6565b828252602094850194909101906149a1565b80820180821115610b8457610b84614840565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b81810381811115610b8457610b84614840565b634e487b7160e01b600052603260045260246000fd5b600080600060608486031215614a6757600080fd5b5050815160208301516040909301519094929350919050565b600060208284031215614a9257600080fd5b815161188281613ef6565b60ff8281168282160390811115610b8457610b84614840565b6001815b6001841115614af157808504811115614ad557614ad5614840565b6001841615614ae357908102905b60019390931c928002614aba565b935093915050565b600082614b0857506001610b84565b81614b1557506000610b84565b8160018114614b2b5760028114614b3557614b51565b6001915050610b84565b60ff841115614b4657614b46614840565b50506001821b610b84565b5060208310610133831016604e8410600b8410161715614b74575081810a610b84565b614b816000198484614ab6565b8060001904821115614b9557614b95614840565b029392505050565b600061188260ff841683614af9565b600082614bc957634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610b8457610b84614840565b601f8211156110a057806000526020600020601f840160051c81016020851015614c0c5750805b601f840160051c820191505b81811015610cf15760008155600101614c18565b6001600160401b03831115614c4357614c43614092565b614c5783614c518354614722565b83614be5565b6000601f841160018114614c8b5760008515614c735750838201355b600019600387901b1c1916600186901b178355610cf1565b600083815260209020601f19861690835b82811015614cbc5786850135825560209485019460019092019101614c9c565b5086821015614cd95760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b838152606060208201526000614d046060830185613eb7565b82810360408401526116598185613eb7565b6001600160a01b0387811682528681166020830152851660408201526060810184905260c060808201819052600090614d5190830185613eb7565b82810360a0840152614d638185613eb7565b9998505050505050505050565b60008251614d82818460208701613e93565b919091019291505056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035375706572546f6b656e3a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5375706572546f6b656e3a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365a2646970667358221220051487297b37014853ca2bf6a1b68805b6deae9a7d985b17481256b57dd48a6e64736f6c634300081a0033000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192000000000000000000000000051e766e2d8dc65ae2bfcf084a50ad04476342270000000000000000000000000043d7c85c8b96a49a72a92c0b48cdc4720437d7000000000000000000000000a132a33bb6ed51085d376b3cc90c7723171ebb790000000000000000000000009dc144ba10c1d0ac64b36f409c70093c72300257
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104075760003560e01c80636c2d9f2f11610220578063b84cdd4a11610130578063dd62ed3e116100b8578063ef43d2c611610087578063ef43d2c614610996578063f5a8b4dd146109bd578063fad8b32a146109e4578063fc673c4f146109f7578063fe9d930314610a0a57600080fd5b8063dd62ed3e1461090b578063eb3537cc14610944578063ec0d634314610972578063ee719bc81461098557600080fd5b8063ca0c1e7f116100ff578063ca0c1e7f146108ac578063ca789464146108bf578063cf97256d146108d2578063d95b6371146108e5578063d9d078d6146108f857600080fd5b8063b84cdd4a14610860578063bb0d196e14610873578063c68d428314610886578063c780fd821461089957600080fd5b806395d89b41116101b3578063a1b2bf8b11610182578063a1b2bf8b146107ed578063a3a7e7f314610800578063a457c2d714610813578063a9059cbb14610826578063b20db1ac1461083957600080fd5b806395d89b41146107b75780639903ad38146107bf5780639bd9bbc6146107c75780639d876741146107da57600080fd5b806383ba2525116101ef57806383ba25251461076c5780638f2839701461077f57806392081a4714610792578063959b8c3f146107a457600080fd5b80636c2d9f2f1461072b5780636e9960c31461073e57806370a082311461074657806379359f6f1461075957600080fd5b8063386fa2211161031b5780634b61cc33116102ae578063556f0dc71161027d578063556f0dc7146106d85780635b9d09cc146106df57806362aa5287146106f257806362ad1b831461070557806366a12fb61461071857600080fd5b80634b61cc33146106635780634c5c0c851461068357806350d75d25146106aa57806352d1902d146106b257600080fd5b806345977d03116102ea57806345977d0314610617578063469519541461062a57806347ba7ad11461063d5780634b2763b31461065057600080fd5b8063386fa221146105cb57806339509351146105de57806341b706be146105f157806342fe09801461060457600080fd5b80631863e8091161039e578063245887fc1161036d578063245887fc146105355780632704839714610548578063282a050b1461055b5780632ec8eec714610583578063313ce567146105b657600080fd5b80631863e809146104c25780631ae88ffc146104d557806320bc4425146104e857806323b872dd1461052257600080fd5b806311bcc81e116103da57806311bcc81e1461047757806312a6a3f81461048a57806316d055d61461049d57806318160ddd146104b057600080fd5b806306e485381461040c57806306fdde031461042a578063090c415e1461043f578063095ea7b314610454575b600080fd5b610414610a1d565b6040516104219190613e47565b60405180910390f35b610432610a2e565b6040516104219190613ee3565b61045261044d366004613f56565b610ac0565b005b610467610462366004613fb1565b610b73565b6040519015158152602001610421565b610452610485366004613fdd565b610b8a565b610452610498366004613ff6565b610bb9565b6104526104ab366004614041565b610c9c565b6003545b604051908152602001610421565b6104526104d0366004614155565b610cf8565b6104526104e33660046141e7565b61102b565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21925b6040516001600160a01b039091168152602001610421565b6104676105303660046141e7565b6110a5565b610452610543366004613fb1565b6110bb565b610452610556366004614228565b611134565b61056e610569366004613fdd565b6111d0565b60408051928352602083019190915201610421565b61059661059136600461424a565b6111e5565b604080519485526020850193909352918301526060820152608001610421565b60125b60405160ff9091168152602001610421565b6104146105d936600461424a565b611288565b6104676105ec366004613fb1565b61132b565b6104526105ff366004614041565b611367565b6104526106123660046142be565b611393565b610452610625366004613fdd565b611474565b61045261063836600461424a565b6114a0565b61045261064b3660046141e7565b611527565b61045261065e3660046141e7565b61159c565b610676610671366004614354565b61161e565b604051610421919061439a565b61050a7f0000000000000000000000000043d7c85c8b96a49a72a92c0b48cdc4720437d781565b61050a611663565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb00196104b4565b60016104b4565b6104526106ed3660046143d2565b61168d565b6104526107003660046141e7565b6116e4565b610452610713366004614421565b611738565b6104526107263660046141e7565b6117e6565b6106766107393660046144c3565b611806565b61050a611848565b6104b461075436600461424a565b611860565b61046761076736600461424a565b611889565b61045261077a366004613fb1565b611911565b61045261078d36600461424a565b61193d565b600e54600160a01b900460ff166105b9565b6104526107b236600461424a565b611a31565b610432611a82565b610452611a91565b6104526107d53660046143d2565b611b53565b6104526107e83660046144f8565b611ba7565b6104526107fb366004613ff6565b611bed565b61045261080e36600461424a565b611c97565b610467610821366004613fb1565b611cab565b610467610834366004613fb1565b611cfa565b61050a7f000000000000000000000000a132a33bb6ed51085d376b3cc90c7723171ebb7981565b61046761086e366004613fb1565b611d08565b61046761088136600461424a565b611d59565b6104526108943660046144f8565b611de1565b6104526108a73660046141e7565b611e29565b6104526108ba366004614550565b611ec1565b6104526108cd366004613fb1565b611f29565b6104526108e0366004613fb1565b611f9e565b6104676108f33660046145bb565b612087565b610467610906366004613fb1565b612095565b6104b46109193660046145bb565b6001600160a01b03918216600090815260116020908152604080832093909416825291909152205490565b610957610952366004613fb1565b6120af565b60408051938452602084019290925290820152606001610421565b6104526109803660046145f4565b6121e3565b600e546001600160a01b031661050a565b61050a7f000000000000000000000000051e766e2d8dc65ae2bfcf084a50ad044763422781565b61050a7f0000000000000000000000009dc144ba10c1d0ac64b36f409c70093c7230025781565b6104526109f236600461424a565b6122ba565b610452610a0536600461469e565b61230b565b610452610a183660046146e4565b6123ac565b6060610a2960126123fd565b905090565b6060600f8054610a3d90614722565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6990614722565b8015610ab65780601f10610a8b57610100808354040283529160200191610ab6565b820191906000526020600020905b815481529060010190602001808311610a9957829003601f168201915b5050505050905090565b6000338585604051602001610ad79392919061475c565b604051602081830303815290604052805190602001209050610b2c8184848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061246392505050565b6040518481526001600160a01b0386169033907f30f416fa68fca014a0f334464c64b000ba53e99b6d2afdea9d5ca756372d59859060200160405180910390a35050505050565b6000610b8033848461249b565b5060015b92915050565b610bb633333384604051806020016040528060008152506040518060200160405280600081525061254a565b50565b6040513390600090610bd190839087906020016147a5565b60408051601f1981840301815291905280516020909101209050610bf5818461270a565b15610c135760405163782a90fb60e11b815260040160405180910390fd5b610c508185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061246392505050565b816001600160a01b03167f770ea40a13a4644573ed785e5c7116890709947918747febc5add46feb531e2d868686604051610c8d939291906147e2565b60405180910390a25050505050565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b03163314610ce55760405163c51efddd60e01b815260040160405180910390fd5b610cf18484848461273e565b5050505050565b604051632329212160e21b81523360048201527f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031690638ca4848490602401602060405180830381865afa158015610d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d809190614823565b610d9d5760405163327fd99160e21b815260040160405180910390fd5b6000610da761285e565b90506001600160a01b038116610dba5750845b600085610dc75786610dc9565b815b905060008313610e9757610ddc83614856565b610de5856129a3565b14610df257610df2614872565b610dfb846129a3565b6001600160a01b03821660009081526002602052604081208054909190610e23908490614888565b90915550506001600160a01b03851660009081526002602052604081208054859290610e50908490614888565b92505081905550806001600160a01b0316856001600160a01b0316600080516020614dd783398151915286604051610e8a91815260200190565b60405180910390a3610fc3565b8515610ea557610ea5614872565b82610eaf856129a3565b610eb99190614888565b6001600160a01b03831660009081526002602052604081208054909190610ee19084906148b0565b90915550610ef09050846129a3565b6001600160a01b03881660009081526002602052604081208054909190610f18908490614888565b90915550506001600160a01b03851660009081526002602052604081208054859290610f45908490614888565b92505081905550866001600160a01b0316826001600160a01b0316600080516020614dd783398151915286604051610f7f91815260200190565b60405180910390a3846001600160a01b0316826001600160a01b0316600080516020614dd783398151915285604051610fba91815260200190565b60405180910390a35b846001600160a01b0316876001600160a01b0316336001600160a01b03167fb8381a3ce157650e06186e3e8f4dd4dc29236f2688b6eed1893d0a60d7c6386f8c8589898f6040516110189594939291906148d0565b60405180910390a4505050505050505050565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031633146110745760405163c51efddd60e01b815260040160405180910390fd5b6110a0338484846040518060200160405280600081525060405180602001604052806000815250612a11565b505050565b60006110b33385858561273e565b949350505050565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031633146111045760405163c51efddd60e01b815260040160405180910390fd5b61113033838484604051806020016040528060008152506040518060200160405280600081525061254a565b5050565b604051339060009061114c90839086906020016147a5565b60405160208183030381529060405280519060200120905061116e818461270a565b61118b5760405163dae1880960e01b815260040160405180910390fd5b6111958184612bc4565b60405184815233907f71a63dc095de07aa5512ad57a7596a39516317e316981a1cd71000057be1537b9060200160405180910390a250505050565b6000806111dc83612bdd565b91509150915091565b6000806000807f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d9190614903565b905061127985826120af565b91979096509094509092509050565b6001600160a01b038181166000908152600160205260409081902054905163c56a069d60e01b8152901960048201526060917f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192169063c56a069d90602401600060405180830381865afa158015611303573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b84919081019061491c565b3360008181526011602090815260408083206001600160a01b03871684529091528120549091610b809185906113629086906149c8565b61249b565b33301461138757604051630fff4cc960e31b815260040160405180910390fd5b610cf18385848461273e565b600054610100900460ff16158080156113b35750600054600160ff909116105b806113cd5750303b1580156113cd575060005460ff166001145b6113f25760405162461bcd60e51b81526004016113e9906149db565b60405180910390fd5b6000805460ff191660011790558015611415576000805461ff0019166101001790555b6114258787878787876000612c99565b801561146b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b610bb6333333846040518060200160405280600081525060405180602001604052806000815250612a11565b60006114b8600080516020614d8d8339815191525490565b905060006001600160a01b038216156114d157816114f3565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21925b9050336001600160a01b0382161461151e57604051630484acab60e01b815260040160405180910390fd5b6110a083612d61565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031633146115705760405163c51efddd60e01b815260040160405180910390fd5b6110a033848484604051806020016040528060008152506040518060200160405280600081525061254a565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031633146115e55760405163c51efddd60e01b815260040160405180910390fd5b6001600160a01b038084166000908152601160209081526040808320938616835292905220546110a090849084906113629085906149c8565b606060008585856040516020016116379392919061475c565b6040516020818303038152906040528051906020012090506116598184612f9b565b9695505050505050565b6000610a297f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6116de3333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250612a11915050565b50505050565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b0316331461172d5760405163c51efddd60e01b815260040160405180910390fd5b6110a083838361249b565b336117456012828a613022565b6117625760405163f7f0222760e01b815260040160405180910390fd5b6117dc8189898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600092019190915250600192506130cb915050565b5050505050505050565b33301461172d57604051630fff4cc960e31b815260040160405180910390fd5b60606000848460405160200161181d9291906147a5565b60405160208183030381529060405280519060200120905061183f8184612f9b565b95945050505050565b6000610a29600080516020614d8d8339815191525490565b60008061186c836111e5565b50505090506000811261187f5780611882565b60005b9392505050565b6000610b84827f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190614903565b61113033338484604051806020016040528060008152506040518060200160405280600081525061254a565b6000611955600080516020614d8d8339815191525490565b905060006001600160a01b0382161561196e5781611990565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21925b9050336001600160a01b038216146119bb57604051630484acab60e01b815260040160405180910390fd5b60006119d3600080516020614d8d8339815191525490565b90506119eb84600080516020614d8d83398151915255565b836001600160a01b0316816001600160a01b03167f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f60405160405180910390a350505050565b33611a3e60128284613144565b806001600160a01b0316826001600160a01b03167ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f960405160405180910390a35050565b606060108054610a3d90614722565b600054610100900460ff1615808015611ab15750600054600160ff909116105b80611acb5750303b158015611acb575060005460ff166001145b611ae75760405162461bcd60e51b81526004016113e9906149db565b6000805460ff191660011790558015611b0a576000805461ff0019166101001790555b8015610bb6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b6116de3333868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525060408051602081019091529081529250600191506130cb9050565b333014611bc757604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a091339186918691901515908690613248565b6040513390600090611c0590839087906020016147a5565b604051602081830303815290604052805190602001209050611c5a8185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061246392505050565b336001600160a01b03167f0c4c547b3a4fcaa5be8353b3111472b124155bccc86de811d4a481c9e6e9faca868686604051610c8d939291906147e2565b611130333383611ca633611860565b61273e565b6000610b803384611362856040518060600160405280602a8152602001614dad602a91393360009081526011602090815260408083206001600160a01b038d1684529091529020549190613315565b60006118823333858561273e565b600080600080611d1886866120af565b9250925092506000611d40828411611d315760006129a3565b611d3b8385614a29565b6129a3565b611d4a9085614888565b60001315979650505050505050565b6000610b84827f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015611dbd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190614903565b333014611e0157604051630fff4cc960e31b815260040160405180910390fd5b80516040805160008152602081019091526110a0913391869186919015159081908790613341565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b03163314611e725760405163c51efddd60e01b815260040160405180910390fd5b6110a08383611362846040518060600160405280602a8152602001614dad602a91396001600160a01b03808a166000908152601160209081526040808320938c16835292905220549190613315565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b03163314611f0a5760405163c51efddd60e01b815260040160405180910390fd5b6116de33858585856040518060200160405280600081525060016130cb565b7f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b03163314611f725760405163c51efddd60e01b815260040160405180910390fd5b611130338384846040518060200160405280600081525060405180602001604052806000815250612a11565b604051632329212160e21b81523360048201527f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031690638ca4848490602401602060405180830381865afa158015612002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120269190614823565b6120435760405163327fd99160e21b815260040160405180910390fd5b6001600160a01b038216600090815260026020526040902054612067908290614888565b6001600160a01b0390921660009081526002602052604090209190915550565b600061188260128484613022565b6000806120a284846120af565b5050600013949350505050565b6001600160a01b0382166000908152600260205260408120549080806120d486611288565b905060005b81518110156121da5760008060008484815181106120f9576120f9614a3c565b60209081029190910101516040516326cb922f60e21b81523060048201526001600160a01b038c81166024830152604482018c905290911690639b2e48bc90606401606060405180830381865afa158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c9190614a52565b9194509250905061218d82886149c8565b965061219981876149c8565b95506121b68183116121ac5760006129a3565b611d3b8284614a29565b6121c0848a614888565b6121ca91906148b0565b97505050508060010190506120d9565b50509250925092565b600054610100900460ff16158080156122035750600054600160ff909116105b8061221d5750303b15801561221d575060005460ff166001145b6122395760405162461bcd60e51b81526004016113e9906149db565b6000805460ff19166001179055801561225c576000805461ff0019166101001790555b61226b88888888888888612c99565b80156117dc576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050565b336122c76012828461340f565b806001600160a01b0316826001600160a01b03167f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa160405160405180910390a35050565b3361231860128289613022565b6123355760405163f7f0222760e01b815260040160405180910390fd5b61146b8188898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525061254a92505050565b6110a03333338686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805160208101909152908152925061254a915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561245757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612439575b50505050509050919050565b60005b81518110156110a057600082828151811061248357612483614a3c565b60209081029190910101518483015550600101612466565b6001600160a01b0383166124c257604051638163862760e01b815260040160405180910390fd5b6001600160a01b0382166124e9576040516337c1c09d60e21b815260040160405180910390fd5b6001600160a01b0383811660008181526011602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600e546001600160a01b031661257357604051637bce7b2b60e11b815260040160405180910390fd5b60008061257f85612bdd565b915091506125968888838751600014158888613248565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156125df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126039190614903565b600e5490915061261d906001600160a01b03168885613507565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268a9190614903565b905060006126988284614a29565b90508085146126ba57604051631c7c26d360e31b815260040160405180910390fd5b896001600160a01b03167f3bc27981aebbb57f9247dc00fde9d6cd91e4b230083fec3238fedbcba1f9ab3d856040516126f591815260200190565b60405180910390a25050505050505050505050565b6000805b828110156127345783810154801561272b57600192505050610b84565b5060010161270e565b5060009392505050565b60006001600160a01b0384166127675760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b03831661278e5760405163e219bd3960e01b815260040160405180910390fd5b60003390506127bf81868686604051806020016040528060008152506040518060200160405280600081525061356a565b846001600160a01b0316866001600160a01b031614612852576128528587611362866040518060600160405280602d8152602001614df7602d9139601160008c6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b03168152602001908152602001600020546133159092919063ffffffff16565b50600195945050505050565b6000807f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031663289b3c0d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e39190614a80565b604051638369a0f160e01b81526001600160a01b037f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192811660048301523060248301527f9f60ae461adf056670e03ae602566409933242392cb06744f5747c9f38b05d09604483015291925090821690638369a0f190606401602060405180830381865afa158015612979573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299d9190614a80565b91505090565b60006001600160ff1b03821115612a0d5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016113e9565b5090565b600e546001600160a01b0316612a3a57604051637bce7b2b60e11b815260040160405180910390fd5b600080612a4685612bdd565b600e546040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612a97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abb9190614903565b600e54909150612ad6906001600160a01b0316893086613609565b600e546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190614903565b90506000612b518383614a29565b9050808514612b7357604051631c7c26d360e31b815260040160405180910390fd5b8651612b89908c908b9087901515808c8c613341565b886001600160a01b03167f25ca84076773b0455db53621c459ddc84fe40840e4932a62706a032566f399df856040516126f591815260200190565b60005b818110156110a057600083820155600101612bc7565b600e54600090819081906012600160a01b90910460ff161015612c3c57600e54612c1290600160a01b900460ff166012614a9d565b612c1d90600a614b9d565b9050612c298185614bac565b9250612c358184614bce565b9150612c93565b600e546012600160a01b90910460ff161115612c8c57600e54612c6b90601290600160a01b900460ff16614a9d565b612c7690600a614b9d565b9050612c828185614bce565b9250839150612c93565b8391508192505b50915091565b600e805460ff8816600160a01b026001600160a81b03199091166001600160a01b038a1617179055600f612cce858783614c2c565b506010612cdc838583614c2c565b50612cf381600080516020614d8d83398151915255565b612cfc30613641565b6040516000808252908190600080516020614dd78339815191529060200160405180910390a36040516001600160a01b038216906000907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f908290a350505050505050565b6000612d8b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b031603612de15760405162461bcd60e51b815260206004820152601d60248201527f5555505350726f786961626c653a206e6f742075706772616461626c6500000060448201526064016113e9565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e439190614903565b7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb001914612ebd5760405162461bcd60e51b815260206004820152602360248201527f5555505350726f786961626c653a206e6f7420636f6d70617469626c65206c6f60448201526267696360e81b60648201526084016113e9565b6001600160a01b0381163003612f155760405162461bcd60e51b815260206004820152601960248201527f5555505350726f786961626c653a2070726f7879206c6f6f700000000000000060448201526064016113e9565b612f3d817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fe011bc04c286c344a8fcbb8de77f953da762c3e25d8cdea984147fc4168a5dcc7f6bfbb132610e56cb96575dba244667b9d6dbfeffe22b68a79fa16f2d18eb0019604080519182526001600160a01b038416602083015201611b48565b6060816001600160401b03811115612fb557612fb5614092565b604051908082528060200260200182016040528015612fde578160200160208202803683370190505b50905060005b8281101561301b5760008185015490508083838151811061300757613007614a3c565b602090810291909101015250600101612fe4565b5092915050565b6000816001600160a01b0316836001600160a01b0316148061309157506001600160a01b038316600090815260018501602052604090205460ff16801561309157506001600160a01b03808316600090815260038601602090815260408083209387168352929052205460ff16155b806110b357506001600160a01b03808316600090815260028601602090815260408083209387168352929052205460ff1690509392505050565b6001600160a01b0386166130f25760405163eecd6c9b60e01b815260040160405180910390fd5b6001600160a01b0385166131195760405163e219bd3960e01b815260040160405180910390fd5b61312787878787878761376f565b61313587878787878761356a565b61146b87878787878787613896565b806001600160a01b0316826001600160a01b0316036131bb5760405162461bcd60e51b815260206004820152602d60248201527f4552433737374f70657261746f72733a20617574686f72697a696e672073656c60448201526c331030b99037b832b930ba37b960991b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff1615613211576001600160a01b03918216600090815260039390930160209081526040808520929093168452529020805460ff19169055565b6001600160a01b0380831660009081526002850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b03851661326f57604051632e8aac6160e21b815260040160405180910390fd5b8215613284576132848686600087868661376f565b61328e85856139e6565b846001600160a01b0316866001600160a01b03167fa78a9be3a7b862d26933ad85fb11d80ef66b8f972d7cbba06621d583943a40988685856040516132d593929190614ceb565b60405180910390a36040518481526000906001600160a01b03871690600080516020614dd7833981519152906020015b60405180910390a3505050505050565b600081848411156133395760405162461bcd60e51b81526004016113e99190613ee3565b505050900390565b6001600160a01b03861661336857604051630d24315760e01b815260040160405180910390fd5b6133728686613af6565b8315613388576133888760008888868689613896565b856001600160a01b0316876001600160a01b03167f2fe5be0146f74c5bce36c0b80911af6c7d86ff27e89d5cfa61fc681327954e5d8785856040516133cf93929190614ceb565b60405180910390a36040518581526001600160a01b03871690600090600080516020614dd78339815191529060200160405180910390a350505050505050565b336001600160a01b0382160361347a5760405162461bcd60e51b815260206004820152602a60248201527f4552433737374f70657261746f72733a207265766f6b696e672073656c662061604482015269399037b832b930ba37b960b11b60648201526084016113e9565b6001600160a01b038116600090815260018401602052604090205460ff16156134d4576001600160a01b0380831660009081526003850160209081526040808320938516835292905220805460ff19166001179055505050565b6001600160a01b03918216600090815260029390930160209081526040808520929093168452529020805460ff19169055565b6040516001600160a01b0383166024820152604481018290526110a090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613b50565b61357d8585613578866129a3565b613c25565b836001600160a01b0316856001600160a01b0316876001600160a01b03167f06b541ddaa720db2b10a4d0cdac39b8d360425fc073085fac19bc826146779878686866040516135ce93929190614ceb565b60405180910390a4836001600160a01b0316856001600160a01b0316600080516020614dd78339815191528560405161330591815260200190565b6040516001600160a01b03808516602483015283166044820152606481018290526116de9085906323b872dd60e01b90608401613533565b6040516329965a1d60e01b81526001600160a01b03821660048201527fac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce21770546024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b1580156136c257600080fd5b505af11580156136d6573d6000803e3d6000fd5b50506040516329965a1d60e01b81526001600160a01b03841660048201527faea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a6024820152306044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b15801561375b57600080fd5b505af1158015610cf1573d6000803e3d6000fd5b60405163555ddc6560e11b81526001600160a01b03861660048201527f29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe8956024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa1580156137f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138149190614a80565b90506001600160a01b0381161561146b57604051633ad5cbc160e11b81526001600160a01b038216906375ab97829061385b908a908a908a908a908a908a90600401614d16565b600060405180830381600087803b15801561387557600080fd5b505af1158015613889573d6000803e3d6000fd5b5050505050505050505050565b60405163555ddc6560e11b81526001600160a01b03861660048201527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6024820152600090731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa158015613917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061393b9190614a80565b90506001600160a01b038116156139b7576040516223de2960e01b81526001600160a01b038216906223de2990613980908b908b908b908b908b908b90600401614d16565b600060405180830381600087803b15801561399a57600080fd5b505af11580156139ae573d6000803e3d6000fd5b505050506117dc565b81156117dc576001600160a01b0386163b156117dc5760405163fe737d0560e01b815260040160405180910390fd5b6000613a6e837f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a4a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109529190614903565b50509050613a7b826129a3565b811215613a9b5760405163043b37d160e21b815260040160405180910390fd5b613aa4826129a3565b6001600160a01b038416600090815260026020526040902054613ac791906148b0565b6001600160a01b038416600090815260026020526040902055600354613aee908390614a29565b600355505050565b613aff816129a3565b6001600160a01b038316600090815260026020526040902054613b229190614888565b6001600160a01b038316600090815260026020526040902055600354613b499082906149c8565b6003555050565b6000613ba5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613d249092919063ffffffff16565b9050805160001480613bc6575080806020019051810190613bc69190614823565b6110a05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016113e9565b6000613c89847f000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d21926001600160a01b031663bbe4fd506040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a4a573d6000803e3d6000fd5b5050905081811215613cae57604051632f4cb94160e01b815260040160405180910390fd5b6001600160a01b038416600090815260026020526040902054613cd29083906148b0565b6001600160a01b038086166000908152600260205260408082209390935590851681522054613d02908390614888565b6001600160a01b03909316600090815260026020526040902092909255505050565b60606110b3848460008585600080866001600160a01b03168587604051613d4b9190614d70565b60006040518083038185875af1925050503d8060008114613d88576040519150601f19603f3d011682016040523d82523d6000602084013e613d8d565b606091505b5091509150613d9e87838387613da9565b979650505050505050565b60608315613e18578251600003613e11576001600160a01b0385163b613e115760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016113e9565b50816110b3565b6110b38383815115613e2d5781518083602001fd5b8060405162461bcd60e51b81526004016113e99190613ee3565b602080825282518282018190526000918401906040840190835b81811015613e885783516001600160a01b0316835260209384019390920191600101613e61565b509095945050505050565b60005b83811015613eae578181015183820152602001613e96565b50506000910152565b60008151808452613ecf816020860160208601613e93565b601f01601f19169290920160200192915050565b6020815260006118826020830184613eb7565b6001600160a01b0381168114610bb657600080fd5b60008083601f840112613f1d57600080fd5b5081356001600160401b03811115613f3457600080fd5b6020830191508360208260051b8501011115613f4f57600080fd5b9250929050565b60008060008060608587031215613f6c57600080fd5b8435613f7781613ef6565b93506020850135925060408501356001600160401b03811115613f9957600080fd5b613fa587828801613f0b565b95989497509550505050565b60008060408385031215613fc457600080fd5b8235613fcf81613ef6565b946020939093013593505050565b600060208284031215613fef57600080fd5b5035919050565b60008060006040848603121561400b57600080fd5b8335925060208401356001600160401b0381111561402857600080fd5b61403486828701613f0b565b9497909650939450505050565b6000806000806080858703121561405757600080fd5b843561406281613ef6565b9350602085013561407281613ef6565b9250604085013561408281613ef6565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156140d0576140d0614092565b604052919050565b600082601f8301126140e957600080fd5b81356001600160401b0381111561410257614102614092565b614115601f8201601f19166020016140a8565b81815284602083860101111561412a57600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114610bb657600080fd5b600080600080600080600060e0888a03121561417057600080fd5b8735965060208801356001600160401b0381111561418d57600080fd5b6141998a828b016140d8565b96505060408801356141aa81613ef6565b945060608801356141ba81614147565b935060808801356141ca81613ef6565b9699959850939692959460a0840135945060c09093013592915050565b6000806000606084860312156141fc57600080fd5b833561420781613ef6565b9250602084013561421781613ef6565b929592945050506040919091013590565b6000806040838503121561423b57600080fd5b50508035926020909101359150565b60006020828403121561425c57600080fd5b813561188281613ef6565b803560ff8116811461427857600080fd5b919050565b60008083601f84011261428f57600080fd5b5081356001600160401b038111156142a657600080fd5b602083019150836020828501011115613f4f57600080fd5b600080600080600080608087890312156142d757600080fd5b86356142e281613ef6565b95506142f060208801614267565b945060408701356001600160401b0381111561430b57600080fd5b61431789828a0161427d565b90955093505060608701356001600160401b0381111561433657600080fd5b61434289828a0161427d565b979a9699509497509295939492505050565b6000806000806080858703121561436a57600080fd5b843561437581613ef6565b9350602085013561438581613ef6565b93969395505050506040820135916060013590565b602080825282518282018190526000918401906040840190835b81811015613e885783518352602093840193909201916001016143b4565b600080600080606085870312156143e857600080fd5b84356143f381613ef6565b93506020850135925060408501356001600160401b0381111561441557600080fd5b613fa58782880161427d565b600080600080600080600060a0888a03121561443c57600080fd5b873561444781613ef6565b9650602088013561445781613ef6565b95506040880135945060608801356001600160401b0381111561447957600080fd5b6144858a828b0161427d565b90955093505060808801356001600160401b038111156144a457600080fd5b6144b08a828b0161427d565b989b979a50959850939692959293505050565b6000806000606084860312156144d857600080fd5b83356144e381613ef6565b95602085013595506040909401359392505050565b60008060006060848603121561450d57600080fd5b833561451881613ef6565b92506020840135915060408401356001600160401b0381111561453a57600080fd5b614546868287016140d8565b9150509250925092565b6000806000806080858703121561456657600080fd5b843561457181613ef6565b9350602085013561458181613ef6565b92506040850135915060608501356001600160401b038111156145a357600080fd5b6145af878288016140d8565b91505092959194509250565b600080604083850312156145ce57600080fd5b82356145d981613ef6565b915060208301356145e981613ef6565b809150509250929050565b600080600080600080600060a0888a03121561460f57600080fd5b873561461a81613ef6565b965061462860208901614267565b955060408801356001600160401b0381111561464357600080fd5b61464f8a828b0161427d565b90965094505060608801356001600160401b0381111561466e57600080fd5b61467a8a828b0161427d565b909450925050608088013561468e81613ef6565b8091505092959891949750929550565b600080600080600080608087890312156146b757600080fd5b86356146c281613ef6565b95506020870135945060408701356001600160401b0381111561430b57600080fd5b6000806000604084860312156146f957600080fd5b8335925060208401356001600160401b0381111561471657600080fd5b6140348682870161427d565b600181811c9082168061473657607f821691505b60208210810361475657634e487b7160e01b600052602260045260246000fd5b50919050565b6080808252600e908201526d41677265656d656e74537461746560901b60a08201526001600160a01b039384166020820152919092166040820152606081019190915260c00190565b6060808252600d908201526c41677265656d656e744461746160981b60808201526001600160a01b03929092166020830152604082015260a00190565b838152604060208201819052810182905260006001600160fb1b0383111561480957600080fd5b8260051b8085606085013791909101606001949350505050565b60006020828403121561483557600080fd5b815161188281614147565b634e487b7160e01b600052601160045260246000fd5b6000600160ff1b820161486b5761486b614840565b5060000390565b634e487b7160e01b600052600160045260246000fd5b80820182811260008312801582168215821617156148a8576148a8614840565b505092915050565b818103600083128015838313168383128216171561301b5761301b614840565b85815260018060a01b038516602082015283604082015282606082015260a060808201526000613d9e60a0830184613eb7565b60006020828403121561491557600080fd5b5051919050565b60006020828403121561492e57600080fd5b81516001600160401b0381111561494457600080fd5b8201601f8101841361495557600080fd5b80516001600160401b0381111561496e5761496e614092565b8060051b61497e602082016140a8565b9182526020818401810192908101908784111561499a57600080fd5b6020850194505b83851015613d9e57845192506149b683613ef6565b828252602094850194909101906149a1565b80820180821115610b8457610b84614840565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b81810381811115610b8457610b84614840565b634e487b7160e01b600052603260045260246000fd5b600080600060608486031215614a6757600080fd5b5050815160208301516040909301519094929350919050565b600060208284031215614a9257600080fd5b815161188281613ef6565b60ff8281168282160390811115610b8457610b84614840565b6001815b6001841115614af157808504811115614ad557614ad5614840565b6001841615614ae357908102905b60019390931c928002614aba565b935093915050565b600082614b0857506001610b84565b81614b1557506000610b84565b8160018114614b2b5760028114614b3557614b51565b6001915050610b84565b60ff841115614b4657614b46614840565b50506001821b610b84565b5060208310610133831016604e8410600b8410161715614b74575081810a610b84565b614b816000198484614ab6565b8060001904821115614b9557614b95614840565b029392505050565b600061188260ff841683614af9565b600082614bc957634e487b7160e01b600052601260045260246000fd5b500490565b8082028115828204841417610b8457610b84614840565b601f8211156110a057806000526020600020601f840160051c81016020851015614c0c5750805b601f840160051c820191505b81811015610cf15760008155600101614c18565b6001600160401b03831115614c4357614c43614092565b614c5783614c518354614722565b83614be5565b6000601f841160018114614c8b5760008515614c735750838201355b600019600387901b1c1916600186901b178355610cf1565b600083815260209020601f19861690835b82811015614cbc5786850135825560209485019460019092019101614c9c565b5086821015614cd95760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b838152606060208201526000614d046060830185613eb7565b82810360408401526116598185613eb7565b6001600160a01b0387811682528681166020830152851660408201526060810184905260c060808201819052600090614d5190830185613eb7565b82810360a0840152614d638185613eb7565b9998505050505050505050565b60008251614d82818460208701613e93565b919091019291505056feb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035375706572546f6b656e3a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef5375706572546f6b656e3a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365a2646970667358221220051487297b37014853ca2bf6a1b68805b6deae9a7d985b17481256b57dd48a6e64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192000000000000000000000000051e766e2d8dc65ae2bfcf084a50ad04476342270000000000000000000000000043d7c85c8b96a49a72a92c0b48cdc4720437d7000000000000000000000000a132a33bb6ed51085d376b3cc90c7723171ebb790000000000000000000000009dc144ba10c1d0ac64b36f409c70093c72300257
-----Decoded View---------------
Arg [0] : host (address): 0xCf8Acb4eF033efF16E8080aed4c7D5B9285D2192
Arg [1] : constantOutflowNFT (address): 0x051e766e2d8dc65ae2bFCF084A50AD0447634227
Arg [2] : constantInflowNFT (address): 0x0043d7c85C8b96a49A72A92C0B48CdC4720437d7
Arg [3] : poolAdminNFT (address): 0xa132a33bB6ED51085d376b3CC90c7723171ebb79
Arg [4] : poolMemberNFT (address): 0x9dC144bA10C1d0AC64B36f409C70093c72300257
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000cf8acb4ef033eff16e8080aed4c7d5b9285d2192
Arg [1] : 000000000000000000000000051e766e2d8dc65ae2bfcf084a50ad0447634227
Arg [2] : 0000000000000000000000000043d7c85c8b96a49a72a92c0b48cdc4720437d7
Arg [3] : 000000000000000000000000a132a33bb6ed51085d376b3cc90c7723171ebb79
Arg [4] : 0000000000000000000000009dc144ba10c1d0ac64b36f409c70093c72300257
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
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.