Contract
0x3D9A67D5ec1E72CEcA8157e028855056786b6159
2
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xb0027a7386810ee7b42ad322b4ae42c54d0c19391b15fcbe0a7b48439726e80d | Change Exit Rate | 16465451 | 454 days 20 hrs ago | 0x476e2651bf97de8a26e4a05a9c8e00a6efa1390c | IN | Superfluid Finance: TOGA | 0 AVAX | 0.01021324879 | |
0x86675fbd11e78fa9e57391051560198db601dfb51ef9c0f9918a52ab483a799a | 0x61010060 | 14769279 | 494 days 3 hrs ago | 0xcca090fd60d405a10b786559933daeec4e2053af | IN | Create: TOGA | 0 AVAX | 0.0392518225 |
[ Download CSV Export ]
Contract Name:
TOGA
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.13; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { ISuperfluid, ISuperToken, ISuperfluidToken } from "../interfaces/superfluid/ISuperfluid.sol"; import { IConstantFlowAgreementV1 } from "../interfaces/agreements/IConstantFlowAgreementV1.sol"; import { IERC1820Registry } from "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol"; import { IERC777Recipient } from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; import { TokenCustodian } from "./TokenCustodian.sol"; /** * @title TOGA: Transparent Ongoing Auction * @author Superfluid * * @dev TOGA is a simple implementation of a continuous auction. * It's used to designate PICs (Patrician In Charge) - a role defined per Super Token. * Anybody can become the PIC for a Super Token by staking the highest bond (denominated in the token). * Staking is done by simply using ERC777.send(), transferring the bond amount to be staked to this contract. * Via userData parameter (abi-encoded int96), an exitRate can be defined. If omitted, a default will be chosen. * The exitRate is the flowrate at which the bond is streamed back to the PIC. * Any rewards accrued by this contract (in general the whole token balance) become part of the bond. * When a PIC is outbid, the current bond is transferred to it with ERC777.send(). * * changes in v2: * In case that send() fails (e.g. due to a reverting hook), the bond is transferred to a custodian contract. * Funds accumulated there can be withdrawn from there at any time. * The current PIC can increase its bond by sending more funds using ERC777.send(). * */ interface ITOGAv1 { /** * @dev get the address of the current PIC for the given token. * @param token The token for which to get the PIC */ function getCurrentPIC(ISuperToken token) external view returns(address pic); /** * @dev get info about the state - most importantly the bond amount - of the current PIC for the given token. * @param token The token for which to get PIC info * Notes: * The bond changes dynamically and can both grow or shrink between 2 blocks. * Even the PIC itself could change anytime, this being a continuous auction. * @return pic Address of the current PIC. Returns the ZERO address if not set * @return bond The current bond amount. Can shrink or grow over time, depending on exitRate and rewards accrued * @return exitRate The current flowrate of given tokens from the contract to the PIC */ function getCurrentPICInfo(ISuperToken token) external view returns(address pic, uint256 bond, int96 exitRate); /** * @dev Get the exit rate set by default for the given token and bond amount * @param token The token for which to get info * @param bondAmount The bond amount for which to make the calculation * @return exitRate The exit rate set by default for a bid with the given bond amount for the given token */ function getDefaultExitRateFor(ISuperToken token, uint256 bondAmount) external view returns(int96 exitRate); /** * @dev Get the max exit which can be set for the given token and bond amount * @param token The token for which to get info * @param bondAmount The bond amount for which to calculate the max exit rate * @return exitRate The max exit rate which can be set for the given bond amount and token * * This limit is enforced only at the time of setting or updating the flow from the contract to the PIC. */ function getMaxExitRateFor(ISuperToken token, uint256 bondAmount) external view returns(int96 exitRate); /** * @dev allows the current PIC for the given token to change the exit rate * @param token The Super Token the exit rate should be changed for * @param newExitRate The new exit rate. The same constraints as during bidding apply. * * Notes: * newExitRate can't be higher than the value returned by getMaxExitRateFor() for the given token and bond. * newExitRate can also be 0, this triggers closing of the flow from the contract to the PIC. * If newExitRate is > 0 and no flow exists, a flow is created. */ function changeExitRate(ISuperToken token, int96 newExitRate) external; /** * @dev Emitted on a successful bid designating a PIC * @param token The Super token the new PIC bid for * @param pic The address of the new PIC * @param bond The size (amount) of the bond staked by the PIC * @param exitRate The flowrate at which the bond and accrued rewards will be streamed to the PIC * The exitRate must be greater or equal zero and respect the upper bound defined by getMaxExitRateFor() */ event NewPIC(ISuperToken indexed token, address pic, uint256 bond, int96 exitRate); /** * @dev Emitted if a PIC changes the exit rate * @param token The Super token for which the exit rate was changed * @param exitRate The new flowrate of the given token from the contract to the PIC */ event ExitRateChanged(ISuperToken indexed token, int96 exitRate); } interface ITOGAv2 is ITOGAv1 { /** * @dev allows previous PICs to withdraw bonds which couldn't be sent back to them * @param token The token for which to withdraw funds in custody */ function withdrawFundsInCustody(ISuperToken token) external; /** * @dev Emitted if a PIC increases its bond * @param additionalBond The additional amount added to the bond */ event BondIncreased(ISuperToken indexed token, uint256 additionalBond); } contract TOGA is ITOGAv2, IERC777Recipient { using SafeCast for uint256; // lightweight struct packing an address and a bool (reentrancy guard) into 1 word struct LockablePIC { address addr; bool lock; } mapping(ISuperToken => LockablePIC) internal _currentPICs; ISuperfluid internal immutable _host; IConstantFlowAgreementV1 internal immutable _cfa; uint256 public immutable minBondDuration; IERC1820Registry constant internal _ERC1820_REG = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24); // solhint-disable-next-line var-name-mixedcase uint64 immutable public ERC777_SEND_GAS_LIMIT = 3000000; // takes custody of bonds which the TOGA fails to send back to an outbid PIC TokenCustodian public custodian; constructor(ISuperfluid host_, uint256 minBondDuration_, TokenCustodian custodian_) { _host = ISuperfluid(host_); minBondDuration = minBondDuration_; _cfa = IConstantFlowAgreementV1( address(host_.getAgreementClass(keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1"))) ); bytes32 erc777TokensRecipientHash = keccak256("ERC777TokensRecipient"); _ERC1820_REG.setInterfaceImplementer(address(this), erc777TokensRecipientHash, address(this)); _ERC1820_REG.setInterfaceImplementer(address(this), keccak256("TOGAv1"), address(this)); _ERC1820_REG.setInterfaceImplementer(address(this), keccak256("TOGAv2"), address(this)); require( _ERC1820_REG.getInterfaceImplementer(address(custodian_), erc777TokensRecipientHash) == address(custodian_), "TOGA: invalid custodian" ); custodian = custodian_; } function getCurrentPIC(ISuperToken token) external view override returns(address pic) { return _currentPICs[token].addr; } function getCurrentPICInfo(ISuperToken token) external view override returns(address pic, uint256 bond, int96 exitRate) { (, exitRate,,) = _cfa.getFlow(token, address(this), _currentPICs[token].addr); return ( _currentPICs[token].addr, _getCurrentPICBond(token), exitRate ); } function capToInt96(int256 value) internal pure returns(int96) { return value < type(int96).max ? int96(value) : type(int96).max; } function getDefaultExitRateFor(ISuperToken /*token*/, uint256 bondAmount) public view override returns(int96 exitRate) { return capToInt96((bondAmount / (minBondDuration * 4)).toInt256()); } function getMaxExitRateFor(ISuperToken /*token*/, uint256 bondAmount) external view override returns(int96 exitRate) { return capToInt96((bondAmount / minBondDuration).toInt256()); } function changeExitRate(ISuperToken token, int96 newExitRate) external override { address currentPICAddr = _currentPICs[token].addr; require(msg.sender == currentPICAddr, "TOGA: only PIC allowed"); require(newExitRate >= 0, "TOGA: negative exitRate not allowed"); require(uint256(int256(newExitRate)) * minBondDuration <= _getCurrentPICBond(token), "TOGA: exitRate too high"); (, int96 curExitRate,,) = _cfa.getFlow(token, address(this), currentPICAddr); if (curExitRate > 0 && newExitRate > 0) { // need to update existing flow _host.callAgreement( _cfa, abi.encodeWithSelector( _cfa.updateFlow.selector, token, currentPICAddr, newExitRate, new bytes(0) ), "0x" ); } else if (curExitRate == 0 && newExitRate > 0) { // no pre-existing flow, need to create _host.callAgreement( _cfa, abi.encodeWithSelector( _cfa.createFlow.selector, token, currentPICAddr, newExitRate, new bytes(0) ), "0x" ); } else if (curExitRate > 0 && newExitRate == 0) { // need to close existing flow _host.callAgreement( _cfa, abi.encodeWithSelector( _cfa.deleteFlow.selector, token, address(this), currentPICAddr, new bytes(0) ), "0x" ); } // else do nothing (no existing flow, newExitRate == 0) emit ExitRateChanged(token, newExitRate); } function withdrawFundsInCustody(ISuperToken token) external override { custodian.flush(token, msg.sender); } // ============ internal ============ function _getCurrentPICBond(ISuperToken token) internal view returns(uint256 bond) { (int256 availBal, uint256 deposit, , ) = token.realtimeBalanceOfNow(address(this)); // The protocol guarantees that we get no values leading to an overflow here return availBal + int256(deposit) > 0 ? uint256(availBal + int256(deposit)) : 0; } // This is the logic for designating a PIC via successful bid - invoked only by the ERC777 send() hook // Relies on CFA (SuperApp) hooks not being able to block the transaction by reverting. function _becomePIC(ISuperToken token, address newPIC, uint256 amount, int96 exitRate) internal { require(!_currentPICs[token].lock, "TOGA: reentrancy not allowed"); require(exitRate >= 0, "TOGA: negative exitRate not allowed"); require(uint256(int256(exitRate)) * minBondDuration <= amount, "TOGA: exitRate too high"); // cannot underflow because amount was added to the balance before uint256 currentPICBond = _getCurrentPICBond(token) - amount; require(amount > currentPICBond, "TOGA: bid too low"); address currentPICAddr = _currentPICs[token].addr; _currentPICs[token].lock = true; // set reentrancy guard // close flow to current (soon previous) PIC if exists (, int96 curFlowRate,,) = _cfa.getFlow(token, address(this), currentPICAddr); if (curFlowRate > 0) { _host.callAgreement( _cfa, abi.encodeWithSelector( _cfa.deleteFlow.selector, token, address(this), currentPICAddr, new bytes(0) ), "0x" ); } // if no PIC was set yet, rewards already accumulated become part of the bond of the first PIC if (currentPICAddr != address(0)) { // send remaining bond to current PIC // solhint-disable-next-line check-send-result try token.send{gas: ERC777_SEND_GAS_LIMIT}(currentPICAddr, currentPICBond, "0x") // solhint-disable-next-line no-empty-blocks {} catch { // if sending failed, move the remaining bond to a custody contract // the current PIC can withdraw it in a separate tx anytime later // solhint-disable-next-line check-send-result, multiple-sends token.send(address(custodian), currentPICBond, abi.encode(currentPICAddr)); } } // set new PIC // solhint-disable-next-line reentrancy _currentPICs[token].addr = newPIC; // if exitRate > 0, open stream to new PIC if (exitRate > 0) { _host.callAgreement( _cfa, abi.encodeWithSelector( _cfa.createFlow.selector, token, newPIC, exitRate, new bytes(0) ), "0x" ); } // solhint-disable-next-line reentrancy _currentPICs[token].lock = false; // release reentrancy guard emit NewPIC(token, newPIC, amount, exitRate); } // ============ IERC777Recipient ============ function tokensReceived( address /*operator*/, address from, address /*to*/, uint256 amount, bytes calldata userData, bytes calldata /*operatorData*/ ) override external { // if it's not a SuperToken, something will revert along the way ISuperToken token = ISuperToken(msg.sender); if(from != _currentPICs[token].addr) { int96 exitRate = userData.length == 0 ? getDefaultExitRateFor(token, amount) : abi.decode(userData, (int96)); _becomePIC(token, from, amount, exitRate); } else { // current PIC increases the bond emit BondIncreased(token, amount); } } }
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.13; import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; import { IERC1820Registry } from "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol"; import { IERC777Recipient } from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; /** * @title Token custodian contract * @author Superfluid * @dev Contract which takes custody of funds which couldn't be sent to the designated recipient */ contract TokenCustodian is IERC777Recipient { IERC1820Registry constant internal _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24); mapping(IERC777 => mapping(address => uint256)) public balances; constructor() { _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777TokensRecipient"), address(this)); } event CustodianDeposit(IERC777 indexed token, address recipient, uint256 amount); event CustodianWithdrawal(IERC777 indexed token, address recipient, uint256 amount); // transfers tokens it has in custody for the given recipient to it function flush(IERC777 token, address recipient) public { uint256 amount = balances[token][recipient]; if (amount > 0) { balances[token][recipient] = 0; // solhint-disable-next-line check-send-result token.send(recipient, amount, "0x0"); emit CustodianWithdrawal(token, recipient, amount); } } // ============ IERC777Recipient ============ // interface through which ERC777 tokens are deposited to this contract. // requires userData to contain an abi-encoded address which designates the recipient for which the deposit is made. function tokensReceived( address /*operator*/, address /*from*/, address /*to*/, uint256 amount, bytes calldata userData, bytes calldata /*operatorData*/ ) override external { IERC777 token = IERC777(msg.sender); // note: if userData is not set or not decodable as address, this will revert address recipient = abi.decode(userData, (address)); balances[token][recipient] += amount; emit CustodianDeposit(token, recipient, amount); // note: anybody could call this function and store balance entries. We can just ignore that, does no harm. } }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.0; /** * @title ERC20 token info interface * @author Superfluid * @dev ERC20 standard interface does not specify these functions, but * often the token implementations have them. */ interface TokenInfo { /** * @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 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. * * NOTE: 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 returns (uint8); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { TokenInfo } from "./TokenInfo.sol"; /** * @title ERC20 token with token info interface * @author Superfluid * @dev Using abstract contract instead of interfaces because old solidity * does not support interface inheriting other interfaces * solhint-disable-next-line no-empty-blocks * */ // solhint-disable-next-line no-empty-blocks abstract contract ERC20WithTokenInfo is IERC20, TokenInfo {}
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.0; import { ISuperAgreement } from "./ISuperAgreement.sol"; /** * @title Superfluid token interface * @author Superfluid */ interface ISuperfluidToken { /************************************************************************** * 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 * * 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 */ 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 */ 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 * * 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 * * 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 of the stream sender * @param rewardAmount The amount the reward recepient account will receive * @param targetAccountBalanceDelta The amount the sender account balance should change by * * - 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 * * 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 rewardAccount 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) * * NOTE: * Reward account rule: * - if the agreement is liquidated during the PIC period * - the rewardAccount 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 liquidatorAccount 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 rewardAccount 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 rewardAccount, 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 * * NOTE: * * [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 * * NOTE: * * [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 * * 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: AGPLv3 pragma solidity >= 0.8.0; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { ISuperToken } from "./ISuperToken.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { ISuperfluid } from "./ISuperfluid.sol"; /** * @title Superfluid governance interface * @author Superfluid */ interface ISuperfluidGovernance { /** * @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 * * 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 ) 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 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: AGPLv3 pragma solidity >= 0.8.0; import { ISuperfluidGovernance } from "./ISuperfluidGovernance.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { ISuperToken } from "./ISuperToken.sol"; import { ISuperTokenFactory } from "./ISuperTokenFactory.sol"; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { ISuperApp } from "./ISuperApp.sol"; import { BatchOperation, ContextDefinitions, FlowOperatorDefinitions, SuperAppDefinitions, SuperfluidGovernanceConfigs } from "./Definitions.sol"; import { TokenInfo } from "../tokens/TokenInfo.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; /** * @title Host interface * @author Superfluid * NOTE: * 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 { /************************************************************************** * 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 * * 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 * * 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 * @dev Refer to ISuperTokenFactory.Upgradability for expected behaviours */ function updateSuperTokenLogic(ISuperToken token) external; /** * @dev SuperToken logic updated event * @param code Address of the new SuperToken logic */ event SuperTokenLogicUpdated(ISuperToken indexed token, address code); /************************************************************************** * App Registry *************************************************************************/ /** * @dev Message sender declares it as a super app * @param configWord The super app manifest configuration, flags are defined in * `SuperAppDefinitions` */ function registerApp(uint256 configWord) external; /** * @dev App registered event * @param app Address of jailed app */ event AppRegistered(ISuperApp indexed app); /** * @dev Message sender declares it as a super app, using a registration key * @param configWord The super app manifest configuration, flags are defined in * `SuperAppDefinitions` * @param registrationKey The registration key issued by the governance */ function registerAppWithKey(uint256 configWord, string calldata registrationKey) external; /** * @dev Message sender declares app as a super app * @param configWord The super app manifest configuration, flags are defined in * `SuperAppDefinitions` * NOTE: only factory contracts authorized by governance can register super apps */ 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 level * @param app Super app address */ function getAppLevel(ISuperApp app) external view returns(uint8 appLevel); /** * @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 allowance 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 */ 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 appAllowanceGranted App allowance granted so far. * @param appAllowanceUsed App allowance used so far. * @return newCtx */ function appCallbackPush( bytes calldata ctx, ISuperApp app, uint256 appAllowanceGranted, int256 appAllowanceUsed, ISuperfluidToken appAllowanceToken ) 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 appAllowanceUsedDelta App allowance used by the app. * @return newCtx * * [SECURITY] NOTE: * - 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 appAllowanceUsedDelta ) external // onlyAgreement returns (bytes memory newCtx); /** * @dev (For agreements) Use app allowance. * @param ctx The current ctx, it will be validated. * @param appAllowanceWantedMore See app allowance for more details. * @param appAllowanceUsedDelta See app allowance for more details. * @return newCtx */ function ctxUseAllowance( bytes calldata ctx, uint256 appAllowanceWantedMore, int256 appAllowanceUsedDelta ) 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 */ 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 * * 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 * * 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. */ struct Context { // // Call context // // callback level uint8 appLevel; // 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 allowance granted uint256 appAllowanceGranted; // app allowance wanted by the app callback uint256 appAllowanceWanted; // app allowance used, allowing negative values over a callback session int256 appAllowanceUsed; // app address address appAddress; // app allowance in super token ISuperfluidToken appAllowanceToken; } 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 calldata 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 */ function batchCall(Operation[] memory operations) external; /** * @dev Batch call function for trusted forwarders (EIP-2771) * @param operations Array of batch operations */ function forwardBatchCall(Operation[] memory operations) external; /************************************************************************** * 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: AGPLv3 pragma solidity >= 0.8.0; import { ISuperToken } from "./ISuperToken.sol"; import { IERC20, ERC20WithTokenInfo } from "../tokens/ERC20WithTokenInfo.sol"; /** * @title Super token factory interface * @author Superfluid */ interface ISuperTokenFactory { /** * @dev Get superfluid host contract address */ function getHost() external view returns(address host); /// @dev Initialize the contract function initialize() external; /** * @dev Get the current super token logic used by the factory */ 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_UPGRADABE } /** * @dev 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 */ function createERC20Wrapper( IERC20 underlyingToken, uint8 underlyingDecimals, Upgradability upgradability, string calldata name, string calldata symbol ) external returns (ISuperToken superToken); /** * @dev 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 * * NOTE: * - It assumes token provide the .decimals() function */ function createERC20Wrapper( ERC20WithTokenInfo underlyingToken, Upgradability upgradability, string calldata name, string calldata symbol ) external returns (ISuperToken superToken); 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: AGPLv3 pragma solidity >= 0.8.0; import { ISuperfluid } from "./ISuperfluid.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { TokenInfo } from "../tokens/TokenInfo.sol"; import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title Super token (Superfluid Token + ERC20 + ERC777) interface * @author Superfluid */ interface ISuperToken is ISuperfluidToken, TokenInfo, IERC20, IERC777 { /** * @dev Initialize the contract */ function initialize( IERC20 underlyingToken, uint8 underlyingDecimals, string calldata n, string calldata s ) external; /************************************************************************** * TokenInfo & ERC777 *************************************************************************/ /** * @dev Returns the name of the token. */ function name() external view override(IERC777, TokenInfo) returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view override(IERC777, TokenInfo) 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. * * NOTE: SuperToken always uses 18 decimals. * * Note: 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(TokenInfo) 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. * * 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. * * 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. * * 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 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. * * 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}. * * Emits an {Approval} event indicating the updated allowance. * * 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}. * * Emits an {Approval} event indicating the updated allowance. * * 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. * * For super token contracts, this value is 1 always */ 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 `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 override(IERC777); /** * @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 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}. * * Emits an {AuthorizedOperator} event. * * 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}. * * Emits a {RevokedOperator} event. * * 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 `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 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 `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 override(IERC777); /************************************************************************** * SuperToken custom token functions *************************************************************************/ /** * @dev Mint new tokens for the account * * Modifiers: * - onlySelf */ function selfMint( address account, uint256 amount, bytes memory userData ) external; /** * @dev Burn existing tokens for the account * * 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`. * * Modifiers: * - onlySelf */ function selfTransferFrom( address sender, address spender, address recipient, uint256 amount ) external; /** * @dev Give `spender`, `amount` allowance to spend the tokens of * `account`. * * 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 Upgrade ERC20 to SuperToken. * @param amount Number of tokens to be upgraded (in 18 decimals) * * 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 received upgraded tokens * @param amount Number of tokens to be upgraded (in 18 decimals) * @param data User data for the TokensRecipient callback * * NOTE: It will use ´transferFrom´ to get tokens. Before calling this * function you should ´approve´ this contract */ function upgradeTo(address to, uint256 amount, bytes calldata data) 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 Token downgrade event * @param account Account whose tokens are upgraded * @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. * * Modifiers: * - onlyHost */ function operationApprove( address account, address spender, uint256 amount ) external; /** * @dev Perform ERC20 transfer from 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 thefunds. * @param amount Number of tokens to be transferred. * * Modifiers: * - onlyHost */ function operationTransferFrom( address account, address spender, address recipient, uint256 amount ) 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) * * 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) * * Modifiers: * - onlyHost */ function operationDowngrade(address account, uint256 amount) external; /************************************************************************** * 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: AGPLv3 pragma solidity >= 0.8.0; 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. * * 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. * * 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. * * 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. * * 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. * * 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. * * 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: AGPLv3 pragma solidity >= 0.8.0; 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: AGPLv3 pragma solidity >= 0.8.0; /** * @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 getAppLevel(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_REGISTRATION_ONLY_IN_CONSTRUCTOR = 1; uint256 constant internal APP_RULE_NO_REGISTRATION_FOR_EOA = 2; 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 appLevel, uint8 callType) { appLevel = uint8(callInfo & CALL_INFO_APP_LEVEL_MASK); callType = uint8((callInfo & CALL_INFO_CALL_TYPE_MASK) >> CALL_INFO_CALL_TYPE_SHIFT); } function encodeCallInfo(uint8 appLevel, uint8 callType) internal pure returns (uint256 callInfo) { return uint256(appLevel) | (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 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 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; } /** * @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.0; import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol"; import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol"; /** * @title Constant Flow Agreement interface * @author Superfluid */ abstract contract IConstantFlowAgreementV1 is ISuperAgreement { /// @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 * 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) public 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); /** * @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) * * # App callbacks * * - AgreementCreated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * 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) * * # App callbacks * * - AgreementUpdated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * 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 receiver * @param receiver Flow sender * @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 * * # App callbacks * * - AgreementTerminated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * 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 v4.4.1 (utils/math/SafeCast.sol) pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted 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 */ 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 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 */ 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 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 */ 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 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 */ 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 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 */ 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 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 */ 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. */ 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. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ 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 v4.4.1 (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 { /** * @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 nor 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); event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer); event ManagerChanged(address indexed account, address indexed newManager); }
// 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 v4.4.1 (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 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 ); event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); event AuthorizedOperator(address indexed operator, address indexed tokenHolder); event RevokedOperator(address indexed operator, address indexed tokenHolder); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @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); /** * @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); }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "london", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"inputs":[{"internalType":"contract ISuperfluid","name":"host_","type":"address"},{"internalType":"uint256","name":"minBondDuration_","type":"uint256"},{"internalType":"contract TokenCustodian","name":"custodian_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperToken","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"additionalBond","type":"uint256"}],"name":"BondIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperToken","name":"token","type":"address"},{"indexed":false,"internalType":"int96","name":"exitRate","type":"int96"}],"name":"ExitRateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperToken","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"pic","type":"address"},{"indexed":false,"internalType":"uint256","name":"bond","type":"uint256"},{"indexed":false,"internalType":"int96","name":"exitRate","type":"int96"}],"name":"NewPIC","type":"event"},{"inputs":[],"name":"ERC777_SEND_GAS_LIMIT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"int96","name":"newExitRate","type":"int96"}],"name":"changeExitRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"custodian","outputs":[{"internalType":"contract TokenCustodian","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"}],"name":"getCurrentPIC","outputs":[{"internalType":"address","name":"pic","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"}],"name":"getCurrentPICInfo","outputs":[{"internalType":"address","name":"pic","type":"address"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"int96","name":"exitRate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"","type":"address"},{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"name":"getDefaultExitRateFor","outputs":[{"internalType":"int96","name":"exitRate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"","type":"address"},{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"name":"getMaxExitRateFor","outputs":[{"internalType":"int96","name":"exitRate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBondDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"}],"name":"withdrawFundsInCustody","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610100604052622dc6c060e0523480156200001957600080fd5b5060405162001b4638038062001b468339810160408190526200003c91620003c2565b6001600160a01b038316608081905260c0839052604051635b69006f60e11b81527fa9214cc96615e0085d3bb077758db69497dc2dce3b2b1e97bc93c3d18d83efd3600482015263b6d200de90602401602060405180830381865afa158015620000aa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000d091906200040a565b6001600160a01b031660a0526040516329965a1d60e01b815230600482018190527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b60248301819052604483019190915290731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d90606401600060405180830381600087803b1580156200015c57600080fd5b505af115801562000171573d6000803e3d6000fd5b50506040516329965a1d60e01b815230600482018190527fece6fc2bcfc93e4c34c28aeaa114be1a6161decb8268f79cbe7c3c7f31b1e8c660248301526044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b158015620001ef57600080fd5b505af115801562000204573d6000803e3d6000fd5b50506040516329965a1d60e01b815230600482018190527fca6323f8f0faf3d4f41f2397ee46c8d85bed576d54aadeb20b6cf7b45b3a696460248301526044820152731820a4b7618bde71dce8cdc73aab6c95905fad2492506329965a1d9150606401600060405180830381600087803b1580156200028257600080fd5b505af115801562000297573d6000803e3d6000fd5b505060405163555ddc6560e11b81526001600160a01b03851660048201819052602482018590529250731820a4b7618bde71dce8cdc73aab6c95905fad24915063aabbb8ca90604401602060405180830381865afa158015620002fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200032491906200040a565b6001600160a01b0316146200037f5760405162461bcd60e51b815260206004820152601760248201527f544f47413a20696e76616c696420637573746f6469616e000000000000000000604482015260640160405180910390fd5b50600180546001600160a01b0319166001600160a01b039290921691909117905550620004319050565b6001600160a01b0381168114620003bf57600080fd5b50565b600080600060608486031215620003d857600080fd5b8351620003e581620003a9565b602085015160408601519194509250620003ff81620003a9565b809150509250925092565b6000602082840312156200041d57600080fd5b81516200042a81620003a9565b9392505050565b60805160a05160c05160e05161166c620004da6000396000818160cf0152610cf801526000818161019101528181610364015281816107bb015281816108710152610a14015260008181610405015281816104c30152818161060d0152818161069b015281816108d901528181610b3501528181610bf50152610e5c01526000818161049c015281816105e60152818161067201528181610bcc0152610e33015261166c6000f3fe608060405234801561001057600080fd5b506004361061009d5760003560e01c8063375b74c311610066578063375b74c31461017957806360dfa6951461018c5780636da8d054146101c1578063b8a14033146101d4578063bf8903dd146101e757600080fd5b806223de29146100a257806302f3c6c5146100b75780630797e3e7146100ca57806316e23b9f1461010f5780633629106314610135575b600080fd5b6100b56100b0366004611131565b610222565b005b6100b56100c53660046111f1565b6102ca565b6100f17f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61012261011d36600461122a565b6107ae565b604051600b9190910b8152602001610106565b610161610143366004611256565b6001600160a01b039081166000908152602081905260409020541690565b6040516001600160a01b039091168152602001610106565b600154610161906001600160a01b031681565b6101b37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610106565b6100b56101cf366004611256565b6107fc565b6101226101e236600461122a565b610864565b6101fa6101f5366004611256565b610896565b604080516001600160a01b0390941684526020840192909252600b0b90820152606001610106565b336000818152602081905260409020546001600160a01b0389811691161461027b576000841561025d5761025885870187611273565b610267565b61026782886107ae565b9050610275828a898461097a565b506102bf565b806001600160a01b03167fb9c1b85a7ee70d95c61aca7cda03ef957abc5265a191ca74cc335faf59409566876040516102b691815260200190565b60405180910390a25b505050505050505050565b6001600160a01b03808316600090815260208190526040902054163381146103325760405162461bcd60e51b81526020600482015260166024820152751513d1d04e881bdb9b1e48141250c8185b1b1bddd95960521b60448201526064015b60405180910390fd5b600082600b0b12156103565760405162461bcd60e51b815260040161032990611290565b61035f83610f99565b61038d7f0000000000000000000000000000000000000000000000000000000000000000600b85900b6112e9565b11156103d55760405162461bcd60e51b81526020600482015260176024820152760a89e8e827440caf0d2e8a4c2e8ca40e8dede40d0d2ced604b1b6044820152606401610329565b604051631cd43d1160e31b81526001600160a01b03848116600483015230602483015282811660448301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e6a1e88890606401608060405180830381865afa15801561044e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104729190611308565b5050915050600081600b0b13801561048d5750600083600b0b135b156105c1576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166339255d5b7f00000000000000000000000000000000000000000000000000000000000000006328104d3160e11b87868860005b6040519080825280601f01601f19166020018201604052801561051a576020820181803683370190505b5060405160240161052e94939291906113b8565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b909216825261057492916004016113f8565b6000604051808303816000875af1158015610593573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105bb9190810190611446565b50610766565b80600b0b60001480156105d75750600083600b0b135b1561063e576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166339255d5b7f000000000000000000000000000000000000000000000000000000000000000063317e182f60e11b87868860006104f0565b600081600b0b138015610654575082600b0b6000145b15610766576040805160008152602081019091526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906339255d5b907f000000000000000000000000000000000000000000000000000000000000000090635a5999e360e11b906106d790899030908990604481016114f3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b909216825261071d92916004016113f8565b6000604051808303816000875af115801561073c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107649190810190611446565b505b604051600b84900b81526001600160a01b038516907f0988aefa675e81e1db7fca08264db5dc2a1cc2a604f2a78d902a9747146a56719060200160405180910390a250505050565b60006107f56107f06107e17f000000000000000000000000000000000000000000000000000000000000000060046112e9565b6107eb9085611527565b61103a565b6110a8565b9392505050565b600154604051634e7eee1b60e11b81526001600160a01b03838116600483015233602483015290911690639cfddc3690604401600060405180830381600087803b15801561084957600080fd5b505af115801561085d573d6000803e3d6000fd5b5050505050565b60006107f56107f06107eb7f000000000000000000000000000000000000000000000000000000000000000085611527565b6001600160a01b03818116600081815260208190526040808220549051631cd43d1160e31b815260048101939093523060248401528316604483015291829182917f0000000000000000000000000000000000000000000000000000000000000000169063e6a1e88890606401608060405180830381865afa158015610920573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109449190611308565b50506001600160a01b0380871660009081526020819052604090205491935016905061096f85610f99565b925092509193909250565b6001600160a01b038416600090815260208190526040902054600160a01b900460ff16156109ea5760405162461bcd60e51b815260206004820152601c60248201527f544f47413a207265656e7472616e6379206e6f7420616c6c6f776564000000006044820152606401610329565b600081600b0b1215610a0e5760405162461bcd60e51b815260040161032990611290565b81610a3d7f0000000000000000000000000000000000000000000000000000000000000000600b84900b6112e9565b1115610a855760405162461bcd60e51b81526020600482015260176024820152760a89e8e827440caf0d2e8a4c2e8ca40e8dede40d0d2ced604b1b6044820152606401610329565b600082610a9186610f99565b610a9b9190611549565b9050808311610ae05760405162461bcd60e51b8152602060048201526011602482015270544f47413a2062696420746f6f206c6f7760781b6044820152606401610329565b6001600160a01b038581166000818152602081905260408082208054600160a01b60ff60a01b198216179091559051631cd43d1160e31b815260048101939093523060248401528316604483018190529290917f00000000000000000000000000000000000000000000000000000000000000009091169063e6a1e88890606401608060405180830381865afa158015610b7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba29190611308565b5050915050600081600b0b1315610cc0576040805160008152602081019091526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906339255d5b907f000000000000000000000000000000000000000000000000000000000000000090635a5999e360e11b90610c31908c9030908990604481016114f3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252610c7792916004016113f8565b6000604051808303816000875af1158015610c96573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cbe9190810190611446565b505b6001600160a01b03821615610de057604051634decdde360e11b81526001600160a01b03881690639bd9bbc69067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690610d299086908890600401611560565b600060405180830381600088803b158015610d4357600080fd5b5087f193505050508015610d55575060015b610de057600154604080516001600160a01b0385811660208301528a811693639bd9bbc6939116918791016040516020818303038152906040526040518463ffffffff1660e01b8152600401610dad93929190611598565b600060405180830381600087803b158015610dc757600080fd5b505af1158015610ddb573d6000803e3d6000fd5b505050505b6001600160a01b03878116600090815260208190526040812080546001600160a01b03191692891692909217909155600b85900b1315610f27576040805160008152602081019091526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906339255d5b907f00000000000000000000000000000000000000000000000000000000000000009063317e182f60e11b90610e98908c908c908b90604481016113b8565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e085901b9092168252610ede92916004016113f8565b6000604051808303816000875af1158015610efd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f259190810190611446565b505b6001600160a01b0387811660008181526020818152604091829020805460ff60a01b191690558151938a1684528301889052600b87900b90830152907f836808e57755d5535898b7203c7d68b1bfb2701b1943ecb133c675e0d00780159060600160405180910390a250505050505050565b604051632ec8eec760e01b8152306004820152600090819081906001600160a01b03851690632ec8eec790602401608060405180830381865afa158015610fe4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100891906115bf565b5050915091506000818361101c91906115f5565b13611028576000611032565b61103281836115f5565b949350505050565b60006001600160ff1b038211156110a45760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401610329565b5090565b60006b7fffffffffffffffffffffff82126110a4576b7fffffffffffffffffffffff92915050565b6001600160a01b03811681146110e557600080fd5b50565b60008083601f8401126110fa57600080fd5b50813567ffffffffffffffff81111561111257600080fd5b60208301915083602082850101111561112a57600080fd5b9250929050565b60008060008060008060008060c0898b03121561114d57600080fd5b8835611158816110d0565b97506020890135611168816110d0565b96506040890135611178816110d0565b955060608901359450608089013567ffffffffffffffff8082111561119c57600080fd5b6111a88c838d016110e8565b909650945060a08b01359150808211156111c157600080fd5b506111ce8b828c016110e8565b999c989b5096995094979396929594505050565b80600b0b81146110e557600080fd5b6000806040838503121561120457600080fd5b823561120f816110d0565b9150602083013561121f816111e2565b809150509250929050565b6000806040838503121561123d57600080fd5b8235611248816110d0565b946020939093013593505050565b60006020828403121561126857600080fd5b81356107f5816110d0565b60006020828403121561128557600080fd5b81356107f5816111e2565b60208082526023908201527f544f47413a206e65676174697665206578697452617465206e6f7420616c6c6f6040820152621dd95960ea1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615611303576113036112d3565b500290565b6000806000806080858703121561131e57600080fd5b845193506020850151611330816111e2565b6040860151606090960151949790965092505050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561137757818101518382015260200161135f565b83811115611386576000848401525b50505050565b600081518084526113a481602086016020860161135c565b601f01601f19169290920160200192915050565b6001600160a01b03858116825284166020820152600b83900b60408201526080606082018190526000906113ee9083018461138c565b9695505050505050565b6001600160a01b038316815260606020820181905260009061141c9083018461138c565b828103604084015261143d816002815261060f60f31b602082015260400190565b95945050505050565b60006020828403121561145857600080fd5b815167ffffffffffffffff8082111561147057600080fd5b818401915084601f83011261148457600080fd5b81518181111561149657611496611346565b604051601f8201601f19908116603f011681019083821181831017156114be576114be611346565b816040528281528760208487010111156114d757600080fd5b6114e883602083016020880161135c565b979650505050505050565b6001600160a01b0385811682528481166020830152831660408201526080606082018190526000906113ee9083018461138c565b60008261154457634e487b7160e01b600052601260045260246000fd5b500490565b60008282101561155b5761155b6112d3565b500390565b6001600160a01b03831681526020810182905260606040820181905260029082015261060f60f31b6080820152600060a08201611032565b60018060a01b038416815282602082015260606040820152600061143d606083018461138c565b600080600080608085870312156115d557600080fd5b505082516020840151604085015160609095015191969095509092509050565b600080821280156001600160ff1b0384900385131615611617576116176112d3565b600160ff1b8390038412811615611630576116306112d3565b5050019056fea2646970667358221220f6d9a86e4217791168479d8577e1aa8a9823521c5035f8d5769ee1f55053412564736f6c634300080d003300000000000000000000000060377c7016e4cdb03c87ef474896c11cb560752c0000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000a4dd3f3b68647206e996e1c756f9c36096e65528
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000060377c7016e4cdb03c87ef474896c11cb560752c0000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000a4dd3f3b68647206e996e1c756f9c36096e65528
-----Decoded View---------------
Arg [0] : host_ (address): 0x60377c7016e4cdb03c87ef474896c11cb560752c
Arg [1] : minBondDuration_ (uint256): 604800
Arg [2] : custodian_ (address): 0xa4dd3f3b68647206e996e1c756f9c36096e65528
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000060377c7016e4cdb03c87ef474896c11cb560752c
Arg [1] : 0000000000000000000000000000000000000000000000000000000000093a80
Arg [2] : 000000000000000000000000a4dd3f3b68647206e996e1c756f9c36096e65528
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.