More Info
Private Name Tags
ContractCreator
Multichain Info
No addresses found
Latest 25 from a total of 31,563 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Delete Flow | 134613391 | 2 days ago | IN | 0 ETH | 0.00000471557 | ||||
Delete Flow | 134596001 | 3 days ago | IN | 0 ETH | 0.000000766525 | ||||
Delete Flow | 134595959 | 3 days ago | IN | 0 ETH | 0.000000765824 | ||||
Delete Flow | 134595946 | 3 days ago | IN | 0 ETH | 0.000000765396 | ||||
Delete Flow | 134504613 | 5 days ago | IN | 0 ETH | 0.000000334346 | ||||
Delete Flow | 134455966 | 6 days ago | IN | 0 ETH | 0.000000330562 | ||||
Delete Flow | 134427056 | 6 days ago | IN | 0 ETH | 0.000002897273 | ||||
Delete Flow | 134395247 | 7 days ago | IN | 0 ETH | 0.000001101544 | ||||
Delete Flow | 134395151 | 7 days ago | IN | 0 ETH | 0.000001254633 | ||||
Update Flow | 134388009 | 7 days ago | IN | 0 ETH | 0.000000989731 | ||||
Delete Flow | 134379096 | 8 days ago | IN | 0 ETH | 0.000001552639 | ||||
Delete Flow | 134379085 | 8 days ago | IN | 0 ETH | 0.000001550277 | ||||
Create Flow | 134373355 | 8 days ago | IN | 0 ETH | 0.000000654712 | ||||
Create Flow | 134322226 | 9 days ago | IN | 0 ETH | 0.000000986138 | ||||
Update Flow | 134264243 | 10 days ago | IN | 0 ETH | 0.000003601303 | ||||
Delete Flow | 134263912 | 10 days ago | IN | 0 ETH | 0.000014533922 | ||||
Create Flow | 134216338 | 11 days ago | IN | 0 ETH | 0.000004513312 | ||||
Delete Flow | 134216315 | 11 days ago | IN | 0 ETH | 0.000004305942 | ||||
Create Flow | 134216189 | 11 days ago | IN | 0 ETH | 0.000005395078 | ||||
Delete Flow | 134153759 | 13 days ago | IN | 0 ETH | 0.000000101036 | ||||
Delete Flow | 134153749 | 13 days ago | IN | 0 ETH | 0.000000104541 | ||||
Delete Flow | 134057476 | 15 days ago | IN | 0 ETH | 0.000000106156 | ||||
Delete Flow | 134006545 | 16 days ago | IN | 0 ETH | 0.000000404659 | ||||
Delete Flow | 133995221 | 16 days ago | IN | 0 ETH | 0.000000390311 | ||||
Delete Flow | 133975264 | 17 days ago | IN | 0 ETH | 0.000000356538 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
107534684 | 629 days ago | 0 ETH | ||||
107534678 | 629 days ago | 0 ETH | ||||
107534666 | 629 days ago | 0 ETH | ||||
107526477 | 629 days ago | 0 ETH | ||||
107496975 | 630 days ago | 0 ETH | ||||
107404655 | 632 days ago | 0 ETH | ||||
107390827 | 632 days ago | 0 ETH | ||||
107390727 | 632 days ago | 0 ETH | ||||
107387495 | 632 days ago | 0 ETH | ||||
107350869 | 633 days ago | 0 ETH | ||||
107338984 | 634 days ago | 0 ETH | ||||
107338791 | 634 days ago | 0 ETH | ||||
107337860 | 634 days ago | 0 ETH | ||||
107337291 | 634 days ago | 0 ETH | ||||
107255230 | 635 days ago | 0 ETH | ||||
107254086 | 635 days ago | 0 ETH | ||||
107132790 | 638 days ago | 0 ETH | ||||
107093183 | 639 days ago | 0 ETH | ||||
107083970 | 639 days ago | 0 ETH | ||||
107055647 | 640 days ago | 0 ETH | ||||
107041823 | 640 days ago | 0 ETH | ||||
107021219 | 641 days ago | 0 ETH | ||||
107021163 | 641 days ago | 0 ETH | ||||
107010193 | 641 days ago | 0 ETH | ||||
107010193 | 641 days ago | 0 ETH |
Loading...
Loading
Contract Name:
CFAv1Forwarder
Compiler Version
v0.8.16+commit.07a7930e
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.4; import { ISuperfluid, ISuperToken, BatchOperation, FlowOperatorDefinitions } from "../interfaces/superfluid/ISuperfluid.sol"; import { IConstantFlowAgreementV1 } from "../interfaces/agreements/IConstantFlowAgreementV1.sol"; import { CallUtils } from "../libs/CallUtils.sol"; /** * Contract address: * The CFAv1Forwarder contract provides an easy to use interface to * ConstantFlowAgreementV1 specific functionality of Super Tokens. * Instances of this contract can operate on the protocol only if configured as "trusted forwarder" * by protocol governance. */ contract CFAv1Forwarder { error CFA_FWD_INVALID_FLOW_RATE(); ISuperfluid internal immutable _host; IConstantFlowAgreementV1 internal immutable _cfa; // is tied to a specific instance of host and agreement contracts at deploy time constructor(ISuperfluid host) { _host = host; _cfa = IConstantFlowAgreementV1(address(_host.getAgreementClass( keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1") ))); } /** * @notice Sets the given flowrate between msg.sender and a given receiver. * If there's no pre-existing flow and `flowrate` non-zero, a new flow is created. * If there's an existing flow and `flowrate` non-zero, the flowrate of that flow is updated. * If there's an existing flow and `flowrate` zero, the flow is deleted. * If the existing and given flowrate are equal, no action is taken. * On creation of a flow, a "buffer" amount is automatically detracted from the sender account's available balance. * If the sender account is solvent when the flow is deleted, this buffer is redeemed to it. * @param token Super token address * @param receiver The receiver of the flow * @param flowrate The wanted flowrate in wad/second. Only positive values are valid here. * @return bool */ function setFlowrate(ISuperToken token, address receiver, int96 flowrate) external returns (bool) { return _setFlowrateFrom(token, msg.sender, receiver, flowrate); } /** * @notice Like `setFlowrate`, but can be invoked by an account with flowOperator permissions * on behalf of the sender account. * @param token Super token address * @param sender The sender of the flow * @param receiver The receiver of the flow * @param flowrate The wanted flowrate in wad/second. Only positive values are valid here. * @return bool */ function setFlowrateFrom( ISuperToken token, address sender, address receiver, int96 flowrate ) external returns (bool) { return _setFlowrateFrom(token, sender, receiver, flowrate); } /** * @notice Get the flowrate of the flow between 2 accounts if exists. * @dev Currently, only 0 or 1 flows can exist between 2 accounts. This may change in the future. * @param token Super token address * @param sender The sender of the flow * @param receiver The receiver of the flow * @return flowrate The flowrate from the sender to the receiver account. Returns 0 if no flow exists. */ function getFlowrate(ISuperToken token, address sender, address receiver) external view returns(int96 flowrate) { (, flowrate, , ) = _cfa.getFlow(token, sender, receiver); } /** * @notice Get all available information about a flow (if exists). * If only the flowrate is needed, consider using `getFlowrate` instead. * @param token Super token address * @param sender The sender of the flow * @param receiver The receiver of the flow * @return lastUpdated Timestamp of last update (flowrate change) or zero if no flow exists * @return flowrate Current flowrate of the flow or zero if no flow exists * @return deposit Deposit amount locked as security buffer during the lifetime of the flow * @return owedDeposit Extra deposit amount borrowed to a SuperApp receiver by the flow sender */ function getFlowInfo(ISuperToken token, address sender, address receiver) external view returns(uint256 lastUpdated, int96 flowrate, uint256 deposit, uint256 owedDeposit) { (lastUpdated, flowrate, deposit, owedDeposit) = _cfa.getFlow(token, sender, receiver); } /** * @notice Get the buffer amount required for the given token and flowrate. * This amount can vary based on the combination of token, flowrate and chain being queried. * The result for a given set of parameters can change over time, * because it depends on governance configurable protocol parameters. * Changes of the required buffer amount affect only flows created or updated after the change. * @param token Super token address * @param flowrate The flowrate for which the buffer amount is calculated * @return bufferAmount The buffer amount required for the given configuration. */ function getBufferAmountByFlowrate(ISuperToken token, int96 flowrate) external view returns (uint256 bufferAmount) { return _cfa.getDepositRequiredForFlowRate(token, flowrate); } /** * @notice Get the net flowrate of an account. * @param token Super token address * @param account Account to query * @return flowrate The net flowrate (aggregate incoming minus aggregate outgoing flowrate), can be negative. */ function getAccountFlowrate(ISuperToken token, address account) external view returns (int96 flowrate) { return _cfa.getNetFlow(token, account); } /** * @notice Get aggregated flow information (if any exist) of an account. * If only the net flowrate is needed, consider using `getAccountFlowrate` instead. * @param token Super token address * @param account Account to query * @return lastUpdated Timestamp of last update of a flow to or from the account (flowrate change) * @return flowrate Current net aggregate flowrate * @return deposit Aggregate deposit amount currently locked as security buffer for outgoing flows * @return owedDeposit Aggregate extra deposit amount currently borrowed to SuperApps receiving from this account */ function getAccountFlowInfo(ISuperToken token, address account) external view returns (uint256 lastUpdated, int96 flowrate, uint256 deposit, uint256 owedDeposit) { return _cfa.getAccountFlowInfo(token, account); } /** * @notice Low-level wrapper of createFlow/createFlowByOperator. * If the address of msg.sender is not the same as the address of the `sender` argument, * createFlowByOperator is used internally. In this case msg.sender needs to have permission to create flows * on behalf of the given sender account with sufficient flowRateAllowance. * Currently, only 1 flow can exist between 2 accounts, thus `createFlow` will fail if one already exists. * @param token Super token address * @param sender Sender address of the flow * @param receiver Receiver address of the flow * @param flowrate The flowrate in wad/second to be set initially * @param userData (optional) User data to be set. Should be set to zero if not needed. * @return bool */ function createFlow(ISuperToken token, address sender, address receiver, int96 flowrate, bytes memory userData) external returns (bool) { return _createFlow(token, sender, receiver, flowrate, userData); } /** * @notice Low-level wrapper if updateFlow/updateFlowByOperator. * If the address of msg.sender doesn't match the address of the `sender` argument, * updateFlowByOperator is invoked. In this case msg.sender needs to have permission to update flows * on behalf of the given sender account with sufficient flowRateAllowance. * @param token Super token address * @param sender Sender address of the flow * @param receiver Receiver address of the flow * @param flowrate The flowrate in wad/second the flow should be updated to * @param userData (optional) User data to be set. Should be set to zero if not needed. * @return bool */ function updateFlow(ISuperToken token, address sender, address receiver, int96 flowrate, bytes memory userData) external returns (bool) { return _updateFlow(token, sender, receiver, flowrate, userData); } /** * @notice Low-level wrapper of deleteFlow/deleteFlowByOperator. * If msg.sender isn't the same as sender address, msg.sender needs to have permission * to delete flows on behalf of the given sender account. * @param token Super token address * @param sender Sender address of the flow * @param receiver Receiver address of the flow * @param userData (optional) User data to be set. Should be set to zero if not needed. * @return bool */ function deleteFlow( ISuperToken token, address sender, address receiver, bytes memory userData ) external returns (bool) { return _deleteFlow(token, sender, receiver, userData); } /** * @notice Grants a flowOperator permission to create/update/delete flows on behalf of msg.sender. * In order to restrict what a flowOperator can or can't do, the flowOperator account * should be a contract implementing the desired restrictions. * @param token Super token address * @param flowOperator Account to which permissions are granted * @return bool */ function grantPermissions(ISuperToken token, address flowOperator) external returns (bool) { return _updateFlowOperatorPermissions( token, flowOperator, FlowOperatorDefinitions.AUTHORIZE_FULL_CONTROL, type(int96).max ); } /** * @notice Revokes all permissions previously granted to a flowOperator by msg.sender. * Revocation doesn't undo or reset flows previously created/updated by the flowOperator. * In order to be sure about the state of flows at the time of revocation, you need to check that state * either in the same transaction or after this transaction. * @param token Super token address * @param flowOperator Account from which permissions are revoked * @return bool */ function revokePermissions(ISuperToken token, address flowOperator) external returns (bool) { return _updateFlowOperatorPermissions( token, flowOperator, 0, 0 ); } /** * @notice Low-level wrapper of `IConstantFlowAgreementV1.updateFlowOperatorPermissions` * @param token Super token address * @param flowOperator Account for which permissions are set on behalf of msg.sender * @param permissions Bitmask for create/update/delete permission flags. See library `FlowOperatorDefinitions` * @param flowrateAllowance Max. flowrate in wad/second the operator can set for individual flows. * @return bool * @notice flowrateAllowance does NOT restrict the net flowrate a flowOperator is able to set. * In order to restrict that, flowOperator needs to be a contract implementing the wanted limitations. */ function updateFlowOperatorPermissions( ISuperToken token, address flowOperator, uint8 permissions, int96 flowrateAllowance ) external returns (bool) { return _updateFlowOperatorPermissions(token, flowOperator, permissions, flowrateAllowance); } /** * @notice Get the currently set permissions granted to the given flowOperator by the given sender account. * @param token Super token address * @param sender The account which (possiby) granted permissions * @param flowOperator Account to which (possibly) permissions were granted * @return permissions A bitmask of the permissions currently granted (or not) by `sender` to `flowOperator` * @return flowrateAllowance Max. flowrate in wad/second the flowOperator can set for individual flows. */ function getFlowOperatorPermissions(ISuperToken token, address sender, address flowOperator) external view returns (uint8 permissions, int96 flowrateAllowance) { (, permissions, flowrateAllowance) = _cfa.getFlowOperatorData(token, sender, flowOperator); } /************************************************************************** * Internal functions *************************************************************************/ function _setFlowrateFrom( ISuperToken token, address sender, address receiver, int96 flowrate ) internal returns (bool) { (, int96 prevFlowRate,,) = _cfa.getFlow(token, sender, receiver); if (flowrate > 0) { if (prevFlowRate == 0) { return _createFlow(token, sender, receiver, flowrate, new bytes(0)); } else if (prevFlowRate != flowrate) { return _updateFlow(token, sender, receiver, flowrate, new bytes(0)); } // else no change, do nothing return true; } else if (flowrate == 0) { if (prevFlowRate > 0) { return _deleteFlow(token, sender, receiver, new bytes(0)); } // else no change, do nothing return true; } else { revert CFA_FWD_INVALID_FLOW_RATE(); } } function _createFlow( ISuperToken token, address sender, address receiver, int96 flowrate, bytes memory userData ) internal returns (bool) { bytes memory cfaCallData = sender == msg.sender ? abi.encodeCall( _cfa.createFlow, ( token, receiver, flowrate, new bytes(0) // placeholder ) ) : abi.encodeCall( _cfa.createFlowByOperator, ( token, sender, receiver, flowrate, new bytes(0) // placeholder ) ); return _forwardBatchCall(address(_cfa), cfaCallData, userData); } function _updateFlow( ISuperToken token, address sender, address receiver, int96 flowrate, bytes memory userData ) internal returns (bool) { bytes memory cfaCallData = sender == msg.sender ? abi.encodeCall( _cfa.updateFlow, ( token, receiver, flowrate, new bytes(0) // placeholder ) ) : abi.encodeCall( _cfa.updateFlowByOperator, ( token, sender, receiver, flowrate, new bytes(0) // placeholder ) ); return _forwardBatchCall(address(_cfa), cfaCallData, userData); } function _deleteFlow( ISuperToken token, address sender, address receiver, bytes memory userData ) internal returns (bool) { bytes memory cfaCallData = sender == msg.sender || receiver == msg.sender ? abi.encodeCall( _cfa.deleteFlow, ( token, sender, receiver, new bytes(0) // placeholder ) ) : abi.encodeCall( _cfa.deleteFlowByOperator, ( token, sender, receiver, new bytes(0) // placeholder ) ); return _forwardBatchCall(address(_cfa), cfaCallData, userData); } function _updateFlowOperatorPermissions( ISuperToken token, address flowOperator, uint8 permissions, int96 flowrateAllowance ) internal returns (bool) { bytes memory cfaCallData = abi.encodeCall( _cfa.updateFlowOperatorPermissions, ( token, flowOperator, permissions, flowrateAllowance, new bytes(0) // placeholder ) ); return _forwardBatchCall(address(_cfa), cfaCallData, new bytes(0)); } // compiles the calldata of a single operation for the host invocation and executes it function _forwardBatchCall(address target, bytes memory callData, bytes memory userData) internal returns (bool) { ISuperfluid.Operation[] memory ops = new ISuperfluid.Operation[](1); ops[0] = ISuperfluid.Operation( BatchOperation.OPERATION_TYPE_SUPERFLUID_CALL_AGREEMENT, // type address(target), // target abi.encode( // data callData, userData ) ); bytes memory fwBatchCallData = abi.encodeCall( _host.forwardBatchCall, ( ops ) ); // https://eips.ethereum.org/EIPS/eip-2771 // we encode the msg.sender as the last 20 bytes per EIP-2771 to extract the original txn signer later on // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returnedData) = address(_host).call(abi.encodePacked(fwBatchCallData, msg.sender)); if (!success) { CallUtils.revertFromReturnedData(returnedData); } return true; } }
// SPDX-License-Identifier: AGPLv3 pragma solidity 0.8.16; /** * @title Call utilities library that is absent from the OpenZeppelin * @author Superfluid */ library CallUtils { /// @dev Bubble up the revert from the returnedData (supports Panic, Error & Custom Errors) /// @notice This is needed in order to provide some human-readable revert message from a call /// @param returnedData Response of the call function revertFromReturnedData(bytes memory returnedData) internal pure { if (returnedData.length < 4) { // case 1: catch all revert("CallUtils: target revert()"); } else { bytes4 errorSelector; assembly { errorSelector := mload(add(returnedData, 0x20)) } if (errorSelector == bytes4(0x4e487b71) /* `seth sig "Panic(uint256)"` */) { // case 2: Panic(uint256) (Defined since 0.8.0) // solhint-disable-next-line max-line-length // ref: https://docs.soliditylang.org/en/v0.8.0/control-structures.html#panic-via-assert-and-error-via-require) string memory reason = "CallUtils: target panicked: 0x__"; uint errorCode; assembly { errorCode := mload(add(returnedData, 0x24)) let reasonWord := mload(add(reason, 0x20)) // [0..9] is converted to ['0'..'9'] // [0xa..0xf] is not correctly converted to ['a'..'f'] // but since panic code doesn't have those cases, we will ignore them for now! let e1 := add(and(errorCode, 0xf), 0x30) let e2 := shl(8, add(shr(4, and(errorCode, 0xf0)), 0x30)) reasonWord := or( and(reasonWord, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000), or(e2, e1)) mstore(add(reason, 0x20), reasonWord) } revert(reason); } else { // case 3: Error(string) (Defined at least since 0.7.0) // case 4: Custom errors (Defined since 0.8.0) uint len = returnedData.length; assembly { revert(add(returnedData, 32), len) } } } } /** * @dev Helper method to parse data and extract the method signature (selector). * * Copied from: https://github.com/argentlabs/argent-contracts/ * blob/master/contracts/modules/common/Utils.sol#L54-L60 */ function parseSelector(bytes memory callData) internal pure returns (bytes4 selector) { require(callData.length >= 4, "CallUtils: invalid callData"); // solhint-disable-next-line no-inline-assembly assembly { selector := mload(add(callData, 0x20)) } } /** * @dev Pad length to 32 bytes word boundary */ function padLength32(uint256 len) internal pure returns (uint256 paddedLen) { return ((len / 32) + (((len & 31) > 0) /* rounding? */ ? 1 : 0)) * 32; } /** * @dev Validate if the data is encoded correctly with abi.encode(bytesData) * * Expected ABI Encode Layout: * | word 1 | word 2 | word 3 | the rest... * | data length | bytesData offset | bytesData length | bytesData + padLength32 zeros | */ function isValidAbiEncodedBytes(bytes memory data) internal pure returns (bool) { if (data.length < 64) return false; uint bytesOffset; uint bytesLen; // bytes offset is always expected to be 32 assembly { bytesOffset := mload(add(data, 32)) } if (bytesOffset != 32) return false; assembly { bytesLen := mload(add(data, 64)) } // the data length should be bytesData.length + 64 + padded bytes length return data.length == 64 + padLength32(bytesLen); } }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; /** * @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.4; 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.4; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { SuperfluidErrors } from "./Definitions.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 * * @custom:note * - version: 1 * - liquidationType key: * - 0 = reward account receives reward (PIC period) * - 1 = liquidator account receives reward (Pleb period) * - 2 = liquidator account receives reward (Pirate period/bailout) */ struct LiquidationTypeData { uint256 version; uint8 liquidationType; } /************************************************************************** * Real-time balance functions *************************************************************************/ /** * @dev Calculate the real balance of a user, taking in consideration all agreements of the account * @param account for the query * @param timestamp Time of balance * @return availableBalance Real-time balance * @return deposit Account deposit * @return owedDeposit Account owed Deposit */ function realtimeBalanceOf( address account, uint256 timestamp ) external view returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit); /** * @notice Calculate the realtime balance given the current host.getNow() value * @dev realtimeBalanceOf with timestamp equals to block timestamp * @param account for the query * @return availableBalance Real-time balance * @return deposit Account deposit * @return owedDeposit Account owed Deposit */ function realtimeBalanceOfNow( address account ) external view returns ( int256 availableBalance, uint256 deposit, uint256 owedDeposit, uint256 timestamp); /** * @notice Check if account is critical * @dev A critical account is when availableBalance < 0 * @param account The account to check * @param timestamp The time we'd like to check if the account is critical (should use future) * @return isCritical Whether the account is critical */ function isAccountCritical( address account, uint256 timestamp ) external view returns(bool isCritical); /** * @notice Check if account is critical now (current host.getNow()) * @dev A critical account is when availableBalance < 0 * @param account The account to check * @return isCritical Whether the account is critical */ function isAccountCriticalNow( address account ) external view returns(bool isCritical); /** * @notice Check if account is solvent * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance * @param account The account to check * @param timestamp The time we'd like to check if the account is solvent (should use future) * @return isSolvent True if the account is solvent, false otherwise */ function isAccountSolvent( address account, uint256 timestamp ) external view returns(bool isSolvent); /** * @notice Check if account is solvent now * @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance * @param account The account to check * @return isSolvent True if the account is solvent, false otherwise */ function isAccountSolventNow( address account ) external view returns(bool isSolvent); /** * @notice Get a list of agreements that is active for the account * @dev An active agreement is one that has state for the account * @param account Account to query * @return activeAgreements List of accounts that have non-zero states for the account */ function getAccountActiveAgreements(address account) external view returns(ISuperAgreement[] memory activeAgreements); /************************************************************************** * Super Agreement hosting functions *************************************************************************/ /** * @dev Create a new agreement * @param id Agreement ID * @param data Agreement data */ function createAgreement( bytes32 id, bytes32[] calldata data ) external; /** * @dev Agreement created event * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param data Agreement data */ event AgreementCreated( address indexed agreementClass, bytes32 id, bytes32[] data ); /** * @dev Get data of the agreement * @param agreementClass Contract address of the agreement * @param id Agreement ID * @return data Data of the agreement */ function getAgreementData( address agreementClass, bytes32 id, uint dataLength ) external view returns(bytes32[] memory data); /** * @dev Create a new agreement * @param id Agreement ID * @param data Agreement data */ function updateAgreementData( bytes32 id, bytes32[] calldata data ) external; /** * @dev Agreement updated event * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param data Agreement data */ event AgreementUpdated( address indexed agreementClass, bytes32 id, bytes32[] data ); /** * @dev Close the agreement * @param id Agreement ID */ function terminateAgreement( bytes32 id, uint dataLength ) external; /** * @dev Agreement terminated event * @param agreementClass Contract address of the agreement * @param id Agreement ID */ event AgreementTerminated( address indexed agreementClass, bytes32 id ); /** * @dev Update agreement state slot * @param account Account to be updated * * @custom:note * - To clear the storage out, provide zero-ed array of intended length */ function updateAgreementStateSlot( address account, uint256 slotId, bytes32[] calldata slotData ) external; /** * @dev Agreement account state updated event * @param agreementClass Contract address of the agreement * @param account Account updated * @param slotId slot id of the agreement state */ event AgreementStateUpdated( address indexed agreementClass, address indexed account, uint256 slotId ); /** * @dev Get data of the slot of the state of an agreement * @param agreementClass Contract address of the agreement * @param account Account to query * @param slotId slot id of the state * @param dataLength length of the state data */ function getAgreementStateSlot( address agreementClass, address account, uint256 slotId, uint dataLength ) external view returns (bytes32[] memory slotData); /** * @notice Settle balance from an account by the agreement * @dev The agreement needs to make sure that the balance delta is balanced afterwards * @param account Account to query. * @param delta Amount of balance delta to be settled * * @custom:modifiers * - onlyAgreement */ function settleBalance( address account, int256 delta ) external; /** * @dev Make liquidation payouts (v2) * @param id Agreement ID * @param liquidationTypeData Data regarding the version of the liquidation schema and the type * @param liquidatorAccount Address of the executor of the liquidation * @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount * @param targetAccount Account to be liquidated * @param rewardAmount The amount the rewarded account will receive * @param targetAccountBalanceDelta The delta amount the target account balance should change by * * @custom:note * - If a bailout is required (bailoutAmount > 0) * - the actual reward (single deposit) goes to the executor, * - while the reward account becomes the bailout account * - total bailout include: bailout amount + reward amount * - the targetAccount will be bailed out * - If a bailout is not required * - the targetAccount will pay the rewardAmount * - the liquidator (reward account in PIC period) will receive the rewardAmount * * @custom:modifiers * - onlyAgreement */ function makeLiquidationPayoutsV2 ( bytes32 id, bytes memory liquidationTypeData, address liquidatorAccount, bool useDefaultRewardAccount, address targetAccount, uint256 rewardAmount, int256 targetAccountBalanceDelta ) external; /** * @dev Agreement liquidation event v2 (including agent account) * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param liquidatorAccount Address of the executor of the liquidation * @param targetAccount Account of the stream sender * @param rewardAmountReceiver Account that collects the reward or bails out insolvent accounts * @param rewardAmount The amount the reward recipient account balance should change by * @param targetAccountBalanceDelta The amount the sender account balance should change by * @param liquidationTypeData The encoded liquidation type data including the version (how to decode) * * @custom:note * Reward account rule: * - if the agreement is liquidated during the PIC period * - the rewardAmountReceiver will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount * - the targetAccount will pay for the rewardAmount * - if the agreement is liquidated after the PIC period AND the targetAccount is solvent * - the rewardAmountReceiver will get the rewardAmount (remaining deposit) * - the targetAccount will pay for the rewardAmount * - if the targetAccount is insolvent * - the liquidatorAccount will get the rewardAmount (single deposit) * - the default reward account (governance) will pay for both the rewardAmount and bailoutAmount * - the targetAccount will receive the bailoutAmount */ event AgreementLiquidatedV2( address indexed agreementClass, bytes32 id, address indexed liquidatorAccount, address indexed targetAccount, address rewardAmountReceiver, uint256 rewardAmount, int256 targetAccountBalanceDelta, bytes liquidationTypeData ); /************************************************************************** * Function modifiers for access control and parameter validations * * While they cannot be explicitly stated in function definitions, they are * listed in function definition comments instead for clarity. * * NOTE: solidity-coverage not supporting it *************************************************************************/ /// @dev The msg.sender must be host contract //modifier onlyHost() virtual; /// @dev The msg.sender must be a listed agreement. //modifier onlyAgreement() virtual; /************************************************************************** * DEPRECATED *************************************************************************/ /** * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy) * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param penaltyAccount Account of the agreement to be penalized * @param rewardAccount Account that collect the reward * @param rewardAmount Amount of liquidation reward * * @custom:deprecated Use AgreementLiquidatedV2 instead */ event AgreementLiquidated( address indexed agreementClass, bytes32 id, address indexed penaltyAccount, address indexed rewardAccount, uint256 rewardAmount ); /** * @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy) * @param bailoutAccount Account that bailout the penalty account * @param bailoutAmount Amount of account bailout * * @custom:deprecated Use AgreementLiquidatedV2 instead */ event Bailout( address indexed bailoutAccount, uint256 bailoutAmount ); /** * @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2) * @param liquidatorAccount Account of the agent that performed the liquidation. * @param agreementClass Contract address of the agreement * @param id Agreement ID * @param penaltyAccount Account of the agreement to be penalized * @param bondAccount Account that collect the reward or bailout accounts * @param rewardAmount Amount of liquidation reward * @param bailoutAmount Amount of liquidation bailouot * * @custom:deprecated Use AgreementLiquidatedV2 instead * * @custom:note * Reward account rule: * - if bailout is equal to 0, then * - the bondAccount will get the rewardAmount, * - the penaltyAccount will pay for the rewardAmount. * - if bailout is larger than 0, then * - the liquidatorAccount will get the rewardAmouont, * - the bondAccount will pay for both the rewardAmount and bailoutAmount, * - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount. */ event AgreementLiquidatedBy( address liquidatorAccount, address indexed agreementClass, bytes32 id, address indexed penaltyAccount, address indexed bondAccount, uint256 rewardAmount, uint256 bailoutAmount ); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperAgreement } from "./ISuperAgreement.sol"; import { ISuperToken } from "./ISuperToken.sol"; import { ISuperfluidToken } from "./ISuperfluidToken.sol"; import { ISuperfluid } from "./ISuperfluid.sol"; import { SuperfluidErrors } from "./Definitions.sol"; /** * @title Superfluid governance interface * @author Superfluid */ interface ISuperfluidGovernance { /************************************************************************** * Errors *************************************************************************/ error SF_GOV_ARRAYS_NOT_SAME_LENGTH(); error SF_GOV_INVALID_LIQUIDATION_OR_PATRICIAN_PERIOD(); /** * @dev Replace the current governance with a new governance */ function replaceGovernance( ISuperfluid host, address newGov) external; /** * @dev Register a new agreement class */ function registerAgreementClass( ISuperfluid host, address agreementClass) external; /** * @dev Update logics of the contracts * * @custom:note * - Because they might have inter-dependencies, it is good to have one single function to update them all */ function updateContracts( ISuperfluid host, address hostNewLogic, address[] calldata agreementClassNewLogics, address superTokenFactoryNewLogic ) 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.4; 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, SuperfluidErrors, 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 * @notice This is the central contract of the system where super agreement, super app * and super token features are connected. * * The Superfluid host contract is also the entry point for the protocol users, * where batch call and meta transaction are provided for UX improvements. * */ interface ISuperfluid { /************************************************************************** * Errors *************************************************************************/ // Superfluid Custom Errors error HOST_AGREEMENT_CALLBACK_IS_NOT_ACTION(); error HOST_CANNOT_DOWNGRADE_TO_NON_UPGRADEABLE(); error HOST_CALL_AGREEMENT_WITH_CTX_FROM_WRONG_ADDRESS(); error HOST_CALL_APP_ACTION_WITH_CTX_FROM_WRONG_ADDRESS(); error HOST_INVALID_CONFIG_WORD(); error HOST_MAX_256_AGREEMENTS(); error HOST_NON_UPGRADEABLE(); error HOST_NON_ZERO_LENGTH_PLACEHOLDER_CTX(); error HOST_ONLY_GOVERNANCE(); error HOST_UNKNOWN_BATCH_CALL_OPERATION_TYPE(); // App Related Custom Errors error HOST_INVALID_OR_EXPIRED_SUPER_APP_REGISTRATION_KEY(); error HOST_NOT_A_SUPER_APP(); error HOST_NO_APP_REGISTRATION_PERMISSIONS(); error HOST_RECEIVER_IS_NOT_SUPER_APP(); error HOST_SENDER_IS_NOT_SUPER_APP(); error HOST_SOURCE_APP_NEEDS_HIGHER_APP_LEVEL(); error HOST_SUPER_APP_IS_JAILED(); error HOST_SUPER_APP_ALREADY_REGISTERED(); error HOST_UNAUTHORIZED_SUPER_APP_FACTORY(); /************************************************************************** * Time * * > The Oracle: You have the sight now, Neo. You are looking at the world without time. * > Neo: Then why can't I see what happens to her? * > The Oracle: We can never see past the choices we don't understand. * > - The Oracle and Neo conversing about the future of Trinity and the effects of Neo's choices *************************************************************************/ function getNow() external view returns (uint256); /************************************************************************** * Governance *************************************************************************/ /** * @dev Get the current governance address of the Superfluid host */ function getGovernance() external view returns(ISuperfluidGovernance governance); /** * @dev Replace the current governance with a new one */ function replaceGovernance(ISuperfluidGovernance newGov) external; /** * @dev Governance replaced event * @param oldGov Address of the old governance contract * @param newGov Address of the new governance contract */ event GovernanceReplaced(ISuperfluidGovernance oldGov, ISuperfluidGovernance newGov); /************************************************************************** * Agreement Whitelisting *************************************************************************/ /** * @dev Register a new agreement class to the system * @param agreementClassLogic Initial agreement class code * * @custom:modifiers * - onlyGovernance */ function registerAgreementClass(ISuperAgreement agreementClassLogic) external; /** * @notice Agreement class registered event * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param agreementType The agreement type registered * @param code Address of the new agreement */ event AgreementClassRegistered(bytes32 agreementType, address code); /** * @dev Update code of an agreement class * @param agreementClassLogic New code for the agreement class * * @custom:modifiers * - onlyGovernance */ function updateAgreementClass(ISuperAgreement agreementClassLogic) external; /** * @notice Agreement class updated event * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param agreementType The agreement type updated * @param code Address of the new agreement */ event AgreementClassUpdated(bytes32 agreementType, address code); /** * @notice Check if the agreement type is whitelisted * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" */ function isAgreementTypeListed(bytes32 agreementType) external view returns(bool yes); /** * @dev Check if the agreement class is whitelisted */ function isAgreementClassListed(ISuperAgreement agreementClass) external view returns(bool yes); /** * @notice Get agreement class * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" */ function getAgreementClass(bytes32 agreementType) external view returns(ISuperAgreement agreementClass); /** * @dev Map list of the agreement classes using a bitmap * @param bitmap Agreement class bitmap */ function mapAgreementClasses(uint256 bitmap) external view returns (ISuperAgreement[] memory agreementClasses); /** * @notice Create a new bitmask by adding a agreement class to it * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param bitmap Agreement class bitmap */ function addToAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType) external view returns (uint256 newBitmap); /** * @notice Create a new bitmask by removing a agreement class from it * @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>" * @param bitmap Agreement class bitmap */ function removeFromAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType) external view returns (uint256 newBitmap); /************************************************************************** * Super Token Factory **************************************************************************/ /** * @dev Get the super token factory * @return factory The factory */ function getSuperTokenFactory() external view returns (ISuperTokenFactory factory); /** * @dev Get the super token factory logic (applicable to upgradable deployment) * @return logic The factory logic */ function getSuperTokenFactoryLogic() external view returns (address logic); /** * @dev Update super token factory * @param newFactory New factory logic */ function updateSuperTokenFactory(ISuperTokenFactory newFactory) external; /** * @dev SuperToken factory updated event * @param newFactory Address of the new factory */ event SuperTokenFactoryUpdated(ISuperTokenFactory newFactory); /** * @notice Update the super token logic to the latest * @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 (must be a contract) declares itself as a super app. * @custom:deprecated you should use `registerAppWithKey` or `registerAppByFactory` instead, * because app registration is currently governance permissioned on mainnets. * @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 itself as a super app. * @param configWord The super app manifest configuration, flags are defined in `SuperAppDefinitions` * @param registrationKey The registration key issued by the governance, needed to register on a mainnet. * @notice See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide * On testnets or in dev environment, a placeholder (e.g. empty string) can be used. * While the message sender must be the super app itself, the transaction sender (tx.origin) * must be the deployer account the registration key was issued for. */ function registerAppWithKey(uint256 configWord, string calldata registrationKey) external; /** * @dev Message sender (must be a contract) declares app as a super app * @param configWord The super app manifest configuration, flags are defined in `SuperAppDefinitions` * @notice On mainnet deployments, only factory contracts pre-authorized by governance can use this. * See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide */ function registerAppByFactory(ISuperApp app, uint256 configWord) external; /** * @dev Query if the app is registered * @param app Super app address */ function isApp(ISuperApp app) external view returns(bool); /** * @dev Query app callbacklevel * @param app Super app address */ function getAppCallbackLevel(ISuperApp app) external view returns(uint8 appCallbackLevel); /** * @dev Get the manifest of the super app * @param app Super app address */ function getAppManifest( ISuperApp app ) external view returns ( bool isSuperApp, bool isJailed, uint256 noopMask ); /** * @dev Query if the app has been jailed * @param app Super app address */ function isAppJailed(ISuperApp app) external view returns (bool isJail); /** * @dev Whitelist the target app for app composition for the source app (msg.sender) * @param targetApp The target super app address */ function allowCompositeApp(ISuperApp targetApp) external; /** * @dev Query if source app is allowed to call the target app as downstream app * @param app Super app address * @param targetApp The target super app address */ function isCompositeAppAllowed( ISuperApp app, ISuperApp targetApp ) external view returns (bool isAppAllowed); /************************************************************************** * Agreement Framework * * Agreements use these function to trigger super app callbacks, updates * app credit and charge gas fees. * * These functions can only be called by registered agreements. *************************************************************************/ /** * @dev (For agreements) StaticCall the app before callback * @param app The super app. * @param callData The call data sending to the super app. * @param isTermination Is it a termination callback? * @param ctx Current ctx, it will be validated. * @return cbdata Data returned from the callback. */ function callAppBeforeCallback( ISuperApp app, bytes calldata callData, bool isTermination, bytes calldata ctx ) external // onlyAgreement // assertValidCtx(ctx) returns(bytes memory cbdata); /** * @dev (For agreements) Call the app after callback * @param app The super app. * @param callData The call data sending to the super app. * @param isTermination Is it a termination callback? * @param ctx Current ctx, it will be validated. * @return newCtx The current context of the transaction. */ function callAppAfterCallback( ISuperApp app, bytes calldata callData, bool isTermination, bytes calldata ctx ) external // onlyAgreement // assertValidCtx(ctx) returns(bytes memory newCtx); /** * @dev (For agreements) Create a new callback stack * @param ctx The current ctx, it will be validated. * @param app The super app. * @param appCreditGranted App credit granted so far. * @param appCreditUsed App credit used so far. * @return newCtx The current context of the transaction. */ function appCallbackPush( bytes calldata ctx, ISuperApp app, uint256 appCreditGranted, int256 appCreditUsed, ISuperfluidToken appCreditToken ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev (For agreements) Pop from the current app callback stack * @param ctx The ctx that was pushed before the callback stack. * @param appCreditUsedDelta App credit used by the app. * @return newCtx The current context of the transaction. * * @custom:security * - Here we cannot do assertValidCtx(ctx), since we do not really save the stack in memory. * - Hence there is still implicit trust that the agreement handles the callback push/pop pair correctly. */ function appCallbackPop( bytes calldata ctx, int256 appCreditUsedDelta ) external // onlyAgreement returns (bytes memory newCtx); /** * @dev (For agreements) Use app credit. * @param ctx The current ctx, it will be validated. * @param appCreditUsedMore See app credit for more details. * @return newCtx The current context of the transaction. */ function ctxUseCredit( bytes calldata ctx, int256 appCreditUsedMore ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev (For agreements) Jail the app. * @param app The super app. * @param reason Jail reason code. * @return newCtx The current context of the transaction. */ function jailApp( bytes calldata ctx, ISuperApp app, uint256 reason ) external // onlyAgreement // assertValidCtx(ctx) returns (bytes memory newCtx); /** * @dev Jail event for the app * @param app Address of jailed app * @param reason Reason the app is jailed (see Definitions.sol for the full list) */ event Jail(ISuperApp indexed app, uint256 reason); /************************************************************************** * Contextless Call Proxies * * NOTE: For EOAs or non-app contracts, they are the entry points for interacting * with agreements or apps. * * NOTE: The contextual call data should be generated using * abi.encodeWithSelector. The context parameter should be set to "0x", * an empty bytes array as a placeholder to be replaced by the host * contract. *************************************************************************/ /** * @dev Call agreement function * @param agreementClass The agreement address you are calling * @param callData The contextual call data with placeholder ctx * @param userData Extra user data being sent to the super app callbacks */ function callAgreement( ISuperAgreement agreementClass, bytes calldata callData, bytes calldata userData ) external //cleanCtx //isAgreement(agreementClass) returns(bytes memory returnedData); /** * @notice Call app action * @dev Main use case is calling app action in a batch call via the host * @param callData The contextual call data * * @custom:note See "Contextless Call Proxies" above for more about contextual call data. */ function callAppAction( ISuperApp app, bytes calldata callData ) external //cleanCtx //isAppActive(app) //isValidAppAction(callData) returns(bytes memory returnedData); /************************************************************************** * Contextual Call Proxies and Context Utilities * * For apps, they must use context they receive to interact with * agreements or apps. * * The context changes must be saved and returned by the apps in their * callbacks always, any modification to the context will be detected and * the violating app will be jailed. *************************************************************************/ /** * @dev Context Struct * * @custom:note on backward compatibility: * - Non-dynamic fields are padded to 32bytes and packed * - Dynamic fields are referenced through a 32bytes offset to their "parents" field (or root) * - The order of the fields hence should not be rearranged in order to be backward compatible: * - non-dynamic fields will be parsed at the same memory location, * - and dynamic fields will simply have a greater offset than it was. * - We cannot change the structure of the Context struct because of ABI compatibility requirements */ struct Context { // // Call context // // app callback level uint8 appCallbackLevel; // type of call uint8 callType; // the system timestamp uint256 timestamp; // The intended message sender for the call address msgSender; // // Callback context // // For callbacks it is used to know which agreement function selector is called bytes4 agreementSelector; // User provided data for app callbacks bytes userData; // // App context // // app credit granted uint256 appCreditGranted; // app credit wanted by the app callback uint256 appCreditWantedDeprecated; // app credit used, allowing negative values over a callback session // the appCreditUsed value over a callback sessions is calculated with: // existing flow data owed deposit + sum of the callback agreements // deposit deltas // the final value used to modify the state is determined by the // _adjustNewAppCreditUsed function (in AgreementLibrary.sol) which takes // the appCreditUsed value reached in the callback session and the app // credit granted int256 appCreditUsed; // app address address appAddress; // app credit in super token ISuperfluidToken appCreditToken; } function callAgreementWithContext( ISuperAgreement agreementClass, bytes calldata callData, bytes calldata userData, bytes calldata ctx ) external // requireValidCtx(ctx) // onlyAgreement(agreementClass) returns (bytes memory newCtx, bytes memory returnedData); function callAppActionWithContext( ISuperApp app, bytes calldata callData, bytes calldata ctx ) external // requireValidCtx(ctx) // isAppActive(app) returns (bytes memory newCtx); function decodeCtx(bytes memory ctx) external pure returns (Context memory context); function isCtxValid(bytes calldata ctx) external view returns (bool); /************************************************************************** * Batch call **************************************************************************/ /** * @dev Batch operation data */ struct Operation { // Operation type. Defined in BatchOperation (Definitions.sol) uint32 operationType; // Operation target address target; // Data specific to the operation bytes data; } /** * @dev Batch call function * @param operations Array of batch operations */ function batchCall(Operation[] calldata operations) external; /** * @dev Batch call function for trusted forwarders (EIP-2771) * @param operations Array of batch operations */ function forwardBatchCall(Operation[] calldata 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.4; import { ISuperToken } from "./ISuperToken.sol"; import { IERC20, ERC20WithTokenInfo } from "../tokens/ERC20WithTokenInfo.sol"; import { SuperfluidErrors } from "./Definitions.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.4; 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"; import { SuperfluidErrors } from "./Definitions.sol"; /** * @title Super token (Superfluid Token + ERC20 + ERC777) interface * @author Superfluid */ interface ISuperToken is ISuperfluidToken, TokenInfo, IERC20, IERC777 { /************************************************************************** * Errors *************************************************************************/ error SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); error SUPER_TOKEN_NOT_ERC777_TOKENS_RECIPIENT(); error SUPER_TOKEN_INFLATIONARY_DEFLATIONARY_NOT_SUPPORTED(); error SUPER_TOKEN_NO_UNDERLYING_TOKEN(); error SUPER_TOKEN_ONLY_SELF(); /** * @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. * * @custom:note SuperToken always uses 18 decimals. * * This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external view override(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. * * @custom:emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external override(IERC20) returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * @notice This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external override(IERC20) view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:note Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * @custom:emits an {Approval} event. */ function approve(address spender, uint256 amount) external override(IERC20) returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * @return Returns Success a boolean value indicating whether the operation succeeded. * * @custom:emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external override(IERC20) returns (bool); /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * @custom:emits an {Approval} event indicating the updated allowance. * * @custom:requirements * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) external returns (bool); /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * @custom:emits an {Approval} event indicating the updated allowance. * * @custom:requirements * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); /************************************************************************** * ERC777 *************************************************************************/ /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * @custom:note For super token contracts, this value is always 1 */ function granularity() external view override(IERC777) returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * @dev If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * @custom:emits a {Sent} event. * * @custom:requirements * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send(address recipient, uint256 amount, bytes calldata 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}. * * @custom:emits a {Burned} event. * * @custom: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}. * * @custom:emits an {AuthorizedOperator} event. * * @custom:requirements * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external override(IERC777); /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * @custom:emits a {RevokedOperator} event. * * @custom:requirements * - `operator` cannot be calling address. */ function revokeOperator(address operator) external override(IERC777); /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external override(IERC777) view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * @custom:emits a {Sent} event. * * @custom:requirements * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata 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}. * * @custom:emits a {Burned} event. * * @custom:requirements * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata data, bytes calldata operatorData ) external override(IERC777); /************************************************************************** * SuperToken custom token functions *************************************************************************/ /** * @dev Mint new tokens for the account * * @custom:modifiers * - onlySelf */ function selfMint( address account, uint256 amount, bytes memory userData ) external; /** * @dev Burn existing tokens for the account * * @custom:modifiers * - onlySelf */ function selfBurn( address account, uint256 amount, bytes memory userData ) external; /** * @dev Transfer `amount` tokens from the `sender` to `recipient`. * If `spender` isn't the same as `sender`, checks if `spender` has allowance to * spend tokens of `sender`. * * @custom:modifiers * - onlySelf */ function selfTransferFrom( address sender, address spender, address recipient, uint256 amount ) external; /** * @dev Give `spender`, `amount` allowance to spend the tokens of * `account`. * * @custom:modifiers * - onlySelf */ function selfApproveFor( address account, address spender, uint256 amount ) external; /************************************************************************** * SuperToken extra functions *************************************************************************/ /** * @dev Transfer all available balance from `msg.sender` to `recipient` */ function transferAll(address recipient) external; /************************************************************************** * ERC20 wrapping *************************************************************************/ /** * @dev Return the underlying token contract * @return tokenAddr Underlying token address */ function getUnderlyingToken() external view returns(address tokenAddr); /** * @dev Upgrade ERC20 to SuperToken. * @param amount Number of tokens to be upgraded (in 18 decimals) * * @custom:note It will use `transferFrom` to get tokens. Before calling this * function you should `approve` this contract */ function upgrade(uint256 amount) external; /** * @dev Upgrade ERC20 to SuperToken and transfer immediately * @param to The account to received upgraded tokens * @param amount Number of tokens to be upgraded (in 18 decimals) * @param data User data for the TokensRecipient callback * * @custom: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. * * @custom: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. * * @custom: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) * * @custom:modifiers * - onlyHost */ function operationUpgrade(address account, uint256 amount) external; /** * @dev Downgrade ERC20 to SuperToken by host contract. * @param account The account to be changed. * @param amount Number of tokens to be downgraded (in 18 decimals) * * @custom:modifiers * - onlyHost */ function operationDowngrade(address account, uint256 amount) external; /************************************************************************** * 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.4; import { ISuperToken } from "./ISuperToken.sol"; /** * @title SuperApp interface * @author Superfluid * @dev Be aware of the app being jailed, when the word permitted is used. */ interface ISuperApp { /** * @dev Callback before a new agreement is created. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass * arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Only revert with a "reason" is permitted. */ function beforeAgreementCreated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is created. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Only revert with a "reason" is permitted. */ function afterAgreementCreated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); /** * @dev Callback before a new agreement is updated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass * arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Only revert with a "reason" is permitted. */ function beforeAgreementUpdated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is updated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Only revert with a "reason" is permitted. */ function afterAgreementUpdated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); /** * @dev Callback before a new agreement is terminated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param ctx The context data. * @return cbdata A free format in memory data the app can use to pass arbitary information to the after-hook callback. * * @custom:note * - It will be invoked with `staticcall`, no state changes are permitted. * - Revert is not permitted. */ function beforeAgreementTerminated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata ctx ) external view returns (bytes memory cbdata); /** * @dev Callback after a new agreement is terminated. * @param superToken The super token used for the agreement. * @param agreementClass The agreement class address. * @param agreementId The agreementId * @param agreementData The agreement data (non-compressed) * @param cbdata The data returned from the before-hook callback. * @param ctx The context data. * @return newCtx The current context of the transaction. * * @custom:note * - State changes is permitted. * - Revert is not permitted. */ function afterAgreementTerminated( ISuperToken superToken, address agreementClass, bytes32 agreementId, bytes calldata agreementData, bytes calldata cbdata, bytes calldata ctx ) external returns (bytes memory newCtx); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; 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.4; /** * @title Super app definitions library * @author Superfluid */ library SuperAppDefinitions { /************************************************************************** / App manifest config word /**************************************************************************/ /* * App level is a way to allow the app to whitelist what other app it can * interact with (aka. composite app feature). * * For more details, refer to the technical paper of superfluid protocol. */ uint256 constant internal APP_LEVEL_MASK = 0xFF; // The app is at the final level, hence it doesn't want to interact with any other app uint256 constant internal APP_LEVEL_FINAL = 1 << 0; // The app is at the second level, it may interact with other final level apps if whitelisted uint256 constant internal APP_LEVEL_SECOND = 1 << 1; function getAppCallbackLevel(uint256 configWord) internal pure returns (uint8) { return uint8(configWord & APP_LEVEL_MASK); } uint256 constant internal APP_JAIL_BIT = 1 << 15; function isAppJailed(uint256 configWord) internal pure returns (bool) { return (configWord & SuperAppDefinitions.APP_JAIL_BIT) > 0; } /************************************************************************** / Callback implementation bit masks /**************************************************************************/ uint256 constant internal AGREEMENT_CALLBACK_NOOP_BITMASKS = 0xFF << 32; uint256 constant internal BEFORE_AGREEMENT_CREATED_NOOP = 1 << (32 + 0); uint256 constant internal AFTER_AGREEMENT_CREATED_NOOP = 1 << (32 + 1); uint256 constant internal BEFORE_AGREEMENT_UPDATED_NOOP = 1 << (32 + 2); uint256 constant internal AFTER_AGREEMENT_UPDATED_NOOP = 1 << (32 + 3); uint256 constant internal BEFORE_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 4); uint256 constant internal AFTER_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 5); /************************************************************************** / App Jail Reasons /**************************************************************************/ uint256 constant internal APP_RULE_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 appCallbackLevel, uint8 callType) { appCallbackLevel = uint8(callInfo & CALL_INFO_APP_LEVEL_MASK); callType = uint8((callInfo & CALL_INFO_CALL_TYPE_MASK) >> CALL_INFO_CALL_TYPE_SHIFT); } function encodeCallInfo(uint8 appCallbackLevel, uint8 callType) internal pure returns (uint256 callInfo) { return uint256(appCallbackLevel) | (uint256(callType) << CALL_INFO_CALL_TYPE_SHIFT); } } /** * @title Flow Operator definitions library * @author Superfluid */ library FlowOperatorDefinitions { uint8 constant internal AUTHORIZE_FLOW_OPERATOR_CREATE = uint8(1) << 0; uint8 constant internal AUTHORIZE_FLOW_OPERATOR_UPDATE = uint8(1) << 1; uint8 constant internal AUTHORIZE_FLOW_OPERATOR_DELETE = uint8(1) << 2; uint8 constant internal AUTHORIZE_FULL_CONTROL = AUTHORIZE_FLOW_OPERATOR_CREATE | AUTHORIZE_FLOW_OPERATOR_UPDATE | AUTHORIZE_FLOW_OPERATOR_DELETE; uint8 constant internal REVOKE_FLOW_OPERATOR_CREATE = ~(uint8(1) << 0); uint8 constant internal REVOKE_FLOW_OPERATOR_UPDATE = ~(uint8(1) << 1); uint8 constant internal REVOKE_FLOW_OPERATOR_DELETE = ~(uint8(1) << 2); function isPermissionsClean(uint8 permissions) internal pure returns (bool) { return ( permissions & ~(AUTHORIZE_FLOW_OPERATOR_CREATE | AUTHORIZE_FLOW_OPERATOR_UPDATE | AUTHORIZE_FLOW_OPERATOR_DELETE) ) == uint8(0); } } /** * @title Batch operation library * @author Superfluid */ library BatchOperation { /** * @dev ERC20.approve batch operation type * * Call spec: * ISuperToken(target).operationApprove( * abi.decode(data, (address spender, uint256 amount)) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_APPROVE = 1; /** * @dev ERC20.transferFrom batch operation type * * Call spec: * ISuperToken(target).operationTransferFrom( * abi.decode(data, (address sender, address recipient, uint256 amount) * ) */ uint32 constant internal OPERATION_TYPE_ERC20_TRANSFER_FROM = 2; /** * @dev 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; } } /** * @title Superfluid Common Custom Errors and Error Codes * @author Superfluid */ library SuperfluidErrors { /************************************************************************** / Shared Custom Errors /**************************************************************************/ error APP_RULE(uint256 _code); // uses SuperAppDefinitions' App Jail Reasons // The Error Code Reference refers to the types of errors within a range, // e.g. ALREADY_EXISTS and DOES_NOT_EXIST error codes will live between // 1000-1099 for Constant Flow Agreement error codes. // Error Code Reference error ALREADY_EXISTS(uint256 _code); // 0 - 99 error DOES_NOT_EXIST(uint256 _code); // 0 - 99 error INSUFFICIENT_BALANCE(uint256 _code); // 100 - 199 error MUST_BE_CONTRACT(uint256 _code); // 200 - 299 error ONLY_LISTED_AGREEMENT(uint256 _code); // 300 - 399 error ONLY_HOST(uint256 _code); // 400 - 499 error ZERO_ADDRESS(uint256 _code); // 500 - 599 /************************************************************************** / Error Codes /**************************************************************************/ // 1000 - 1999 | Constant Flow Agreement uint256 constant internal CFA_FLOW_ALREADY_EXISTS = 1000; uint256 constant internal CFA_FLOW_DOES_NOT_EXIST = 1001; uint256 constant internal CFA_INSUFFICIENT_BALANCE = 1100; uint256 constant internal CFA_ZERO_ADDRESS_SENDER = 1500; uint256 constant internal CFA_ZERO_ADDRESS_RECEIVER = 1501; // 2000 - 2999 | Instant Distribution Agreement uint256 constant internal IDA_INDEX_ALREADY_EXISTS = 2000; uint256 constant internal IDA_INDEX_DOES_NOT_EXIST = 2001; uint256 constant internal IDA_SUBSCRIPTION_DOES_NOT_EXIST = 2002; uint256 constant internal IDA_SUBSCRIPTION_ALREADY_APPROVED = 2003; uint256 constant internal IDA_SUBSCRIPTION_IS_NOT_APPROVED = 2004; uint256 constant internal IDA_INSUFFICIENT_BALANCE = 2100; uint256 constant internal IDA_ZERO_ADDRESS_SUBSCRIBER = 2500; // 3000 - 3999 | Host uint256 constant internal HOST_AGREEMENT_ALREADY_REGISTERED = 3000; uint256 constant internal HOST_AGREEMENT_IS_NOT_REGISTERED = 3001; uint256 constant internal HOST_SUPER_APP_ALREADY_REGISTERED = 3002; uint256 constant internal HOST_MUST_BE_CONTRACT = 3200; uint256 constant internal HOST_ONLY_LISTED_AGREEMENT = 3300; // 4000 - 4999 | Superfluid Governance II uint256 constant internal SF_GOV_MUST_BE_CONTRACT = 4200; // 5000 - 5999 | SuperfluidToken uint256 constant internal SF_TOKEN_AGREEMENT_ALREADY_EXISTS = 5000; uint256 constant internal SF_TOKEN_AGREEMENT_DOES_NOT_EXIST = 5001; uint256 constant internal SF_TOKEN_BURN_INSUFFICIENT_BALANCE = 5100; uint256 constant internal SF_TOKEN_MOVE_INSUFFICIENT_BALANCE = 5101; uint256 constant internal SF_TOKEN_ONLY_LISTED_AGREEMENT = 5300; uint256 constant internal SF_TOKEN_ONLY_HOST = 5400; // 6000 - 6999 | SuperToken uint256 constant internal SUPER_TOKEN_ONLY_HOST = 6400; uint256 constant internal SUPER_TOKEN_APPROVE_FROM_ZERO_ADDRESS = 6500; uint256 constant internal SUPER_TOKEN_APPROVE_TO_ZERO_ADDRESS = 6501; uint256 constant internal SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS = 6502; uint256 constant internal SUPER_TOKEN_MINT_TO_ZERO_ADDRESS = 6503; uint256 constant internal SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS = 6504; uint256 constant internal SUPER_TOKEN_TRANSFER_TO_ZERO_ADDRESS = 6505; // 7000 - 7999 | SuperToken Factory uint256 constant internal SUPER_TOKEN_FACTORY_ONLY_HOST = 7400; uint256 constant internal SUPER_TOKEN_FACTORY_ZERO_ADDRESS = 7500; // 8000 - 8999 | Agreement Base uint256 constant internal AGREEMENT_BASE_ONLY_HOST = 8400; }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.8.4; import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol"; import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol"; import { SuperfluidErrors } from "../superfluid/Definitions.sol"; /** * @title Constant Flow Agreement interface * @author Superfluid */ abstract contract IConstantFlowAgreementV1 is ISuperAgreement { /************************************************************************** * Errors *************************************************************************/ error CFA_ACL_NO_SENDER_CREATE(); error CFA_ACL_NO_SENDER_UPDATE(); error CFA_ACL_OPERATOR_NO_CREATE_PERMISSIONS(); error CFA_ACL_OPERATOR_NO_UPDATE_PERMISSIONS(); error CFA_ACL_OPERATOR_NO_DELETE_PERMISSIONS(); error CFA_ACL_FLOW_RATE_ALLOWANCE_EXCEEDED(); error CFA_ACL_UNCLEAN_PERMISSIONS(); error CFA_ACL_NO_SENDER_FLOW_OPERATOR(); error CFA_ACL_NO_NEGATIVE_ALLOWANCE(); error CFA_DEPOSIT_TOO_BIG(); error CFA_FLOW_RATE_TOO_BIG(); error CFA_NON_CRITICAL_SENDER(); error CFA_INVALID_FLOW_RATE(); error CFA_NO_SELF_FLOW(); /// @dev ISuperAgreement.agreementType implementation function agreementType() external override pure returns (bytes32) { return keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1"); } /** * @notice Get the maximum flow rate allowed with the deposit * @dev The deposit is clipped and rounded down * @param deposit Deposit amount used for creating the flow * @return flowRate The maximum flow rate */ function getMaximumFlowRateFromDeposit( ISuperfluidToken token, uint256 deposit) external view virtual returns (int96 flowRate); /** * @notice Get the deposit required for creating the flow * @dev Calculates the deposit based on the liquidationPeriod and flowRate * @param flowRate Flow rate to be tested * @return deposit The deposit amount based on flowRate and liquidationPeriod * @custom:note * - if calculated deposit (flowRate * liquidationPeriod) is less * than the minimum deposit, we use the minimum deposit otherwise * we use the calculated deposit */ function getDepositRequiredForFlowRate( ISuperfluidToken token, int96 flowRate) external view virtual returns (uint256 deposit); /** * @dev Returns whether it is the patrician period based on host.getNow() * @param account The account we are interested in * @return isCurrentlyPatricianPeriod Whether it is currently the patrician period dictated by governance * @return timestamp The value of host.getNow() */ function isPatricianPeriodNow( ISuperfluidToken token, address account) external view virtual returns (bool isCurrentlyPatricianPeriod, uint256 timestamp); /** * @dev Returns whether it is the patrician period based on timestamp * @param account The account we are interested in * @param timestamp The timestamp we are interested in observing the result of isPatricianPeriod * @return bool Whether it is currently the patrician period dictated by governance */ function isPatricianPeriod( ISuperfluidToken token, address account, uint256 timestamp ) public view virtual returns (bool); /** * @dev msgSender from `ctx` updates permissions for the `flowOperator` with `flowRateAllowance` * @param token Super token address * @param flowOperator The permission grantee address * @param permissions A bitmask representation of the granted permissions * @param flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function updateFlowOperatorPermissions( ISuperfluidToken token, address flowOperator, uint8 permissions, int96 flowRateAllowance, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev msgSender from `ctx` grants `flowOperator` all permissions with flowRateAllowance as type(int96).max * @param token Super token address * @param flowOperator The permission grantee address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function authorizeFlowOperatorWithFullControl( ISuperfluidToken token, address flowOperator, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice msgSender from `ctx` revokes `flowOperator` create/update/delete permissions * @dev `permissions` and `flowRateAllowance` will both be set to 0 * @param token Super token address * @param flowOperator The permission grantee address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function revokeFlowOperatorWithFullControl( ISuperfluidToken token, address flowOperator, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Get the permissions of a flow operator between `sender` and `flowOperator` for `token` * @param token Super token address * @param sender The permission granter address * @param flowOperator The permission grantee address * @return flowOperatorId The keccak256 hash of encoded string "flowOperator", sender and flowOperator * @return permissions A bitmask representation of the granted permissions * @return flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) */ function getFlowOperatorData( ISuperfluidToken token, address sender, address flowOperator ) public view virtual returns ( bytes32 flowOperatorId, uint8 permissions, int96 flowRateAllowance ); /** * @notice Get flow operator using flowOperatorId * @param token Super token address * @param flowOperatorId The keccak256 hash of encoded string "flowOperator", sender and flowOperator * @return permissions A bitmask representation of the granted permissions * @return flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) */ function getFlowOperatorDataByID( ISuperfluidToken token, bytes32 flowOperatorId ) external view virtual returns ( uint8 permissions, int96 flowRateAllowance ); /** * @notice Create a flow betwen ctx.msgSender and receiver * @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver * @param token Super token address * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - AgreementCreated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * @custom:note * - A deposit is taken as safety margin for the solvency agents * - A extra gas fee may be taken to pay for solvency agent liquidations */ function createFlow( ISuperfluidToken token, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Create a flow between sender and receiver * @dev A flow created by an approved flow operator (see above for details on callbacks) * @param token Super token address * @param sender Flow sender address (has granted permissions) * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function createFlowByOperator( ISuperfluidToken token, address sender, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Update the flow rate between ctx.msgSender and receiver * @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver * @param token Super token address * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * * @custom:callbacks * - AgreementUpdated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * @custom:note * - Only the flow sender may update the flow rate * - Even if the flow rate is zero, the flow is not deleted * from the system * - Deposit amount will be adjusted accordingly * - No new gas fee is charged */ function updateFlow( ISuperfluidToken token, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Update a flow between sender and receiver * @dev A flow updated by an approved flow operator (see above for details on callbacks) * @param token Super token address * @param sender Flow sender address (has granted permissions) * @param receiver Flow receiver address * @param flowRate New flow rate in amount per second * @param ctx Context bytes (see ISuperfluid.sol for Context struct) */ function updateFlowByOperator( ISuperfluidToken token, address sender, address receiver, int96 flowRate, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev Get the flow data between `sender` and `receiver` of `token` * @param token Super token address * @param sender Flow 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 * * @custom:callbacks * - AgreementTerminated * - agreementId - can be used in getFlowByID * - agreementData - abi.encode(address flowSender, address flowReceiver) * * @custom:note * - Both flow sender and receiver may delete the flow * - If Sender account is insolvent or in critical state, a solvency agent may * also terminate the agreement * - Gas fee may be returned to the sender */ function deleteFlow( ISuperfluidToken token, address sender, address receiver, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @notice Delete the flow between sender and receiver * @dev A flow deleted by an approved flow operator (see above for details on callbacks) * @param token Super token address * @param ctx Context bytes (see ISuperfluid.sol for Context struct) * @param receiver Flow receiver address */ function deleteFlowByOperator( ISuperfluidToken token, address sender, address receiver, bytes calldata ctx ) external virtual returns(bytes memory newCtx); /** * @dev Flow operator updated event * @param token Super token address * @param sender Flow sender address * @param flowOperator Flow operator address * @param permissions Octo bitmask representation of permissions * @param flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down) */ event FlowOperatorUpdated( ISuperfluidToken indexed token, address indexed sender, address indexed flowOperator, uint8 permissions, int96 flowRateAllowance ); /** * @dev Flow updated event * @param token Super token address * @param sender Flow sender address * @param receiver Flow recipient address * @param flowRate Flow rate in amount per second for this flow * @param totalSenderFlowRate Total flow rate in amount per second for the sender * @param totalReceiverFlowRate Total flow rate in amount per second for the receiver * @param userData The user provided data * */ event FlowUpdated( ISuperfluidToken indexed token, address indexed sender, address indexed receiver, int96 flowRate, int256 totalSenderFlowRate, int256 totalReceiverFlowRate, bytes userData ); /** * @dev Flow updated extension event * @param flowOperator Flow operator address - the Context.msgSender * @param deposit The deposit amount for the stream */ event FlowUpdatedExtension( address indexed flowOperator, uint256 deposit ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC777/IERC777.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777Token standard as defined in the EIP. * * This contract uses the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let * token holders and recipients react to token movements by using setting implementers * for the associated interfaces in said registry. See {IERC1820Registry} and * {ERC1820Implementer}. */ interface IERC777 { /** * @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`. * * Note that some additional user `data` and `operatorData` can be logged in the event. */ event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); /** * @dev Emitted when `operator` destroys `amount` tokens from `account`. * * Note that some additional user `data` and `operatorData` can be logged in the event. */ event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); /** * @dev Emitted when `operator` is made operator for `tokenHolder` */ event AuthorizedOperator(address indexed operator, address indexed tokenHolder); /** * @dev Emitted when `operator` is revoked its operator status for `tokenHolder` */ event RevokedOperator(address indexed operator, address indexed tokenHolder); /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * For most token contracts, this value will equal 1. */ function granularity() external view returns (uint256); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address owner) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send( address recipient, uint256 amount, bytes calldata data ) external; /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply. * * If a send hook is registered for the caller, the corresponding function * will be called with `data` and empty `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata data) external; /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * Emits an {AuthorizedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external; /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * Emits a {RevokedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function revokeOperator(address operator) external; /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `data` and `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; event Sent( address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "london", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ISuperfluid","name":"host","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CFA_FWD_INVALID_FLOW_RATE","type":"error"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"int96","name":"flowrate","type":"int96"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"createFlow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"deleteFlow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"getAccountFlowInfo","outputs":[{"internalType":"uint256","name":"lastUpdated","type":"uint256"},{"internalType":"int96","name":"flowrate","type":"int96"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"uint256","name":"owedDeposit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"}],"name":"getAccountFlowrate","outputs":[{"internalType":"int96","name":"flowrate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"int96","name":"flowrate","type":"int96"}],"name":"getBufferAmountByFlowrate","outputs":[{"internalType":"uint256","name":"bufferAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"getFlowInfo","outputs":[{"internalType":"uint256","name":"lastUpdated","type":"uint256"},{"internalType":"int96","name":"flowrate","type":"int96"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"uint256","name":"owedDeposit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"flowOperator","type":"address"}],"name":"getFlowOperatorPermissions","outputs":[{"internalType":"uint8","name":"permissions","type":"uint8"},{"internalType":"int96","name":"flowrateAllowance","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"getFlowrate","outputs":[{"internalType":"int96","name":"flowrate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"flowOperator","type":"address"}],"name":"grantPermissions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"flowOperator","type":"address"}],"name":"revokePermissions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"int96","name":"flowrate","type":"int96"}],"name":"setFlowrate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"int96","name":"flowrate","type":"int96"}],"name":"setFlowrateFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"int96","name":"flowrate","type":"int96"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"updateFlow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"address","name":"flowOperator","type":"address"},{"internalType":"uint8","name":"permissions","type":"uint8"},{"internalType":"int96","name":"flowrateAllowance","type":"int96"}],"name":"updateFlowOperatorPermissions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b50604051620017db380380620017db8339810160408190526200003491620000ef565b6001600160a01b0381166080819052604051635b69006f60e11b81527fa9214cc96615e0085d3bb077758db69497dc2dce3b2b1e97bc93c3d18d83efd3600482015263b6d200de90602401602060405180830381865afa1580156200009d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000c39190620000ef565b6001600160a01b031660a0525062000116565b6001600160a01b0381168114620000ec57600080fd5b50565b6000602082840312156200010257600080fd5b81516200010f81620000d6565b9392505050565b60805160a051611628620001b36000396000818161029a01528181610366015281816103fb015281816104ab01528181610520015281816105de015281816106e901528181610766015281816107aa01528181610851015281816108ef0152818161092501528181610abc01528181610b4101528181610bb001528181610bf30152610c2d015260008181610d150152610d8701526116286000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063308855911161008c5780637243fb93116100665780637243fb9314610222578063b4b333c614610235578063c5ad5c1a14610248578063e15536b61461025b57600080fd5b806330885591146101cd5780634d3f60f9146101e057806357e6aa361461020f57600080fd5b80630f1ac495116100c85780630f1ac4951461014b5780631d8b65261461018157806322c904d9146101a75780632860fd93146101ba57600080fd5b806309f0b495146100ef5780630bd0728d146101155780630c03399114610138575b600080fd5b6101026100fd366004610f76565b61026e565b6040519081526020015b60405180910390f35b610128610123366004610faf565b61030e565b604051901515815260200161010c565b610128610146366004611080565b61031d565b61015e610159366004610faf565b610336565b60408051948552600b9390930b602085015291830152606082015260800161010c565b61019461018f366004611108565b6103e1565b604051600b9190910b815260200161010c565b6101946101b5366004610faf565b610481565b61015e6101c8366004611108565b610518565b6101286101db366004611162565b6105c0565b6101f36101ee366004611108565b6105d9565b6040805160ff9093168352600b9190910b60208301520161010c565b61012861021d3660046111be565b610679565b610128610230366004610faf565b610687565b6101286102433660046111fe565b6106a2565b610128610256366004611273565b6106b0565b610128610269366004611080565b6106be565b6040516346ccbfb760e11b81526001600160a01b038381166004830152600b83900b60248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638d997f6e90604401602060405180830381865afa1580156102e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030791906112b4565b9392505050565b600061030783836000806106cd565b600061032c868686868661078d565b9695505050505050565b604051630f1ac49560e01b81526001600160a01b03838116600483015282811660248301526000918291829182917f00000000000000000000000000000000000000000000000000000000000000001690630f1ac49590604401608060405180830381865afa1580156103ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d191906112cd565b9299919850965090945092505050565b604051631cd43d1160e31b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e6a1e888906104349087908790879060040161130b565b608060405180830381865afa158015610451573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047591906112cd565b50909695505050505050565b60405163e8e7e2d160e01b81526001600160a01b03838116600483015282811660248301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e8e7e2d190604401602060405180830381865afa1580156104f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610307919061132e565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e6a1e8888888886040518463ffffffff1660e01b815260040161056e9392919061130b565b608060405180830381865afa15801561058b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105af91906112cd565b929a91995097509095509350505050565b60006105ce858585856106cd565b90505b949350505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031662422bbe8686866040518463ffffffff1660e01b815260040161062b9392919061130b565b606060405180830381865afa158015610648573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066c919061134b565b9097909650945050505050565b60006105d184338585610920565b6000610307838360076b7fffffffffffffffffffffff6106cd565b60006105ce85858585610a7d565b60006105ce85858585610920565b600061032c8686868686610bd6565b6040805160008082526020820190925281906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063811b3d4090610725908990899089908990604481016113d3565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b949094179093528051600081529283019052925061032c91507f0000000000000000000000000000000000000000000000000000000000000000908390610c5c565b6000806001600160a01b0386163314610847576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663354b95908888888860005b6040519080825280601f01601f191660200182016040528015610800576020820181803683370190505b50604051602401610815959493929190611412565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506108e8565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166350209a6288878760005b6040519080825280601f01601f1916602001820160405280156108a6576020820181803683370190505b506040516024016108ba9493929190611450565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050505b90506109157f00000000000000000000000000000000000000000000000000000000000000008285610c5c565b979650505050505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e6a1e8888787876040518463ffffffff1660e01b81526004016109739392919061130b565b608060405180830381865afa158015610990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b491906112cd565b5050915050600083600b0b1315610a2f5780600b0b6000036109f8576040805160008152602081019091526109f0908790879087908790610bd6565b9150506105d1565b82600b0b81600b0b14610a25576040805160008152602081019091526109f090879087908790879061078d565b60019150506105d1565b82600b0b600003610a6457600081600b0b1315610a25576040805160008152602081019091526109f090879087908790610a7d565b60405163cea9aa5f60e01b815260040160405180910390fd5b6000806001600160a01b038516331480610a9f57506001600160a01b03841633145b610b28576040805160008152602081019091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634c8b181f90610af69089908990899060448101611486565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610ba9565b6040805160008152602081019091526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b4b333c690610b7b9089908990899060448101611486565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050505b905061032c7f00000000000000000000000000000000000000000000000000000000000000008285610c5c565b6000806001600160a01b0386163314610c23576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166394229ecb8888888860006107d6565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166362fc305e888787600061087c565b604080516001808252818301909252600091829190816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081610c76579050509050604051806060016040528060c963ffffffff168152602001866001600160a01b031681526020018585604051602001610ce19291906114ba565b60405160208183030381529060405281525081600081518110610d0657610d066114e8565b602002602001018190525060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663670e77e383604051602401610d5391906114fe565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505090506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168333604051602001610dc292919061158c565b60408051601f1981840301815290829052610ddc916115c3565b6000604051808303816000865af19150503d8060008114610e19576040519150601f19603f3d011682016040523d82523d6000602084013e610e1e565b606091505b509150915081610e3157610e3181610e3f565b506001979650505050505050565b600481511015610e965760405162461bcd60e51b815260206004820152601a60248201527f43616c6c5574696c733a2074617267657420726576657274282900000000000060448201526064015b60405180910390fd5b602081015163b1b7848f60e01b6001600160e01b0319821601610f465760408051808201825260208082527f43616c6c5574696c733a207461726765742070616e69636b65643a2030785f5f90820190815260248501517f43616c6c5574696c733a207461726765742070616e69636b65643a2030780000600482811c600f908116603090810160081b918516011791909117909252925162461bcd60e51b8152919291610e8d918491016115df565b81518060208401fd5b50565b6001600160a01b0381168114610f4f57600080fd5b80600b0b8114610f4f57600080fd5b60008060408385031215610f8957600080fd5b8235610f9481610f52565b91506020830135610fa481610f67565b809150509250929050565b60008060408385031215610fc257600080fd5b8235610fcd81610f52565b91506020830135610fa481610f52565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261100457600080fd5b813567ffffffffffffffff8082111561101f5761101f610fdd565b604051601f8301601f19908116603f0116810190828211818310171561104757611047610fdd565b8160405283815286602085880101111561106057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561109857600080fd5b85356110a381610f52565b945060208601356110b381610f52565b935060408601356110c381610f52565b925060608601356110d381610f67565b9150608086013567ffffffffffffffff8111156110ef57600080fd5b6110fb88828901610ff3565b9150509295509295909350565b60008060006060848603121561111d57600080fd5b833561112881610f52565b9250602084013561113881610f52565b9150604084013561114881610f52565b809150509250925092565b60ff81168114610f4f57600080fd5b6000806000806080858703121561117857600080fd5b843561118381610f52565b9350602085013561119381610f52565b925060408501356111a381611153565b915060608501356111b381610f67565b939692955090935050565b6000806000606084860312156111d357600080fd5b83356111de81610f52565b925060208401356111ee81610f52565b9150604084013561114881610f67565b6000806000806080858703121561121457600080fd5b843561121f81610f52565b9350602085013561122f81610f52565b9250604085013561123f81610f52565b9150606085013567ffffffffffffffff81111561125b57600080fd5b61126787828801610ff3565b91505092959194509250565b6000806000806080858703121561128957600080fd5b843561129481610f52565b935060208501356112a481610f52565b925060408501356111a381610f52565b6000602082840312156112c657600080fd5b5051919050565b600080600080608085870312156112e357600080fd5b8451935060208501516112f581610f67565b6040860151606090960151949790965092505050565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561134057600080fd5b815161030781610f67565b60008060006060848603121561136057600080fd5b83519250602084015161137281611153565b604085015190925061114881610f67565b60005b8381101561139e578181015183820152602001611386565b50506000910152565b600081518084526113bf816020860160208601611383565b601f01601f19169290920160200192915050565b6001600160a01b0386811682528516602082015260ff84166040820152600b83900b606082015260a060808201819052600090610915908301846113a7565b6001600160a01b038681168252858116602083015284166040820152600b83900b606082015260a060808201819052600090610915908301846113a7565b6001600160a01b03858116825284166020820152600b83900b604082015260806060820181905260009061032c908301846113a7565b6001600160a01b03858116825284811660208301528316604082015260806060820181905260009061032c908301846113a7565b6040815260006114cd60408301856113a7565b82810360208401526114df81856113a7565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561157e57888303603f190185528151805163ffffffff168452878101516001600160a01b031688850152860151606087850181905261156a818601836113a7565b968901969450505090860190600101611525565b509098975050505050505050565b6000835161159e818460208801611383565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b600082516115d5818460208701611383565b9190910192915050565b60208152600061030760208301846113a756fea2646970667358221220a0c1c529333797349b5ec212cb7fcb57b06d7c1a39e211da36f599a4248c43a164736f6c63430008100033000000000000000000000000567c4b141ed61923967ca25ef4906c8781069a10
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063308855911161008c5780637243fb93116100665780637243fb9314610222578063b4b333c614610235578063c5ad5c1a14610248578063e15536b61461025b57600080fd5b806330885591146101cd5780634d3f60f9146101e057806357e6aa361461020f57600080fd5b80630f1ac495116100c85780630f1ac4951461014b5780631d8b65261461018157806322c904d9146101a75780632860fd93146101ba57600080fd5b806309f0b495146100ef5780630bd0728d146101155780630c03399114610138575b600080fd5b6101026100fd366004610f76565b61026e565b6040519081526020015b60405180910390f35b610128610123366004610faf565b61030e565b604051901515815260200161010c565b610128610146366004611080565b61031d565b61015e610159366004610faf565b610336565b60408051948552600b9390930b602085015291830152606082015260800161010c565b61019461018f366004611108565b6103e1565b604051600b9190910b815260200161010c565b6101946101b5366004610faf565b610481565b61015e6101c8366004611108565b610518565b6101286101db366004611162565b6105c0565b6101f36101ee366004611108565b6105d9565b6040805160ff9093168352600b9190910b60208301520161010c565b61012861021d3660046111be565b610679565b610128610230366004610faf565b610687565b6101286102433660046111fe565b6106a2565b610128610256366004611273565b6106b0565b610128610269366004611080565b6106be565b6040516346ccbfb760e11b81526001600160a01b038381166004830152600b83900b60248301526000917f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed90911690638d997f6e90604401602060405180830381865afa1580156102e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030791906112b4565b9392505050565b600061030783836000806106cd565b600061032c868686868661078d565b9695505050505050565b604051630f1ac49560e01b81526001600160a01b03838116600483015282811660248301526000918291829182917f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed1690630f1ac49590604401608060405180830381865afa1580156103ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d191906112cd565b9299919850965090945092505050565b604051631cd43d1160e31b81526000906001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed169063e6a1e888906104349087908790879060040161130b565b608060405180830381865afa158015610451573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047591906112cd565b50909695505050505050565b60405163e8e7e2d160e01b81526001600160a01b03838116600483015282811660248301526000917f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed9091169063e8e7e2d190604401602060405180830381865afa1580156104f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610307919061132e565b6000806000807f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed6001600160a01b031663e6a1e8888888886040518463ffffffff1660e01b815260040161056e9392919061130b565b608060405180830381865afa15801561058b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105af91906112cd565b929a91995097509095509350505050565b60006105ce858585856106cd565b90505b949350505050565b6000807f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed6001600160a01b031662422bbe8686866040518463ffffffff1660e01b815260040161062b9392919061130b565b606060405180830381865afa158015610648573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066c919061134b565b9097909650945050505050565b60006105d184338585610920565b6000610307838360076b7fffffffffffffffffffffff6106cd565b60006105ce85858585610a7d565b60006105ce85858585610920565b600061032c8686868686610bd6565b6040805160008082526020820190925281906001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed169063811b3d4090610725908990899089908990604481016113d3565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b949094179093528051600081529283019052925061032c91507f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed908390610c5c565b6000806001600160a01b0386163314610847576001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed1663354b95908888888860005b6040519080825280601f01601f191660200182016040528015610800576020820181803683370190505b50604051602401610815959493929190611412565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506108e8565b6001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed166350209a6288878760005b6040519080825280601f01601f1916602001820160405280156108a6576020820181803683370190505b506040516024016108ba9493929190611450565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050505b90506109157f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed8285610c5c565b979650505050505050565b6000807f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed6001600160a01b031663e6a1e8888787876040518463ffffffff1660e01b81526004016109739392919061130b565b608060405180830381865afa158015610990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b491906112cd565b5050915050600083600b0b1315610a2f5780600b0b6000036109f8576040805160008152602081019091526109f0908790879087908790610bd6565b9150506105d1565b82600b0b81600b0b14610a25576040805160008152602081019091526109f090879087908790879061078d565b60019150506105d1565b82600b0b600003610a6457600081600b0b1315610a25576040805160008152602081019091526109f090879087908790610a7d565b60405163cea9aa5f60e01b815260040160405180910390fd5b6000806001600160a01b038516331480610a9f57506001600160a01b03841633145b610b28576040805160008152602081019091526001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed1690634c8b181f90610af69089908990899060448101611486565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050610ba9565b6040805160008152602081019091526001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed169063b4b333c690610b7b9089908990899060448101611486565b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050505b905061032c7f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed8285610c5c565b6000806001600160a01b0386163314610c23576001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed166394229ecb8888888860006107d6565b6001600160a01b037f000000000000000000000000204c6f131bb7f258b2ea1593f5309911d8e458ed166362fc305e888787600061087c565b604080516001808252818301909252600091829190816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081610c76579050509050604051806060016040528060c963ffffffff168152602001866001600160a01b031681526020018585604051602001610ce19291906114ba565b60405160208183030381529060405281525081600081518110610d0657610d066114e8565b602002602001018190525060007f000000000000000000000000567c4b141ed61923967ca25ef4906c8781069a106001600160a01b031663670e77e383604051602401610d5391906114fe565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505090506000807f000000000000000000000000567c4b141ed61923967ca25ef4906c8781069a106001600160a01b03168333604051602001610dc292919061158c565b60408051601f1981840301815290829052610ddc916115c3565b6000604051808303816000865af19150503d8060008114610e19576040519150601f19603f3d011682016040523d82523d6000602084013e610e1e565b606091505b509150915081610e3157610e3181610e3f565b506001979650505050505050565b600481511015610e965760405162461bcd60e51b815260206004820152601a60248201527f43616c6c5574696c733a2074617267657420726576657274282900000000000060448201526064015b60405180910390fd5b602081015163b1b7848f60e01b6001600160e01b0319821601610f465760408051808201825260208082527f43616c6c5574696c733a207461726765742070616e69636b65643a2030785f5f90820190815260248501517f43616c6c5574696c733a207461726765742070616e69636b65643a2030780000600482811c600f908116603090810160081b918516011791909117909252925162461bcd60e51b8152919291610e8d918491016115df565b81518060208401fd5b50565b6001600160a01b0381168114610f4f57600080fd5b80600b0b8114610f4f57600080fd5b60008060408385031215610f8957600080fd5b8235610f9481610f52565b91506020830135610fa481610f67565b809150509250929050565b60008060408385031215610fc257600080fd5b8235610fcd81610f52565b91506020830135610fa481610f52565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261100457600080fd5b813567ffffffffffffffff8082111561101f5761101f610fdd565b604051601f8301601f19908116603f0116810190828211818310171561104757611047610fdd565b8160405283815286602085880101111561106057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561109857600080fd5b85356110a381610f52565b945060208601356110b381610f52565b935060408601356110c381610f52565b925060608601356110d381610f67565b9150608086013567ffffffffffffffff8111156110ef57600080fd5b6110fb88828901610ff3565b9150509295509295909350565b60008060006060848603121561111d57600080fd5b833561112881610f52565b9250602084013561113881610f52565b9150604084013561114881610f52565b809150509250925092565b60ff81168114610f4f57600080fd5b6000806000806080858703121561117857600080fd5b843561118381610f52565b9350602085013561119381610f52565b925060408501356111a381611153565b915060608501356111b381610f67565b939692955090935050565b6000806000606084860312156111d357600080fd5b83356111de81610f52565b925060208401356111ee81610f52565b9150604084013561114881610f67565b6000806000806080858703121561121457600080fd5b843561121f81610f52565b9350602085013561122f81610f52565b9250604085013561123f81610f52565b9150606085013567ffffffffffffffff81111561125b57600080fd5b61126787828801610ff3565b91505092959194509250565b6000806000806080858703121561128957600080fd5b843561129481610f52565b935060208501356112a481610f52565b925060408501356111a381610f52565b6000602082840312156112c657600080fd5b5051919050565b600080600080608085870312156112e357600080fd5b8451935060208501516112f581610f67565b6040860151606090960151949790965092505050565b6001600160a01b0393841681529183166020830152909116604082015260600190565b60006020828403121561134057600080fd5b815161030781610f67565b60008060006060848603121561136057600080fd5b83519250602084015161137281611153565b604085015190925061114881610f67565b60005b8381101561139e578181015183820152602001611386565b50506000910152565b600081518084526113bf816020860160208601611383565b601f01601f19169290920160200192915050565b6001600160a01b0386811682528516602082015260ff84166040820152600b83900b606082015260a060808201819052600090610915908301846113a7565b6001600160a01b038681168252858116602083015284166040820152600b83900b606082015260a060808201819052600090610915908301846113a7565b6001600160a01b03858116825284166020820152600b83900b604082015260806060820181905260009061032c908301846113a7565b6001600160a01b03858116825284811660208301528316604082015260806060820181905260009061032c908301846113a7565b6040815260006114cd60408301856113a7565b82810360208401526114df81856113a7565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561157e57888303603f190185528151805163ffffffff168452878101516001600160a01b031688850152860151606087850181905261156a818601836113a7565b968901969450505090860190600101611525565b509098975050505050505050565b6000835161159e818460208801611383565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b600082516115d5818460208701611383565b9190910192915050565b60208152600061030760208301846113a756fea2646970667358221220a0c1c529333797349b5ec212cb7fcb57b06d7c1a39e211da36f599a4248c43a164736f6c63430008100033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000567c4b141ed61923967ca25ef4906c8781069a10
-----Decoded View---------------
Arg [0] : host (address): 0x567c4B141ED61923967cA25Ef4906C8781069a10
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000567c4b141ed61923967ca25ef4906c8781069a10
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.