Contract 0x6AEAeE5Fd4D05A741723D752D30EE4D72690A8f7

DeFi  
 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x6f13fe83042aceaca6fd41fbdd54db2e05b800f49fad6d1c63c6fd0eb1eda135Change Exit Rate359870902022-11-24 0:25:0212 days 13 mins ago0xe2b52fc1ad49b93f85c45315ecbad740f17b0e8e IN  Superfluid: TOGA0 MATIC0.016375311734.7
0x24db56f3df4fe82de5662228f8535f91e64a94fabfb9293238663e2c892b6b30Change Exit Rate359473962022-11-23 1:07:4612 days 23 hrs ago0xe2b52fc1ad49b93f85c45315ecbad740f17b0e8e IN  Superfluid: TOGA0 MATIC0.021025043244.8
0x614b442d341c4a0ea178454eb1e76c592256f92eb0c974a039158db7f5bfc844Change Exit Rate321180152022-08-20 16:33:55107 days 8 hrs ago0xf11b3c65e229f25467c6eea0a94e7b89d4f48de9 IN  Superfluid: TOGA0 MATIC0.014399999199 38.799999999
0x8db6a784c6e4714c344f6e15fa04dca5845879435d73049e5a5af398fc2d46e2Change Exit Rate312754532022-07-29 12:17:23129 days 12 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.012418611422 33.379415935
0x07f64150f618db52b5ae1946a8f47755d123f2472816bde15ef4418418afb435Change Exit Rate310691572022-07-24 1:51:19134 days 22 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.010624020051 30.000000145
0xde0bbf1950b5d0f492c4fc2596bc5590d5b5e4a70aff41b020c1d96170f38e69Change Exit Rate290264402022-06-01 8:35:27187 days 16 hrs ago0x6eaa11eec98c663ba096593cc779217a7e20665a IN  Superfluid: TOGA0 MATIC0.010659120006 30.000000018
0xa3aaa5557d32c93ff5c935b6f24e700521b9050b8f688aa98987d83f51ea366eChange Exit Rate289246232022-05-29 19:51:55190 days 4 hrs ago0x6eaa11eec98c663ba096593cc779217a7e20665a IN  Superfluid: TOGA0 MATIC0.011050718448 31.168205556
0x643069075bbba972ab134f6c9ff7ef3c768517a358aa04b87ae27bd9a6a7f6a9Change Exit Rate285622392022-05-20 20:59:21199 days 3 hrs ago0x9e3429a12547f86e0fdbb7d26dd49e6ce355b2cb IN  Superfluid: TOGA0 MATIC0.011309779668 31.831275946
0x8f5357a0debb8772a3a44b98f290c5e30b42d261584851329f1d3a76e79b0991Change Exit Rate284421732022-05-17 20:34:18202 days 4 hrs ago0x9e3429a12547f86e0fdbb7d26dd49e6ce355b2cb IN  Superfluid: TOGA0 MATIC0.010686830027 30.074857748
0x03998f360bf675f76363363920bf08cde0c1ad17d006a50ea94e534671bb3cd4Change Exit Rate280745442022-05-08 14:08:04211 days 10 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.015915894436 44.795145668
0xf5bc20ef0fe3f909e2fe301b54ff52eeef3ac7ade92a54684cee8287d0077fbcChange Exit Rate280313222022-05-07 12:11:32212 days 12 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.011962976682 33.669693228
0x0a05d74cfa931204fdea0c6ab4a10837133e3a61683117957d64c7ddd5f3dc79Change Exit Rate280313062022-05-07 12:11:00212 days 12 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.005059280361 33.737757399
0x920c9ef85afe72828660f258985ea0ef7b29e5421043105043c7612ccb8a9430Change Exit Rate279289932022-05-04 21:56:43215 days 2 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.011231865849 30.124840012
0x9acad3842e0e1c8eeef80ca5d3eca923cec2f2ab5204c5c7f1d7c18ddae43aafChange Exit Rate277148982022-04-29 11:33:02220 days 13 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.012221836231 31.233130335
0x6c622e9f7a4a27f3eed8a6c8655075bdda884863cd77e9209ea2310c94423197Change Exit Rate277148702022-04-29 11:32:02220 days 13 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.012094086427 32.251155149
0x07e5714953150685302f936e97e172fa8d8cd0b6aaa5555d405df4492115af05Change Exit Rate277148172022-04-29 11:30:16220 days 13 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.011956477051 30.555000005
0xc80da470a1fe233014d674697a4fb05c7ca2b08ca113d0396f19de50ad1b25e3Change Exit Rate277145962022-04-29 11:22:38220 days 13 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.013113204744 36.626812722
0xd1af1ea590df1685f555a133f0c85d7e9f6ed6e05ae095d1b4fac3e4355723e9Change Exit Rate277145722022-04-29 11:21:50220 days 13 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.012167546632 33.950006788
0xa2efdfa62fae951a9a53ba6ea835ee50bb418d6027f95a5aefda4b5e1d7fecc5Change Exit Rate272852062022-04-18 13:04:03231 days 11 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.014525357155 41.093606687
0xe2bd1566a2abfa42b462b2aa5884c4671c21c8fcacc656456c971bf1faccee51Change Exit Rate272824712022-04-18 11:24:47231 days 13 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.013698417654 38.800000155
0x90161cc610b6027f7850251c7ab92a3c3e7b09ccdf12c8ac60777bbdbbc02729Change Exit Rate272530742022-04-17 17:35:45232 days 7 hrs ago0x9e3429a12547f86e0fdbb7d26dd49e6ce355b2cb IN  Superfluid: TOGA0 MATIC0.010827960149 30.209750825
0x2d6914daf6e1b6d392fd454e3cd0b0e1188ac44c8152f76a8d378a9159747cafChange Exit Rate270155322022-04-11 16:49:42238 days 7 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.009476532024 30.428700862
0x050796e15c7bdc79604cc6c27b243727cbfa31b27535d7b4fd76d2bfb2837bc7Change Exit Rate270155132022-04-11 16:49:04238 days 7 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.009664986653 31.072331773
0xcb7d60cf9083c0962ad6037e2756222cdadd3e14f07f8b0a2575ffa4dad21081Change Exit Rate269660162022-04-10 11:12:05239 days 13 hrs ago0x9e3429a12547f86e0fdbb7d26dd49e6ce355b2cb IN  Superfluid: TOGA0 MATIC0.009465153285 30.428705992
0x0e77ac398c0418199d907ed054dad8a9c7e773ee68a389f53bdd067463c8008eChange Exit Rate268888332022-04-08 11:29:48241 days 13 hrs ago0xab7323b71b0f1c82c62719ab10cbe17148f38532 IN  Superfluid: TOGA0 MATIC0.009234391087 30.111130237
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TOGA

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 17 : TOGA.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity 0.7.6;

import {
    ISuperfluid,
    ISuperToken,
    ISuperfluidToken
} from "../interfaces/superfluid/ISuperfluid.sol";
import { IConstantFlowAgreementV1 } from "../interfaces/agreements/IConstantFlowAgreementV1.sol";

import { IERC1820Registry } from "@openzeppelin/contracts/introspection/IERC1820Registry.sol";
import { IERC777Recipient } from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol";

import { TokenCustodian } from "./TokenCustodian.sol";

/**
 * @title TOGA: Transparent Ongoing Auction
 *
 * TOGA is a simple implementation of a continuous auction.
 * It's used to designate PICs (Patrician In Charge) - a role defined per Super Token.
 * Anybody can become the PIC for a Super Token by staking the highest bond (denominated in the token).
 * Staking is done by simply using ERC777.send(), transferring the bond amount to be staked to this contract.
 * Via userData parameter (abi-encoded int96), an exitRate can be defined. If omitted, a default will be chosen.
 * The exitRate is the flowrate at which the bond is streamed back to the PIC.
 * Any rewards accrued by this contract (in general the whole token balance) become part of the bond.
 * When a PIC is outbid, the current bond is transferred to it with ERC777.send().
 *
 * changes in v2:
 * In case that send() fails (e.g. due to a reverting hook), the bond is transferred to a custodian contract.
 * Funds accumulated there can be withdrawn from there at any time.
 * The current PIC can increase its bond by sending more funds using ERC777.send().
 *
 * @author Superfluid
 */
interface ITOGAv1 {
    /**
     * @dev get the address of the current PIC for the given token.
     * @param token The token for which to get the PIC
     */
    function getCurrentPIC(ISuperToken token) external view returns(address pic);

    /**
     * @dev get info about the state - most importantly the bond amount - of the current PIC for the given token.
     * @param token The token for which to get PIC info
     * Notes:
     * The bond changes dynamically and can both grow or shrink between 2 blocks.
     * Even the PIC itself could change anytime, this being a continuous auction.
     * @return pic Address of the current PIC. Returns the ZERO address if not set
     * @return bond The current bond amount. Can shrink or grow over time, depending on exitRate and rewards accrued
     * @return exitRate The current flowrate of given tokens from the contract to the PIC
     */
    function getCurrentPICInfo(ISuperToken token) external view
        returns(address pic, uint256 bond, int96 exitRate);

    /**
     * @dev Get the exit rate set by default for the given token and bond amount
     * @param token The token for which to get info
     * @param bondAmount The bond amount for which to make the calculation
     * @return exitRate The exit rate set by default for a bid with the given bond amount for the given token
     */
    function getDefaultExitRateFor(ISuperToken token, uint256 bondAmount) external view returns(int96 exitRate);

    /**
     * @dev Get the max exit which can be set for the given token and bond amount
     * @param token The token for which to get info
     * @param bondAmount The bond amount for which to calculate the max exit rate
     * @return exitRate The max exit rate which can be set for the given bond amount and token
     *
     * This limit is enforced only at the time of setting or updating the flow from the contract to the PIC.
     */
    function getMaxExitRateFor(ISuperToken token, uint256 bondAmount) external view returns(int96 exitRate);

    /**
    * @dev allows the current PIC for the given token to change the exit rate
    * @param token The Super Token the exit rate should be changed for
    * @param newExitRate The new exit rate. The same constraints as during bidding apply.
    *
    * Notes:
    * newExitRate can't be higher than the value returned by getMaxExitRateFor() for the given token and bond.
    * newExitRate can also be 0, this triggers closing of the flow from the contract to the PIC.
    * If newExitRate is > 0 and no flow exists, a flow is created.
    */
    function changeExitRate(ISuperToken token, int96 newExitRate) external;

    /**
     * @dev Emitted on a successful bid designating a PIC
     * @param token The Super token the new PIC bid for
     * @param pic The address of the new PIC
     * @param bond The size (amount) of the bond staked by the PIC
     * @param exitRate The flowrate at which the bond and accrued rewards will be streamed to the PIC
     * The exitRate must be greater or equal zero and respect the upper bound defined by getMaxExitRateFor()
     */
    event NewPIC(ISuperToken indexed token, address pic, uint256 bond, int96 exitRate);

    /**
     * @dev Emitted if a PIC changes the exit rate
     * @param token The Super token for which the exit rate was changed
     * @param exitRate The new flowrate of the given token from the contract to the PIC
     */
    event ExitRateChanged(ISuperToken indexed token, int96 exitRate);
}

interface ITOGAv2 is ITOGAv1 {
    /**
    * @dev allows previous PICs to withdraw bonds which couldn't be sent back to them
    * @param token The token for which to withdraw funds in custody
    */
    function withdrawFundsInCustody(ISuperToken token) external;

    /**
     * @dev Emitted if a PIC increases its bond
     * @param additionalBond The additional amount added to the bond
     */
    event BondIncreased(ISuperToken indexed token, uint256 additionalBond);
}

contract TOGA is ITOGAv2, IERC777Recipient {
    // lightweight struct packing an address and a bool (reentrancy guard) into 1 word
    struct LockablePIC {
        address addr;
        bool lock;
    }
    mapping(ISuperToken => LockablePIC) internal _currentPICs;
    ISuperfluid internal immutable _host;
    IConstantFlowAgreementV1 internal immutable _cfa;
    uint256 public immutable minBondDuration;
    IERC1820Registry constant internal _ERC1820_REG = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
    // solhint-disable-next-line var-name-mixedcase
    uint64 immutable public ERC777_SEND_GAS_LIMIT = 3000000;
    // takes custody of bonds which the TOGA fails to send back to an outbid PIC
    TokenCustodian public custodian;

    constructor(ISuperfluid host_, uint256 minBondDuration_, TokenCustodian custodian_) {
        _host = ISuperfluid(host_);
        minBondDuration = minBondDuration_;
        _cfa = IConstantFlowAgreementV1(
            address(host_.getAgreementClass(keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1")))
        );
        bytes32 erc777TokensRecipientHash = keccak256("ERC777TokensRecipient");
        _ERC1820_REG.setInterfaceImplementer(address(this), erc777TokensRecipientHash, address(this));
        _ERC1820_REG.setInterfaceImplementer(address(this), keccak256("TOGAv1"), address(this));
        _ERC1820_REG.setInterfaceImplementer(address(this), keccak256("TOGAv2"), address(this));

        require(
            _ERC1820_REG.getInterfaceImplementer(address(custodian_), erc777TokensRecipientHash) == address(custodian_),
            "TOGA: invalid custodian"
        );
        custodian = custodian_;
    }

    function getCurrentPIC(ISuperToken token) external view override returns(address pic) {
        return _currentPICs[token].addr;
    }

    function getCurrentPICInfo(ISuperToken token)
        external view override
        returns(address pic, uint256 bond, int96 exitRate)
    {
        (, exitRate,,) = _cfa.getFlow(token, address(this), _currentPICs[token].addr);
        return (
            _currentPICs[token].addr,
            _getCurrentPICBond(token),
            exitRate
        );
    }

    function getDefaultExitRateFor(ISuperToken /*token*/, uint256 bondAmount)
        public view override
        returns(int96 exitRate)
    {
        return int96(bondAmount / (minBondDuration * 4));
    }

    function getMaxExitRateFor(ISuperToken /*token*/, uint256 bondAmount)
        external view override
        returns(int96 exitRate)
    {
        return int96(bondAmount / minBondDuration);
    }

    function changeExitRate(ISuperToken token, int96 newExitRate) external override {
        address currentPICAddr = _currentPICs[token].addr;
        require(msg.sender == currentPICAddr, "TOGA: only PIC allowed");
        require(newExitRate >= 0, "TOGA: negative exitRate not allowed");
        require(uint256(newExitRate) * minBondDuration <= _getCurrentPICBond(token), "TOGA: exitRate too high");

        (, int96 curExitRate,,) = _cfa.getFlow(token, address(this), currentPICAddr);
        if (curExitRate > 0 && newExitRate > 0) {
            // need to update existing flow
            _host.callAgreement(
                _cfa,
                abi.encodeWithSelector(
                    _cfa.updateFlow.selector,
                    token,
                    currentPICAddr,
                    newExitRate,
                    new bytes(0)
                ),
                "0x"
            );
        } else if (curExitRate == 0 && newExitRate > 0) {
            // no pre-existing flow, need to create
            _host.callAgreement(
                _cfa,
                abi.encodeWithSelector(
                    _cfa.createFlow.selector,
                    token,
                    currentPICAddr,
                    newExitRate,
                    new bytes(0)
                ),
                "0x"
            );
        } else if (curExitRate > 0 && newExitRate == 0) {
            // need to close existing flow
            _host.callAgreement(
                _cfa,
                abi.encodeWithSelector(
                    _cfa.deleteFlow.selector,
                    token,
                    address(this),
                    currentPICAddr,
                    new bytes(0)
                ),
                "0x"
            );
        } // else do nothing (no existing flow, newExitRate == 0)

        emit ExitRateChanged(token, newExitRate);
    }

    function withdrawFundsInCustody(ISuperToken token) external override {
        custodian.flush(token, msg.sender);
    }

    // ============ internal ============

    function _getCurrentPICBond(ISuperToken token) internal view returns(uint256 bond) {
        (int256 availBal, uint256 deposit, , ) = token.realtimeBalanceOfNow(address(this));
        // The protocol guarantees that we get no values leading to an overflow here
        return availBal + int256(deposit) > 0 ? uint256(availBal + int256(deposit)) : 0;
    }

    // This is the logic for designating a PIC via successful bid - invoked only by the ERC777 send() hook
    // Relies on CFA (SuperApp) hooks not being able to block the transaction by reverting.
    function _becomePIC(ISuperToken token, address newPIC, uint256 amount, int96 exitRate) internal {
        require(!_currentPICs[token].lock, "TOGA: reentrancy not allowed");
        require(exitRate >= 0, "TOGA: negative exitRate not allowed");
        require(uint256(exitRate) * minBondDuration <= amount, "TOGA: exitRate too high");
        // cannot underflow because amount was added to the balance before
        uint256 currentPICBond = _getCurrentPICBond(token) - amount;
        require(amount > currentPICBond, "TOGA: bid too low");
        address currentPICAddr = _currentPICs[token].addr;

        _currentPICs[token].lock = true; // set reentrancy guard

        // close flow to current (soon previous) PIC if exists
        (, int96 curFlowRate,,) = _cfa.getFlow(token, address(this), currentPICAddr);
        if (curFlowRate > 0) {
            _host.callAgreement(
                _cfa,
                abi.encodeWithSelector(
                    _cfa.deleteFlow.selector,
                    token,
                    address(this),
                    currentPICAddr,
                    new bytes(0)
                ),
                "0x"
            );
        }

        // if no PIC was set yet, rewards already accumulated become part of the bond of the first PIC
        if (currentPICAddr != address(0)) {
            // send remaining bond to current PIC
            // solhint-disable-next-line check-send-result
            try token.send{gas: ERC777_SEND_GAS_LIMIT}(currentPICAddr, currentPICBond, "0x")
            // solhint-disable-next-line no-empty-blocks
            {} catch {
                // if sending failed, move the remaining bond to a custody contract
                // the current PIC can withdraw it in a separate tx anytime later
                // solhint-disable-next-line check-send-result, multiple-sends
                token.send(address(custodian), currentPICBond, abi.encode(currentPICAddr));
            }
        }

        // set new PIC
        // solhint-disable-next-line reentrancy
        _currentPICs[token].addr = newPIC;

        // if exitRate > 0, open stream to new PIC
        if (exitRate > 0) {
            _host.callAgreement(
                _cfa,
                abi.encodeWithSelector(
                    _cfa.createFlow.selector,
                    token,
                    newPIC,
                    exitRate,
                    new bytes(0)
                ),
                "0x"
            );
        }

        // solhint-disable-next-line reentrancy
        _currentPICs[token].lock = false; // release reentrancy guard
        emit NewPIC(token, newPIC, amount, exitRate);
    }

    // ============ IERC777Recipient ============

    function tokensReceived(
        address /*operator*/,
        address from,
        address /*to*/,
        uint256 amount,
        bytes calldata userData,
        bytes calldata /*operatorData*/
    ) override external {
        // if it's not a SuperToken, something will revert along the way
        ISuperToken token = ISuperToken(msg.sender);

        if(from != _currentPICs[token].addr) {
            int96 exitRate = userData.length == 0 ?
                getDefaultExitRateFor(token, amount) :
                abi.decode(userData, (int96));
            _becomePIC(token, from, amount, exitRate);
        } else {
            // current PIC increases the bond
            emit BondIncreased(token, amount);
        }
    }
}

File 2 of 17 : TokenCustodian.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity 0.7.6;

import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol";
import { IERC1820Registry } from "@openzeppelin/contracts/introspection/IERC1820Registry.sol";
import { IERC777Recipient } from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol";

// contract which takes custody of funds which couldn't be sent to the designated recipient
contract TokenCustodian is IERC777Recipient {
    IERC1820Registry constant internal _ERC1820_REGISTRY =
    IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
    mapping(IERC777 => mapping(address => uint256)) public balances;

    constructor() {
        _ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777TokensRecipient"), address(this));
    }

    event CustodianDeposit(IERC777 indexed token, address recipient, uint256 amount);
    event CustodianWithdrawal(IERC777 indexed token, address recipient, uint256 amount);

    // transfers tokens it has in custody for the given recipient to it
    function flush(IERC777 token, address recipient) public {
        uint256 amount = balances[token][recipient];
        if (amount > 0) {
            balances[token][recipient] = 0;
            // solhint-disable-next-line check-send-result
            token.send(recipient, amount, "0x0");
            emit CustodianWithdrawal(token, recipient, amount);
        }
    }

    // ============ IERC777Recipient ============

    // interface through which ERC777 tokens are deposited to this contract.
    // requires userData to contain an abi-encoded address which designates the recipient for which the deposit is made.
    function tokensReceived(
        address /*operator*/,
        address /*from*/,
        address /*to*/,
        uint256 amount,
        bytes calldata userData,
        bytes calldata /*operatorData*/
    ) override external {
        IERC777 token = IERC777(msg.sender);
        // note: if userData is not set or not decodable as address, this will revert
        address recipient = abi.decode(userData, (address));
        balances[token][recipient] += amount;
        emit CustodianDeposit(token, recipient, amount);
        // note: anybody could call this function and store balance entries. We can just ignore that, does no harm.
    }
}

File 3 of 17 : TokenInfo.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.5.0;

/**
 * @dev ERC20 token info interface
 *
 * NOTE: 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);
}

File 4 of 17 : ERC20WithTokenInfo.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.5.0;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { TokenInfo } from "./TokenInfo.sol";


/**
 *
 * @dev Interface for ERC20 token with token info
 *
 * NOTE: 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 {}

File 5 of 17 : ISuperfluidToken.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

import { ISuperAgreement } from "./ISuperAgreement.sol";


/**
 * @title Superfluid's token interface.
 *
 * @author Superfluid
 */
interface ISuperfluidToken {

    /**************************************************************************
     * Basic information
     *************************************************************************/

    /**
     * @dev Get superfluid host contract address
     */
    function getHost() external view returns(address host);

    /**************************************************************************
     * 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);

    /// @dev realtimeBalanceOf with timestamp equals to block timestamp
    function realtimeBalanceOfNow(
       address account
    )
        external view
        returns (
            int256 availableBalance,
            uint256 deposit,
            uint256 owedDeposit,
            uint256 timestamp);

    /**
    * @dev Check if one account is critical
    * @param account Account check if is critical by a future time
    * @param timestamp Time of balance
    * @return isCritical
    */
    function isAccountCritical(
        address account,
        uint256 timestamp
    )
        external view
        returns(bool isCritical);

    /**
    * @dev Check if one account is critical now
    * @param account Account check if is critical by a future time
    * @return isCritical
    */
    function isAccountCriticalNow(
        address account
    )
        external view
        returns(bool isCritical);

    /**
     * @dev Check if one account is solvent
     * @param account Account check if is solvent by a future time
     * @param timestamp Time of balance
     * @return isSolvent
     */
    function isAccountSolvent(
        address account,
        uint256 timestamp
    )
        external view
        returns(bool isSolvent);

    /**
     * @dev Check if one account is solvent now
     * @param account Account check if is solvent now
     * @return isSolvent
     */
    function isAccountSolventNow(
        address account
    )
        external view
        returns(bool isSolvent);

    /**
    * @dev 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 creation 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 creation 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 termination event
     * @param agreementClass Contract address of the agreement
     * @param id Agreement ID
     */
    event AgreementTerminated(
        address indexed agreementClass,
        bytes32 id
    );

    /**
     * @dev Update agreement state slot
     * @param account Account to be updated
     *
     * NOTE
     * - To clear the storage out, provide zero-ed array of intended length
     */
    function updateAgreementStateSlot(
        address account,
        uint256 slotId,
        bytes32[] calldata slotData
    )
        external;

    /**
     * @dev Agreement account state updated event
     * @param agreementClass Contract address of the agreement
     * @param account Account updated
     * @param slotId slot id of the agreement state
     */
    event AgreementStateUpdated(
        address indexed agreementClass,
        address indexed account,
        uint256 slotId
    );

    /**
     * @dev Get data of the slot of the state of a 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);

    /**
     * @dev Agreement account state updated event
     * @param agreementClass Contract address of the agreement
     * @param account Account of the agrement
     * @param state Agreement state of the account
     */
    event AgreementAccountStateUpdated(
        address indexed agreementClass,
        address indexed account,
        bytes state
    );

    /**
     * @dev Settle balance from an account by the agreement.
     *      The agreement needs to make sure that the balance delta is balanced afterwards
     * @param account Account to query.
     * @param delta Amount of balance delta to be settled
     *
     * Modifiers:
     *  - onlyAgreement
     */
    function settleBalance(
        address account,
        int256 delta
    )
        external;

    /**
     * @dev 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
     */
    event AgreementLiquidated(
        address indexed agreementClass,
        bytes32 id,
        address indexed penaltyAccount,
        address indexed rewardAccount,
        uint256 rewardAmount
    );

    /**
     * @dev System bailout occurred (DEPRECATIED BY AgreementLiquidatedBy)
     * @param bailoutAccount Account that bailout the penalty account
     * @param bailoutAmount Amount of account bailout
     */
    event Bailout(
        address indexed bailoutAccount,
        uint256 bailoutAmount
    );

    /**
     * @dev Agreement liquidation event (including agent account)
     * @param agreementClass Contract address of the agreement
     * @param id Agreement ID
     * @param liquidatorAccount Account of the agent that performed the liquidation.
     * @param penaltyAccount Account of the agreement to be penalized
     * @param bondAccount Account that collect the reward or bailout accounts
     * @param rewardAmount Amount of liquidation reward
     * @param bailoutAmount Amount of liquidation bailouot
     *
     * NOTE:
     * Reward account rule:
     * - if bailout is equal to 0, then
     *   - the bondAccount will get the rewardAmount,
     *   - the penaltyAccount will pay for the rewardAmount.
     * - if bailout is larger than 0, then
     *   - the liquidatorAccount will get the rewardAmouont,
     *   - the bondAccount will pay for both the rewardAmount and bailoutAmount,
     *   - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.
     */
    event AgreementLiquidatedBy(
        address liquidatorAccount,
        address indexed agreementClass,
        bytes32 id,
        address indexed penaltyAccount,
        address indexed bondAccount,
        uint256 rewardAmount,
        uint256 bailoutAmount
    );

    /**
     * @dev Make liquidation payouts
     * @param id Agreement ID
     * @param liquidator Address of the executer of liquidation
     * @param penaltyAccount Account of the agreement to be penalized
     * @param rewardAmount Amount of liquidation reward
     * @param bailoutAmount Amount of account bailout needed
     *
     * NOTE:
     * Liquidation rules:
     *  - If a bailout is required (bailoutAmount > 0)
     *     - the actual reward goes to the liquidator,
     *     - while the reward account becomes the bailout account
     *     - total bailout include: bailout amount + reward amount
     *
     * Modifiers:
     *  - onlyAgreement
     */
    function makeLiquidationPayouts
    (
        bytes32 id,
        address liquidator,
        address penaltyAccount,
        uint256 rewardAmount,
        uint256 bailoutAmount
    )
        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 host contract
     //modifier onlyHost() virtual;

    /// @dev The msg.sender must be a listed agreement.
    //modifier onlyAgreement() virtual;

}

File 6 of 17 : ISuperfluidGovernance.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

import { ISuperAgreement } from "./ISuperAgreement.sol";
import { ISuperToken } from "./ISuperToken.sol";
import { ISuperfluidToken  } from "./ISuperfluidToken.sol";
import { ISuperfluid } from "./ISuperfluid.sol";


/**
 * @dev Superfluid's Governance interface
 *
 * @author Superfluid
 */
interface ISuperfluidGovernance {

    /**
     * @dev Replace the current governance with a new governance
     */
    function replaceGovernance(
        ISuperfluid host,
        address newGov) external;

    /**
     * @dev Register a new agreement class
     */
    function registerAgreementClass(
        ISuperfluid host,
        address agreementClass) external;

    /**
     * @dev Update logics of the contracts
     *
     * NOTE:
     * - Because they might have inter-dependencies, it is good to have one single function to update them all
     */
    function updateContracts(
        ISuperfluid host,
        address hostNewLogic,
        address[] calldata agreementClassNewLogics,
        address superTokenFactoryNewLogic
    ) external;

    /**
     * @dev Update supertoken logic contract to the latest that is managed by the super token factory
     */
    function batchUpdateSuperTokenLogic(
        ISuperfluid host,
        ISuperToken[] calldata tokens) external;

    /// @dev 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);

}

File 7 of 17 : ISuperfluid.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;
// This is required by the batchCall and decodeCtx
pragma experimental ABIEncoderV2;

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 {
    SuperAppDefinitions,
    ContextDefinitions,
    BatchOperation,
    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";


/**
 * @dev Superfluid host interface.

 * It is the central contract of the system where super agreement, super app
 * and super token features are connected together.
 *
 * The superfluid host contract is also the entry point for the protocol users,
 * where batch call and meta transaction are provided for UX improvements.
 *
 * @author Superfluid
 */
interface ISuperfluid {

    /**************************************************************************
     * Governance
     *************************************************************************/

    /**
     * @dev Get the current governace of the Superfluid host
     */
    function getGovernance() external view returns(ISuperfluidGovernance governance);

    event GovernanceReplaced(ISuperfluidGovernance oldGov, ISuperfluidGovernance newGov);
    /**
     * @dev Replace the current governance with a new one
     */
    function replaceGovernance(ISuperfluidGovernance newGov) external;

    /**************************************************************************
     * Agreement Whitelisting
     *************************************************************************/

    event AgreementClassRegistered(bytes32 agreementType, address code);
    /**
     * @dev Register a new agreement class to the system
     * @param agreementClassLogic INitial agreement class code
     *
     * Modifiers:
     *  - onlyGovernance
     */
    function registerAgreementClass(ISuperAgreement agreementClassLogic) external;

    event AgreementClassUpdated(bytes32 agreementType, address code);
    /**
    * @dev Update code of an agreement class
    * @param agreementClassLogic New code for the agreement class
    *
    * Modifiers:
    *  - onlyGovernance
    */
    function updateAgreementClass(ISuperAgreement agreementClassLogic) external;

    /**
    * @dev Check if the agreement class is whitelisted
    */
    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);

    /**
    * @dev Get agreement class
    */
    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);

    /**
    * @dev Create a new bitmask by adding a agreement class to it.
    * @param bitmap Agreement class bitmap
    */
    function addToAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType)
        external view
        returns (uint256 newBitmap);

    /**
    * @dev Create a new bitmask by removing a agreement class from it.
    * @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);

    event SuperTokenFactoryUpdated(ISuperTokenFactory newFactory);
    /**
     * @dev Update super token factory
     * @param newFactory New factory logic
     */
    function updateSuperTokenFactory(ISuperTokenFactory newFactory) external;

    event SuperTokenLogicUpdated(ISuperToken indexed token, address code);
    /**
     * @dev Update the super token logic to the latest
     *
     * NOTE:
     * - Refer toISuperTokenFactory.Upgradability for expected behaviours.
     */
    function updateSuperTokenLogic(ISuperToken token) external;

    /**************************************************************************
     * App Registry
     *************************************************************************/

    /**
     * @dev App registered event
     */
    event AppRegistered(ISuperApp indexed app);

    /**
     * @dev Jail event for the app
     */
    event Jail(ISuperApp indexed app, uint256 reason);

    /**
     * @dev Message sender declares it as a super app
     * @param configWord The super app manifest configuration, flags are defined in
     *                   `SuperAppDefinitions`
     */
    function registerApp(uint256 configWord) external;

    /**
     * @dev Message sender declares it as a super app, using a registration key
     * @param configWord The super app manifest configuration, flags are defined in
     *                   `SuperAppDefinitions`
     * @param registrationKey The registration key issued by the governance
     */
    function registerAppWithKey(uint256 configWord, string calldata registrationKey) external;

    /**
     * @dev Message sender declares app as a super app
     * @param configWord The super app manifest configuration, flags are defined in
     *                   `SuperAppDefinitions`
     * NOTE: only factory contracts authorized by governance can register super apps
     */
    function registerAppByFactory(ISuperApp app, uint256 configWord) external;

    /**
     * @dev Query if the app is registered
     * @param app Super app address
     */
    function isApp(ISuperApp app) external view returns(bool);

    /**
     * @dev Query app level
     * @param app Super app address
     */
    function getAppLevel(ISuperApp app) external view returns(uint8 appLevel);

    /**
     * @dev Get the manifest of the super app
     * @param app Super app address
     */
    function getAppManifest(
        ISuperApp app
    )
        external view
        returns (
            bool isSuperApp,
            bool isJailed,
            uint256 noopMask
        );

    /**
     * @dev Query if the app has been jailed
     * @param app Super app address
     */
    function isAppJailed(ISuperApp app) external view returns (bool isJail);

    /**
     * @dev White-list the target app for app composition for the source app (msg.sender)
     * @param targetApp The taget 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 taget super app address
     */
    function isCompositeAppAllowed(
        ISuperApp app,
        ISuperApp targetApp
    )
        external view
        returns (bool isAppAllowed);

    /**************************************************************************
     * Agreement Framework
     *
     * Agreements use these function to trigger super app callbacks, updates
     * app allowance and charge gas fees.
     *
     * These functions can only be called by registered agreements.
     *************************************************************************/

    function callAppBeforeCallback(
        ISuperApp app,
        bytes calldata callData,
        bool isTermination,
        bytes calldata ctx
    )
        external
        // onlyAgreement
        // isAppActive(app)
        returns(bytes memory cbdata);

    function callAppAfterCallback(
        ISuperApp app,
        bytes calldata callData,
        bool isTermination,
        bytes calldata ctx
    )
        external
        // onlyAgreement
        // isAppActive(app)
        returns(bytes memory appCtx);

    function appCallbackPush(
        bytes calldata ctx,
        ISuperApp app,
        uint256 appAllowanceGranted,
        int256 appAllowanceUsed,
        ISuperfluidToken appAllowanceToken
    )
        external
        // onlyAgreement
        returns (bytes memory appCtx);

    function appCallbackPop(
        bytes calldata ctx,
        int256 appAllowanceUsedDelta
    )
        external
        // onlyAgreement
        returns (bytes memory newCtx);

    function ctxUseAllowance(
        bytes calldata ctx,
        uint256 appAllowanceWantedMore,
        int256 appAllowanceUsedDelta
    )
        external
        // onlyAgreement
        returns (bytes memory newCtx);

    function jailApp(
        bytes calldata ctx,
        ISuperApp app,
        uint256 reason
    )
        external
        // onlyAgreement
        returns (bytes memory newCtx);

    /**************************************************************************
     * 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 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
        returns(bytes memory returnedData);

    /**
     * @dev Call app action
     * @param callData The contextual call data.
     *
     * NOTE: See callAgreement about contextual call data.
     */
    function callAppAction(
        ISuperApp app,
        bytes calldata callData
    )
        external
        //cleanCtx
        //isAppActive(app)
        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 ABIv2 Encoded memory data of context
     *
     * NOTE on backward compatibility:
     * - Non-dynamic fields are padded to 32bytes and packed
     * - Dynamic fields are referenced through a 32bytes offset to their "parents" field (or root)
     * - The order of the fields hence should not be rearranged in order to be backward compatible:
     *    - non-dynamic fields will be parsed at the same memory location,
     *    - and dynamic fields will simply have a greater offset than it was.
     */
    struct Context {
        //
        // Call context
        //
        // callback level
        uint8 appLevel;
        // type of call
        uint8 callType;
        // the system timestsamp
        uint256 timestamp;
        // The intended message sender for the call
        address msgSender;

        //
        // Callback context
        //
        // For callbacks it is used to know which agreement function selector is called
        bytes4 agreementSelector;
        // User provided data for app callbacks
        bytes userData;

        //
        // App context
        //
        // app allowance granted
        uint256 appAllowanceGranted;
        // app allowance wanted by the app callback
        uint256 appAllowanceWanted;
        // app allowance used, allowing negative values over a callback session
        int256 appAllowanceUsed;
        // app address
        address appAddress;
        // app allowance in super token
        ISuperfluidToken appAllowanceToken;
    }

    function callAgreementWithContext(
        ISuperAgreement agreementClass,
        bytes calldata callData,
        bytes calldata userData,
        bytes calldata ctx
    )
        external
        // validCtx(ctx)
        // onlyAgreement(agreementClass)
        returns (bytes memory newCtx, bytes memory returnedData);

    function callAppActionWithContext(
        ISuperApp app,
        bytes calldata callData,
        bytes calldata ctx
    )
        external
        // validCtx(ctx)
        // isAppActive(app)
        returns (bytes memory newCtx);

    function decodeCtx(bytes calldata ctx)
        external pure
        returns (Context memory context);

    function isCtxValid(bytes calldata ctx) external view returns (bool);

    /**************************************************************************
    * Batch call
    **************************************************************************/
    /**
     * @dev Batch operation data
     */
    struct Operation {
        // Operation. Defined in BatchOperation (Definitions.sol)
        uint32 operationType;
        // Operation target
        address target;
        // Data specific to the operation
        bytes data;
    }

    /**
     * @dev Batch call function
     * @param operations Array of batch operations.
     */
    function batchCall(Operation[] memory operations) external;

    /**
     * @dev Batch call function for trusted forwarders (EIP-2771)
     * @param operations Array of batch operations.
     */
    function forwardBatchCall(Operation[] memory operations) external;

    /**************************************************************************
     * Function modifiers for access control and parameter validations
     *
     * While they cannot be explicitly stated in function definitions, they are
     * listed in function definition comments instead for clarity.
     *
     * TODO: turning these off because solidity-coverage don't like it
     *************************************************************************/

     /* /// @dev The current superfluid context is clean.
     modifier cleanCtx() virtual;

     /// @dev The superfluid context is valid.
     modifier validCtx(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; */
}

File 8 of 17 : ISuperTokenFactory.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

import { ISuperToken } from "./ISuperToken.sol";

import {
    IERC20,
    ERC20WithTokenInfo
} from "../tokens/ERC20WithTokenInfo.sol";


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;

    event SuperTokenLogicCreated(ISuperToken indexed tokenLogic);

    event SuperTokenCreated(ISuperToken indexed token);

    event CustomSuperTokenCreated(ISuperToken indexed token);

}

File 9 of 17 : ISuperToken.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

import { ISuperfluid } from "./ISuperfluid.sol";
import { ISuperfluidToken } from "./ISuperfluidToken.sol";
import { TokenInfo } from "../tokens/TokenInfo.sol";
import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
 * @title Superfluid's super token (Superfluid Token + ERC20 + ERC777) interface
 *
 * @author Superfluid
 */
interface ISuperToken is ISuperfluidToken, TokenInfo, IERC20, IERC777 {

    /// @dev Initialize the contract
    function initialize(
        IERC20 underlyingToken,
        uint8 underlyingDecimals,
        string calldata n,
        string calldata s
    ) external;

    /**************************************************************************
    * TokenInfo & ERC777
    *************************************************************************/

    /**
     * @dev Returns the name of the token.
     */
    function name() external view override(IERC777, TokenInfo) returns (string memory);

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external view override(IERC777, TokenInfo) returns (string memory);

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: SuperToken always uses 18 decimals.
     *
     * Note: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() external view override(TokenInfo) returns (uint8);

    /**************************************************************************
    * ERC20 & ERC777
    *************************************************************************/

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() external view override(IERC777, IERC20) returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by an account (`owner`).
     */
    function balanceOf(address account) external view override(IERC777, IERC20) returns(uint256 balance);

    /**************************************************************************
    * ERC20
    *************************************************************************/

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external override(IERC20) returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external override(IERC20) view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * 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 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.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external override(IERC20) returns (bool);

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
     function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

    /**************************************************************************
    * ERC777
    *************************************************************************/

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For super token contracts, this value is 1 always
     */
    function granularity() external view override(IERC777) returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(address recipient, uint256 amount, bytes calldata data) external override(IERC777);

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external override(IERC777);

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external override(IERC777) view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external override(IERC777);

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external override(IERC777);

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external override(IERC777) view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external override(IERC777);

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external override(IERC777);

    /**************************************************************************
     * SuperToken custom token functions
     *************************************************************************/

    /**
     * @dev Mint new tokens for the account
     *
     * Modifiers:
     *  - onlySelf
     */
    function selfMint(
        address account,
        uint256 amount,
        bytes memory userData
    ) external;

   /**
    * @dev Burn existing tokens for the account
    *
    * Modifiers:
    *  - onlySelf
    */
   function selfBurn(
       address account,
       uint256 amount,
       bytes memory userData
   ) external;

    /**************************************************************************
     * SuperToken extra functions
     *************************************************************************/

    /**
     * @dev Transfer all available balance from `msg.sender` to `recipient`
     */
    function transferAll(address recipient) external;

    /**************************************************************************
     * ERC20 wrapping
     *************************************************************************/

    /**
     * @dev Return the underlying token contract
     * @return tokenAddr Underlying token address
     */
    function getUnderlyingToken() external view returns(address tokenAddr);

    /**
     * @dev Upgrade ERC20 to SuperToken.
     * @param amount Number of tokens to be upgraded (in 18 decimals)
     *
     * NOTE: It will use ´transferFrom´ to get tokens. Before calling this
     * function you should ´approve´ this contract
     */
    function upgrade(uint256 amount) external;

    /**
     * @dev Upgrade ERC20 to SuperToken and transfer immediately
     * @param to The account to received upgraded tokens
     * @param amount Number of tokens to be upgraded (in 18 decimals)
     * @param data User data for the TokensRecipient callback
     *
     * NOTE: It will use ´transferFrom´ to get tokens. Before calling this
     * function you should ´approve´ this contract
     */
    function upgradeTo(address to, uint256 amount, bytes calldata data) external;

    /**
     * @dev Token upgrade event
     * @param account Account where tokens are upgraded to
     * @param amount Amount of tokens upgraded (in 18 decimals)
     */
    event TokenUpgraded(
        address indexed account,
        uint256 amount
    );

    /**
     * @dev Downgrade SuperToken to ERC20.
     * @dev It will call transfer to send tokens
     * @param amount Number of tokens to be downgraded
     */
    function downgrade(uint256 amount) external;

    /**
     * @dev Token downgrade event
     * @param account Account whose tokens are upgraded
     * @param amount Amount of tokens downgraded
     */
    event TokenDowngraded(
        address indexed account,
        uint256 amount
    );

    /**************************************************************************
    * Batch Operations
    *************************************************************************/

    /**
    * @dev Perform ERC20 approve by host contract.
    * @param account The account owner to be approved.
    * @param spender The spender of account owner's funds.
    * @param amount Number of tokens to be approved.
    *
    * Modifiers:
    *  - onlyHost
    */
    function operationApprove(
        address account,
        address spender,
        uint256 amount
    ) external;

    /**
    * @dev Perform ERC20 transfer from by host contract.
    * @param account The account to spend sender's funds.
    * @param spender  The account where the funds is sent from.
    * @param recipient The recipient of thefunds.
    * @param amount Number of tokens to be transferred.
    *
    * Modifiers:
    *  - onlyHost
    */
    function operationTransferFrom(
        address account,
        address spender,
        address recipient,
        uint256 amount
    ) external;

    /**
    * @dev Upgrade ERC20 to SuperToken by host contract.
    * @param account The account to be changed.
    * @param amount Number of tokens to be upgraded (in 18 decimals)
    *
    * Modifiers:
    *  - onlyHost
    */
    function operationUpgrade(address account, uint256 amount) external;

    /**
    * @dev Downgrade ERC20 to SuperToken by host contract.
    * @param account The account to be changed.
    * @param amount Number of tokens to be downgraded (in 18 decimals)
    *
    * Modifiers:
    *  - onlyHost
    */
    function operationDowngrade(address account, uint256 amount) external;


    /**************************************************************************
    * Function modifiers for access control and parameter validations
    *
    * While they cannot be explicitly stated in function definitions, they are
    * listed in function definition comments instead for clarity.
    *
    * NOTE: solidity-coverage not supporting it
    *************************************************************************/

    /// @dev The msg.sender must be the contract itself
    //modifier onlySelf() virtual

}

File 10 of 17 : ISuperApp.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

import { ISuperToken } from "./ISuperToken.sol";


/**
 * @title Superfluid's app interface.
 *
 * NOTE:
 * - Be fearful of the app jail, when the word permitted is used.
 *
 * @author Superfluid
 */
interface ISuperApp {

    /**
     * @dev Callback before a new agreement is created.
     * @param superToken The super token used for the agreement.
     * @param agreementClass The agreement class address.
     * @param agreementId The agreementId
     * @param agreementData The agreement data (non-compressed)
     * @param ctx The context data.
     * @return cbdata A free format in memory data the app can use to pass
     *          arbitary information to the after-hook callback.
     *
     * NOTE:
     * - It will be invoked with `staticcall`, no state changes are permitted.
     * - Only revert with a "reason" is permitted.
     */
    function beforeAgreementCreated(
        ISuperToken superToken,
        address agreementClass,
        bytes32 agreementId,
        bytes calldata agreementData,
        bytes calldata ctx
    )
        external
        view
        returns (bytes memory cbdata);

    /**
     * @dev Callback after a new agreement is created.
     * @param superToken The super token used for the agreement.
     * @param agreementClass The agreement class address.
     * @param agreementId The agreementId
     * @param agreementData The agreement data (non-compressed)
     * @param cbdata The data returned from the before-hook callback.
     * @param ctx The context data.
     * @return newCtx The current context of the transaction.
     *
     * NOTE:
     * - State changes is permitted.
     * - Only revert with a "reason" is permitted.
     */
    function afterAgreementCreated(
        ISuperToken superToken,
        address agreementClass,
        bytes32 agreementId,
        bytes calldata agreementData,
        bytes calldata cbdata,
        bytes calldata ctx
    )
        external
        returns (bytes memory newCtx);

    /**
     * @dev Callback before a new agreement is updated.
     * @param superToken The super token used for the agreement.
     * @param agreementClass The agreement class address.
     * @param agreementId The agreementId
     * @param agreementData The agreement data (non-compressed)
     * @param ctx The context data.
     * @return cbdata A free format in memory data the app can use to pass
     *          arbitary information to the after-hook callback.
     *
     * NOTE:
     * - It will be invoked with `staticcall`, no state changes are permitted.
     * - Only revert with a "reason" is permitted.
     */
    function beforeAgreementUpdated(
        ISuperToken superToken,
        address agreementClass,
        bytes32 agreementId,
        bytes calldata agreementData,
        bytes calldata ctx
    )
        external
        view
        returns (bytes memory cbdata);


    /**
    * @dev Callback after a new agreement is updated.
    * @param superToken The super token used for the agreement.
    * @param agreementClass The agreement class address.
    * @param agreementId The agreementId
    * @param agreementData The agreement data (non-compressed)
    * @param cbdata The data returned from the before-hook callback.
    * @param ctx The context data.
    * @return newCtx The current context of the transaction.
    *
    * NOTE:
    * - State changes is permitted.
    * - Only revert with a "reason" is permitted.
    */
    function afterAgreementUpdated(
        ISuperToken superToken,
        address agreementClass,
        bytes32 agreementId,
        bytes calldata agreementData,
        bytes calldata cbdata,
        bytes calldata ctx
    )
        external
        returns (bytes memory newCtx);

    /**
    * @dev Callback before a new agreement is terminated.
    * @param superToken The super token used for the agreement.
    * @param agreementClass The agreement class address.
    * @param agreementId The agreementId
    * @param agreementData The agreement data (non-compressed)
    * @param ctx The context data.
    * @return cbdata A free format in memory data the app can use to pass
    *          arbitary information to the after-hook callback.
    *
    * NOTE:
    * - It will be invoked with `staticcall`, no state changes are permitted.
    * - Revert is not permitted.
    */
    function beforeAgreementTerminated(
        ISuperToken superToken,
        address agreementClass,
        bytes32 agreementId,
        bytes calldata agreementData,
        bytes calldata ctx
    )
        external
        view
        returns (bytes memory cbdata);

    /**
    * @dev Callback after a new agreement is terminated.
    * @param superToken The super token used for the agreement.
    * @param agreementClass The agreement class address.
    * @param agreementId The agreementId
    * @param agreementData The agreement data (non-compressed)
    * @param cbdata The data returned from the before-hook callback.
    * @param ctx The context data.
    * @return newCtx The current context of the transaction.
    *
    * NOTE:
    * - State changes is permitted.
    * - Revert is not permitted.
    */
    function afterAgreementTerminated(
        ISuperToken superToken,
        address agreementClass,
        bytes32 agreementId,
        bytes calldata agreementData,
        bytes calldata cbdata,
        bytes calldata ctx
    )
        external
        returns (bytes memory newCtx);
}

File 11 of 17 : ISuperAgreement.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

import { ISuperfluidToken } from "./ISuperfluidToken.sol";

/**
 * @title Superfluid's agreement interface.
 *
 * @author Superfluid
 */
interface ISuperAgreement {

    /**
     * @dev Initialize the agreement contract
     */
    function initialize() external;

    /**
     * @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 Future 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
        );

}

File 12 of 17 : Definitions.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

/**
 * @dev Super app definitions library
 */
library SuperAppDefinitions {

    /**************************************************************************
    / App manifest config word
    /**************************************************************************/

    /*
     * App level is a way to allow the app to whitelist what other app it can
     * interact with (aka. composite app feature).
     *
     * For more details, refer to the technical paper of superfluid protocol.
     */
    uint256 constant internal APP_LEVEL_MASK = 0xFF;

    // The app is at the final level, hence it doesn't want to interact with any other app
    uint256 constant internal APP_LEVEL_FINAL = 1 << 0;

    // The app is at the second level, it may interact with other final level apps if whitelisted
    uint256 constant internal APP_LEVEL_SECOND = 1 << 1;

    function getAppLevel(uint256 configWord) internal pure returns (uint8) {
        return uint8(configWord & APP_LEVEL_MASK);
    }

    uint256 constant internal APP_JAIL_BIT = 1 << 15;
    function isAppJailed(uint256 configWord) internal pure returns (bool) {
        return (configWord & SuperAppDefinitions.APP_JAIL_BIT) > 0;
    }

    /**************************************************************************
    / Callback implementation bit masks
    /**************************************************************************/
    uint256 constant internal AGREEMENT_CALLBACK_NOOP_BITMASKS = 0xFF << 32;
    uint256 constant internal BEFORE_AGREEMENT_CREATED_NOOP = 1 << (32 + 0);
    uint256 constant internal AFTER_AGREEMENT_CREATED_NOOP = 1 << (32 + 1);
    uint256 constant internal BEFORE_AGREEMENT_UPDATED_NOOP = 1 << (32 + 2);
    uint256 constant internal AFTER_AGREEMENT_UPDATED_NOOP = 1 << (32 + 3);
    uint256 constant internal BEFORE_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 4);
    uint256 constant internal AFTER_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 5);

    /**************************************************************************
    / App Jail Reasons
    /**************************************************************************/

    uint256 constant internal APP_RULE_REGISTRATION_ONLY_IN_CONSTRUCTOR = 1;
    uint256 constant internal APP_RULE_NO_REGISTRATION_FOR_EOA = 2;
    uint256 constant internal APP_RULE_NO_REVERT_ON_TERMINATION_CALLBACK = 10;
    uint256 constant internal APP_RULE_NO_CRITICAL_SENDER_ACCOUNT = 11;
    uint256 constant internal APP_RULE_NO_CRITICAL_RECEIVER_ACCOUNT = 12;
    uint256 constant internal APP_RULE_CTX_IS_READONLY = 20;
    uint256 constant internal APP_RULE_CTX_IS_NOT_CLEAN = 21;
    uint256 constant internal APP_RULE_CTX_IS_MALFORMATED = 22;
    uint256 constant internal APP_RULE_COMPOSITE_APP_IS_NOT_WHITELISTED = 30;
    uint256 constant internal APP_RULE_COMPOSITE_APP_IS_JAILED = 31;
    uint256 constant internal APP_RULE_MAX_APP_LEVEL_REACHED = 40;
}

/**
 * @dev Context definitions library
 */
library ContextDefinitions {

    /**************************************************************************
    / Call info
    /**************************************************************************/

    // app level
    uint256 constant internal CALL_INFO_APP_LEVEL_MASK = 0xFF;

    // call type
    uint256 constant internal CALL_INFO_CALL_TYPE_SHIFT = 32;
    uint256 constant internal CALL_INFO_CALL_TYPE_MASK = 0xF << CALL_INFO_CALL_TYPE_SHIFT;
    uint8 constant internal CALL_INFO_CALL_TYPE_AGREEMENT = 1;
    uint8 constant internal CALL_INFO_CALL_TYPE_APP_ACTION = 2;
    uint8 constant internal CALL_INFO_CALL_TYPE_APP_CALLBACK = 3;

    function decodeCallInfo(uint256 callInfo)
        internal pure
        returns (uint8 appLevel, uint8 callType)
    {
        appLevel = uint8(callInfo & CALL_INFO_APP_LEVEL_MASK);
        callType = uint8((callInfo & CALL_INFO_CALL_TYPE_MASK) >> CALL_INFO_CALL_TYPE_SHIFT);
    }

    function encodeCallInfo(uint8 appLevel, uint8 callType)
        internal pure
        returns (uint256 callInfo)
    {
        return uint256(appLevel) | (uint256(callType) << CALL_INFO_CALL_TYPE_SHIFT);
    }

}

/**
 * @dev Batch operation library
 */
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;
}

library SuperfluidGovernanceConfigs {

    bytes32 constant internal SUPERFLUID_REWARD_ADDRESS_CONFIG_KEY =
        keccak256("org.superfluid-finance.superfluid.rewardAddress");

    bytes32 constant internal CFAv1_LIQUIDATION_PERIOD_CONFIG_KEY =
        keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1.liquidationPeriod");

    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));
    }
}

File 13 of 17 : IConstantFlowAgreementV1.sol
// SPDX-License-Identifier: AGPLv3
pragma solidity >= 0.7.0;

import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol";
import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol";


/**
 * @dev Superfluid's constant flow agreement interface
 *
 * @author Superfluid
 */
abstract contract IConstantFlowAgreementV1 is ISuperAgreement {

    /// @dev ISuperAgreement.agreementType implementation
    function agreementType() external override pure returns (bytes32) {
        return keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1");
    }

    /**
     * @dev Get the maximum flow rate allowed with the deposit
     * @param deposit Deposit amount used for creating the flow
     */
    function getMaximumFlowRateFromDeposit(
        ISuperfluidToken token,
        uint256 deposit)
        external view virtual
        returns (int96 flowRate);

    /**
     * @dev Get the deposit required for creating the flow
     * @param flowRate Flow rate to be tested
     */
    function getDepositRequiredForFlowRate(
        ISuperfluidToken token,
        int96 flowRate)
        external view virtual
        returns (uint256 deposit);

    /**
     * @dev Create a flow betwen sender and receiver.
     * @param token Super token address.
     * @param receiver Flow receiver address.
     * @param flowRate New flow rate in amount per second.
     *
     * # App callbacks
     *
     * - AgreementCreated
     *   - agreementId - can be used in getFlowByID
     *   - agreementData - abi.encode(address flowSender, address flowReceiver)
     *
     * NOTE:
     * - A deposit is taken as safety margin for the solvency agents.
     * - A extra gas fee may be taken to pay for solvency agent liquidations.
     */
    function createFlow(
        ISuperfluidToken token,
        address receiver,
        int96 flowRate,
        bytes calldata ctx
    )
        external virtual
        returns(bytes memory newCtx);

    /**
     * @dev Update the flow rate between sender and receiver.
     * @param token Super token address.
     * @param receiver Flow receiver address.
     * @param flowRate New flow rate in amount per second.
     *
     * # App callbacks
     *
     * - AgreementUpdated
     *   - agreementId - can be used in getFlowByID
     *   - agreementData - abi.encode(address flowSender, address flowReceiver)
     *
     * NOTE:
     * - Only the flow sender may update the flow rate.
     * - Even if the flow rate is zero, the flow is not deleted
     * from the system.
     * - Deposit amount will be adjusted accordingly.
     * - No new gas fee is charged.
     */
    function updateFlow(
        ISuperfluidToken token,
        address receiver,
        int96 flowRate,
        bytes calldata ctx
    )
        external virtual
        returns(bytes memory newCtx);


    /**
     * @dev Get the flow data between `sender` and `receiver`.
     * @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
        );

    /**
     * @dev Get flow data using agreement ID
     * @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 amount of deposit the flow.
     * @return owedDeposit The amount of owed deposit 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.
    */
    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 Flow rate.
     */
    function getNetFlow(
        ISuperfluidToken token,
        address account
    )
        external view virtual
        returns (int96 flowRate);

    /**
     * @dev Delete the flow between sender and receiver
     * @param token Super token address.
     * @param ctx Context bytes.
     * @param receiver Flow receiver address.
     *
     * # App callbacks
     *
     * - AgreementTerminated
     *   - agreementId - can be used in getFlowByID
     *   - agreementData - abi.encode(address flowSender, address flowReceiver)
     *
     * NOTE:
     * - Both flow sender and receiver may delete the flow.
     * - If Sender account is insolvent or in critical state, a solvency agent may
     *   also terminate the agreement.
     * - Gas fee may be returned to the sender.
     */
    function deleteFlow(
        ISuperfluidToken token,
        address sender,
        address receiver,
        bytes calldata ctx
    )
        external virtual
        returns(bytes memory newCtx);

     /**
      * @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 flowRate Total flow rate in amount per second for the sender.
      * @param flowRate 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
     );

}

File 14 of 17 : IERC777Recipient.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.
 *
 * Accounts can be notified of {IERC777} tokens being sent to them by having a
 * contract implement this interface (contract holders can be their own
 * implementer) and registering it on the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].
 *
 * See {IERC1820Registry} and {ERC1820Implementer}.
 */
interface IERC777Recipient {
    /**
     * @dev Called by an {IERC777} token contract whenever tokens are being
     * moved or created into a registered account (`to`). The type of operation
     * is conveyed by `from` being the zero address or not.
     *
     * This call occurs _after_ the token contract's state is updated, so
     * {IERC777-balanceOf}, etc., can be used to query the post-operation state.
     *
     * This function may revert to prevent the operation from being executed.
     */
    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}

File 15 of 17 : IERC777.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC777Token standard as defined in the EIP.
 *
 * This contract uses the
 * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
 * token holders and recipients react to token movements by using setting implementers
 * for the associated interfaces in said registry. See {IERC1820Registry} and
 * {ERC1820Implementer}.
 */
interface IERC777 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the smallest part of the token that is not divisible. This
     * means all token operations (creation, movement and destruction) must have
     * amounts that are a multiple of this number.
     *
     * For most token contracts, this value will equal 1.
     */
    function granularity() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by an account (`owner`).
     */
    function balanceOf(address owner) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * If send or receive hooks are registered for the caller and `recipient`,
     * the corresponding functions will be called with `data` and empty
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function send(address recipient, uint256 amount, bytes calldata data) external;

    /**
     * @dev Destroys `amount` tokens from the caller's account, reducing the
     * total supply.
     *
     * If a send hook is registered for the caller, the corresponding function
     * will be called with `data` and empty `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - the caller must have at least `amount` tokens.
     */
    function burn(uint256 amount, bytes calldata data) external;

    /**
     * @dev Returns true if an account is an operator of `tokenHolder`.
     * Operators can send and burn tokens on behalf of their owners. All
     * accounts are their own operator.
     *
     * See {operatorSend} and {operatorBurn}.
     */
    function isOperatorFor(address operator, address tokenHolder) external view returns (bool);

    /**
     * @dev Make an account an operator of the caller.
     *
     * See {isOperatorFor}.
     *
     * Emits an {AuthorizedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function authorizeOperator(address operator) external;

    /**
     * @dev Revoke an account's operator status for the caller.
     *
     * See {isOperatorFor} and {defaultOperators}.
     *
     * Emits a {RevokedOperator} event.
     *
     * Requirements
     *
     * - `operator` cannot be calling address.
     */
    function revokeOperator(address operator) external;

    /**
     * @dev Returns the list of default operators. These accounts are operators
     * for all token holders, even if {authorizeOperator} was never called on
     * them.
     *
     * This list is immutable, but individual holders may revoke these via
     * {revokeOperator}, in which case {isOperatorFor} will return false.
     */
    function defaultOperators() external view returns (address[] memory);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
     * be an operator of `sender`.
     *
     * If send or receive hooks are registered for `sender` and `recipient`,
     * the corresponding functions will be called with `data` and
     * `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
     *
     * Emits a {Sent} event.
     *
     * Requirements
     *
     * - `sender` cannot be the zero address.
     * - `sender` must have at least `amount` tokens.
     * - the caller must be an operator for `sender`.
     * - `recipient` cannot be the zero address.
     * - if `recipient` is a contract, it must implement the {IERC777Recipient}
     * interface.
     */
    function operatorSend(
        address sender,
        address recipient,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the total supply.
     * The caller must be an operator of `account`.
     *
     * If a send hook is registered for `account`, the corresponding function
     * will be called with `data` and `operatorData`. See {IERC777Sender}.
     *
     * Emits a {Burned} event.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     * - the caller must be an operator for `account`.
     */
    function operatorBurn(
        address account,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );

    event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);

    event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);

    event AuthorizedOperator(address indexed operator, address indexed tokenHolder);

    event RevokedOperator(address indexed operator, address indexed tokenHolder);
}

File 16 of 17 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 17 of 17 : IERC1820Registry.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the global ERC1820 Registry, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register
 * implementers for interfaces in this registry, as well as query support.
 *
 * Implementers may be shared by multiple accounts, and can also implement more
 * than a single interface for each account. Contracts can implement interfaces
 * for themselves, but externally-owned accounts (EOA) must delegate this to a
 * contract.
 *
 * {IERC165} interfaces can also be queried via the registry.
 *
 * For an in-depth explanation and source code analysis, see the EIP text.
 */
interface IERC1820Registry {
    /**
     * @dev Sets `newManager` as the manager for `account`. A manager of an
     * account is able to set interface implementers for it.
     *
     * By default, each account is its own manager. Passing a value of `0x0` in
     * `newManager` will reset the manager to this initial state.
     *
     * Emits a {ManagerChanged} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     */
    function setManager(address account, address newManager) external;

    /**
     * @dev Returns the manager for `account`.
     *
     * See {setManager}.
     */
    function getManager(address account) external view returns (address);

    /**
     * @dev Sets the `implementer` contract as ``account``'s implementer for
     * `interfaceHash`.
     *
     * `account` being the zero address is an alias for the caller's address.
     * The zero address can also be used in `implementer` to remove an old one.
     *
     * See {interfaceHash} to learn how these are created.
     *
     * Emits an {InterfaceImplementerSet} event.
     *
     * Requirements:
     *
     * - the caller must be the current manager for `account`.
     * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
     * end in 28 zeroes).
     * - `implementer` must implement {IERC1820Implementer} and return true when
     * queried for support, unless `implementer` is the caller. See
     * {IERC1820Implementer-canImplementInterfaceForAddress}.
     */
    function setInterfaceImplementer(address account, bytes32 _interfaceHash, address implementer) external;

    /**
     * @dev Returns the implementer of `interfaceHash` for `account`. If no such
     * implementer is registered, returns the zero address.
     *
     * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
     * zeroes), `account` will be queried for support of it.
     *
     * `account` being the zero address is an alias for the caller's address.
     */
    function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);

    /**
     * @dev Returns the interface hash for an `interfaceName`, as defined in the
     * corresponding
     * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
     */
    function interfaceHash(string calldata interfaceName) external pure returns (bytes32);

    /**
     *  @notice Updates the cache with whether the contract implements an ERC165 interface or not.
     *  @param account Address of the contract for which to update the cache.
     *  @param interfaceId ERC165 interface for which to update the cache.
     */
    function updateERC165Cache(address account, bytes4 interfaceId) external;

    /**
     *  @notice Checks whether a contract implements an ERC165 interface or not.
     *  If the result is not cached a direct lookup on the contract address is performed.
     *  If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
     *  {updateERC165Cache} with the contract address.
     *  @param account Address of the contract to check.
     *  @param interfaceId ERC165 interface to check.
     *  @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);

    /**
     *  @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
     *  @param account Address of the contract to check.
     *  @param interfaceId ERC165 interface to check.
     *  @return True if `account` implements `interfaceId`, false otherwise.
     */
    function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);

    event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);

    event ManagerChanged(address indexed account, address indexed newManager);
}

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract ISuperfluid","name":"host_","type":"address"},{"internalType":"uint256","name":"minBondDuration_","type":"uint256"},{"internalType":"contract TokenCustodian","name":"custodian_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperToken","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"additionalBond","type":"uint256"}],"name":"BondIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperToken","name":"token","type":"address"},{"indexed":false,"internalType":"int96","name":"exitRate","type":"int96"}],"name":"ExitRateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ISuperToken","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"pic","type":"address"},{"indexed":false,"internalType":"uint256","name":"bond","type":"uint256"},{"indexed":false,"internalType":"int96","name":"exitRate","type":"int96"}],"name":"NewPIC","type":"event"},{"inputs":[],"name":"ERC777_SEND_GAS_LIMIT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"},{"internalType":"int96","name":"newExitRate","type":"int96"}],"name":"changeExitRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"custodian","outputs":[{"internalType":"contract TokenCustodian","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"}],"name":"getCurrentPIC","outputs":[{"internalType":"address","name":"pic","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"}],"name":"getCurrentPICInfo","outputs":[{"internalType":"address","name":"pic","type":"address"},{"internalType":"uint256","name":"bond","type":"uint256"},{"internalType":"int96","name":"exitRate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"","type":"address"},{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"name":"getDefaultExitRateFor","outputs":[{"internalType":"int96","name":"exitRate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"","type":"address"},{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"name":"getMaxExitRateFor","outputs":[{"internalType":"int96","name":"exitRate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBondDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"token","type":"address"}],"name":"withdrawFundsInCustody","outputs":[],"stateMutability":"nonpayable","type":"function"}]

61010060405261b71b60c61b60e0523480156200001b57600080fd5b5060405162001ef338038062001ef3833981810160405260608110156200004157600080fd5b5080516020808301516040938401516001600160601b0319606085901b1660805260c08290528451635b69006f60e11b81527fa9214cc96615e0085d3bb077758db69497dc2dce3b2b1e97bc93c3d18d83efd3600482015294519394919390926001600160a01b0386169263b6d200de9260248083019392829003018186803b158015620000ce57600080fd5b505afa158015620000e3573d6000803e3d6000fd5b505050506040513d6020811015620000fa57600080fd5b505160601b6001600160601b03191660a052604080516329965a1d60e01b815230600482018190527fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b6024830181905260448301919091529151731820a4b7618bde71dce8cdc73aab6c95905fad24916329965a1d91606480830192600092919082900301818387803b1580156200019157600080fd5b505af1158015620001a6573d6000803e3d6000fd5b5050604080516329965a1d60e01b815230600482018190527fece6fc2bcfc93e4c34c28aeaa114be1a6161decb8268f79cbe7c3c7f31b1e8c6602483015260448201529051731820a4b7618bde71dce8cdc73aab6c95905fad2493506329965a1d9250606480830192600092919082900301818387803b1580156200022a57600080fd5b505af11580156200023f573d6000803e3d6000fd5b5050604080516329965a1d60e01b815230600482018190527fca6323f8f0faf3d4f41f2397ee46c8d85bed576d54aadeb20b6cf7b45b3a6964602483015260448201529051731820a4b7618bde71dce8cdc73aab6c95905fad2493506329965a1d9250606480830192600092919082900301818387803b158015620002c357600080fd5b505af1158015620002d8573d6000803e3d6000fd5b50506040805163555ddc6560e11b81526001600160a01b03861660048201819052602482018690529151919350731820a4b7618bde71dce8cdc73aab6c95905fad24925063aabbb8ca916044808301926020929190829003018186803b1580156200034257600080fd5b505afa15801562000357573d6000803e3d6000fd5b505050506040513d60208110156200036e57600080fd5b50516001600160a01b031614620003cc576040805162461bcd60e51b815260206004820152601760248201527f544f47413a20696e76616c696420637573746f6469616e000000000000000000604482015290519081900360640190fd5b50600180546001600160a01b039092166001600160a01b0319909216919091179055505060805160601c60a05160601c60c05160e05160c01c611a746200047f60003980610ca3528061148f52508061048b5280610cc95280610d2a5280610dbf5280610f9252508061052f52806105f3528061091752806109a75280610e2b52806110b2528061117b52806116585250806105cc52806108f05280610976528061114a52806116275250611a746000f3fe608060405234801561001057600080fd5b506004361061009d5760003560e01c8063375b74c311610066578063375b74c31461026357806360dfa6951461026b5780636da8d05414610285578063b8a14033146102ab578063bf8903dd146102d75761009d565b806223de29146100a257806302f3c6c51461018a5780630797e3e7146101b957806316e23b9f146101de5780633629106314610221575b600080fd5b610188600480360360c08110156100b857600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b8111156100fa57600080fd5b82018360208201111561010c57600080fd5b803590602001918460018302840111600160201b8311171561012d57600080fd5b919390929091602081019035600160201b81111561014a57600080fd5b82018360208201111561015c57600080fd5b803590602001918460018302840111600160201b8311171561017d57600080fd5b509092509050610328565b005b610188600480360360408110156101a057600080fd5b506001600160a01b038135169060200135600b0b6103d5565b6101c1610ca1565b6040805167ffffffffffffffff9092168252519081900360200190f35b61020a600480360360408110156101f457600080fd5b506001600160a01b038135169060200135610cc5565b60408051600b9290920b8252519081900360200190f35b6102476004803603602081101561023757600080fd5b50356001600160a01b0316610cfb565b604080516001600160a01b039092168252519081900360200190f35b610247610d19565b610273610d28565b60408051918252519081900360200190f35b6101886004803603602081101561029b57600080fd5b50356001600160a01b0316610d4c565b61020a600480360360408110156102c157600080fd5b506001600160a01b038135169060200135610dbb565b6102fd600480360360208110156102ed57600080fd5b50356001600160a01b0316610de6565b604080516001600160a01b0390941684526020840192909252600b0b82820152519081900360600190f35b336000818152602081905260409020546001600160a01b0389811691161461038a576000841561036c578585602081101561036257600080fd5b5035600b0b610376565b6103768288610cc5565b9050610384828a8984610ed7565b506103ca565b6040805187815290516001600160a01b038316917fb9c1b85a7ee70d95c61aca7cda03ef957abc5265a191ca74cc335faf59409566919081900360200190a25b505050505050505050565b6001600160a01b038083166000908152602081905260409020541633811461043d576040805162461bcd60e51b81526020600482015260166024820152751513d1d04e881bdb9b1e48141250c8185b1b1bddd95960521b604482015290519081900360640190fd5b600082600b0b12156104805760405162461bcd60e51b8152600401808060200182810382526023815260200180611a1c6023913960400191505060405180910390fd5b61048983611974565b7f000000000000000000000000000000000000000000000000000000000000000083600b0b0211156104fc576040805162461bcd60e51b81526020600482015260176024820152760a89e8e827440caf0d2e8a4c2e8ca40e8dede40d0d2ced604b1b604482015290519081900360640190fd5b60408051631cd43d1160e31b81526001600160a01b038581166004830152306024830152838116604483015291516000927f0000000000000000000000000000000000000000000000000000000000000000169163e6a1e888916064808301926080929190829003018186803b15801561057557600080fd5b505afa158015610589573d6000803e3d6000fd5b505050506040513d608081101561059f57600080fd5b506020015190506000600b82900b1380156105bd5750600083600b0b135b156108cb576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166339255d5b7f00000000000000000000000000000000000000000000000000000000000000006328104d3160e11b8786886000805b506040519080825280601f01601f19166020018201604052801561064c576020820181803683370190505b5060405160240180856001600160a01b03168152602001846001600160a01b0316815260200183600b0b815260200180602001828103825283818151815260200191508051906020019080838360005b838110156106b457818101518382015260200161069c565b50505050905090810190601f1680156106e15780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199a8b16178152905160e08c901b90991689526001600160a01b038a1660048a01908152606060248b01908152835160648c01528351939a919950975060448101965060840194509250905080838360005b8381101561077357818101518382015260200161075b565b50505050905090810190601f1680156107a05780820380516001836020036101000a031916815260200191505b508381038252600281526020018061060f60f31b815250602001945050505050600060405180830381600087803b1580156107da57600080fd5b505af11580156107ee573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561081757600080fd5b8101908080516040519392919084600160201b82111561083657600080fd5b90830190602082018581111561084b57600080fd5b8251600160201b81118282018810171561086457600080fd5b82525081516020918201929091019080838360005b83811015610891578181015183820152602001610879565b50505050905090810190601f1680156108be5780820380516001836020036101000a031916815260200191505b5060405250505050610c57565b80600b0b60001480156108e15750600083600b0b135b15610949576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166339255d5b7f000000000000000000000000000000000000000000000000000000000000000063317e182f60e11b878688600080610621565b600081600b0b13801561095f575082600b0b6000145b15610c5757604080516000808252602082019092527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916339255d5b917f000000000000000000000000000000000000000000000000000000000000000091635a5999e360e11b918991309189915060405160240180856001600160a01b03168152602001846001600160a01b03168152602001836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610a44578181015183820152602001610a2c565b50505050905090810190601f168015610a715780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199a8b16178152905160e08c901b90991689526001600160a01b038a1660048a01908152606060248b01908152835160648c01528351939a919950975060448101965060840194509250905080838360005b83811015610b03578181015183820152602001610aeb565b50505050905090810190601f168015610b305780820380516001836020036101000a031916815260200191505b508381038252600281526020018061060f60f31b815250602001945050505050600060405180830381600087803b158015610b6a57600080fd5b505af1158015610b7e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610ba757600080fd5b8101908080516040519392919084600160201b821115610bc657600080fd5b908301906020820185811115610bdb57600080fd5b8251600160201b811182820188101715610bf457600080fd5b82525081516020918201929091019080838360005b83811015610c21578181015183820152602001610c09565b50505050905090810190601f168015610c4e5780820380516001836020036101000a031916815260200191505b50604052505050505b836001600160a01b03167f0988aefa675e81e1db7fca08264db5dc2a1cc2a604f2a78d902a9747146a5671846040518082600b0b815260200191505060405180910390a250505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60007f00000000000000000000000000000000000000000000000000000000000000006004028281610cf357fe5b049392505050565b6001600160a01b039081166000908152602081905260409020541690565b6001546001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015460408051634e7eee1b60e11b81526001600160a01b03848116600483015233602483015291519190921691639cfddc3691604480830192600092919082900301818387803b158015610da057600080fd5b505af1158015610db4573d6000803e3d6000fd5b5050505050565b60007f00000000000000000000000000000000000000000000000000000000000000008281610cf357fe5b6001600160a01b03818116600081815260208190526040808220548151631cd43d1160e31b8152600481019490945230602485015284166044840152519092839283927f00000000000000000000000000000000000000000000000000000000000000009092169163e6a1e88891606480820192608092909190829003018186803b158015610e7457600080fd5b505afa158015610e88573d6000803e3d6000fd5b505050506040513d6080811015610e9e57600080fd5b506020908101516001600160a01b0380871660009081529283905260409092205490925016610ecc85611974565b925092509193909250565b6001600160a01b038416600090815260208190526040902054600160a01b900460ff1615610f4c576040805162461bcd60e51b815260206004820152601c60248201527f544f47413a207265656e7472616e6379206e6f7420616c6c6f77656400000000604482015290519081900360640190fd5b600081600b0b1215610f8f5760405162461bcd60e51b8152600401808060200182810382526023815260200180611a1c6023913960400191505060405180910390fd5b817f000000000000000000000000000000000000000000000000000000000000000082600b0b021115611003576040805162461bcd60e51b81526020600482015260176024820152760a89e8e827440caf0d2e8a4c2e8ca40e8dede40d0d2ced604b1b604482015290519081900360640190fd5b60008261100f86611974565b03905080831161105a576040805162461bcd60e51b8152602060048201526011602482015270544f47413a2062696420746f6f206c6f7760781b604482015290519081900360640190fd5b6001600160a01b03808616600081815260208190526040808220805460ff60a01b198116600160a01b179091558151631cd43d1160e31b815260048101949094523060248501528416604484018190529051909391927f00000000000000000000000000000000000000000000000000000000000000009092169163e6a1e888916064808301926080929190829003018186803b1580156110fa57600080fd5b505afa15801561110e573d6000803e3d6000fd5b505050506040513d608081101561112457600080fd5b506020015190506000600b82900b131561142b57604080516000808252602082019092527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916339255d5b917f000000000000000000000000000000000000000000000000000000000000000091635a5999e360e11b918c91309189915060405160240180856001600160a01b03168152602001846001600160a01b03168152602001836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611218578181015183820152602001611200565b50505050905090810190601f1680156112455780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199a8b16178152905160e08c901b90991689526001600160a01b038a1660048a01908152606060248b01908152835160648c01528351939a919950975060448101965060840194509250905080838360005b838110156112d75781810151838201526020016112bf565b50505050905090810190601f1680156113045780820380516001836020036101000a031916815260200191505b508381038252600281526020018061060f60f31b815250602001945050505050600060405180830381600087803b15801561133e57600080fd5b505af1158015611352573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561137b57600080fd5b8101908080516040519392919084600160201b82111561139a57600080fd5b9083019060208201858111156113af57600080fd5b8251600160201b8111828201881017156113c857600080fd5b82525081516020918201929091019080838360005b838110156113f55781810151838201526020016113dd565b50505050905090810190601f1680156114225780820380516001836020036101000a031916815260200191505b50604052505050505b6001600160a01b038216156115db5760408051634decdde360e11b81526001600160a01b03848116600483015260248201869052606060448301526002606483015261060f60f31b6084830152915191891691639bd9bbc69167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169160a480830192600092919082900301818388803b1580156114d057600080fd5b5087f1935050505080156114e2575060015b6115db57600154604080516001600160a01b0385811660208084019190915283518084038201815283850194859052634decdde360e11b9094529381166044830181815260648401899052606060848501908152855160a48601528551938e1696639bd9bbc69693958b9560c49091019185019080838360005b8381101561157457818101518382015260200161155c565b50505050905090810190601f1680156115a15780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156115c257600080fd5b505af11580156115d6573d6000803e3d6000fd5b505050505b6001600160a01b03878116600090815260208190526040812080546001600160a01b03191692891692909217909155600b85900b131561190257604080516000808252602082019092527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316916339255d5b917f00000000000000000000000000000000000000000000000000000000000000009163317e182f60e11b918c918c918b915060405160240180856001600160a01b03168152602001846001600160a01b0316815260200183600b0b815260200180602001828103825283818151815260200191508051906020019080838360005b838110156116ef5781810151838201526020016116d7565b50505050905090810190601f16801561171c5780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199a8b16178152905160e08c901b90991689526001600160a01b038a1660048a01908152606060248b01908152835160648c01528351939a919950975060448101965060840194509250905080838360005b838110156117ae578181015183820152602001611796565b50505050905090810190601f1680156117db5780820380516001836020036101000a031916815260200191505b508381038252600281526020018061060f60f31b815250602001945050505050600060405180830381600087803b15801561181557600080fd5b505af1158015611829573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561185257600080fd5b8101908080516040519392919084600160201b82111561187157600080fd5b90830190602082018581111561188657600080fd5b8251600160201b81118282018810171561189f57600080fd5b82525081516020918201929091019080838360005b838110156118cc5781810151838201526020016118b4565b50505050905090810190601f1680156118f95780820380516001836020036101000a031916815260200191505b50604052505050505b6001600160a01b0380881660008181526020818152604091829020805460ff60a01b191690558151938a1684528301889052600b87900b838201525190917f836808e57755d5535898b7203c7d68b1bfb2701b1943ecb133c675e0d0078015919081900360600190a250505050505050565b6000806000836001600160a01b0316632ec8eec7306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060806040518083038186803b1580156119c657600080fd5b505afa1580156119da573d6000803e3d6000fd5b505050506040513d60808110156119f057600080fd5b5080516020909101519092509050600081830113611a0f576000611a13565b8082015b94935050505056fe544f47413a206e65676174697665206578697452617465206e6f7420616c6c6f776564a264697066735822122014ae35bf1aeb42a36c3a695f63745f20d13e2aa3768d2a82a458438d637dc44a64736f6c634300070600330000000000000000000000003e14dc1b13c488a8d5d310918780c983bd5982e70000000000000000000000000000000000000000000000000000000000093a800000000000000000000000001bad501b22ab1ffc983a1a563acece561fa53040

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000003e14dc1b13c488a8d5d310918780c983bd5982e70000000000000000000000000000000000000000000000000000000000093a800000000000000000000000001bad501b22ab1ffc983a1a563acece561fa53040

-----Decoded View---------------
Arg [0] : host_ (address): 0x3e14dc1b13c488a8d5d310918780c983bd5982e7
Arg [1] : minBondDuration_ (uint256): 604800
Arg [2] : custodian_ (address): 0x1bad501b22ab1ffc983a1a563acece561fa53040

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000003e14dc1b13c488a8d5d310918780c983bd5982e7
Arg [1] : 0000000000000000000000000000000000000000000000000000000000093a80
Arg [2] : 0000000000000000000000001bad501b22ab1ffc983a1a563acece561fa53040


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.