Contract Overview
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
StreamExchange
Compiler Version
v0.8.3+commit.8d00100c
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma abicoder v2; // import "hardhat/console.sol"; import {ISuperfluid, ISuperToken, ISuperApp, ISuperAgreement, SuperAppDefinitions} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; //"@superfluid-finance/ethereum-monorepo/packages/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; import {IConstantFlowAgreementV1} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/IConstantFlowAgreementV1.sol"; import {IInstantDistributionAgreementV1} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/IInstantDistributionAgreementV1.sol"; import {SuperAppBase} from "@superfluid-finance/ethereum-contracts/contracts/apps/SuperAppBase.sol"; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./tellor/UsingTellor.sol"; import "./StreamExchangeStorage.sol"; import "./StreamExchangeHelper.sol"; import "./tellor/ITellor.sol"; /// @title StreamExchange SuperApp /// @notice This contract is an SuperFluid SuperApp contract StreamExchange is Ownable, SuperAppBase, UsingTellor, Initializable { // TODO: uint256 public constant RATE_PERCISION = 1000000; using SafeERC20 for ERC20; using StreamExchangeHelper for StreamExchangeStorage.StreamExchange; using StreamExchangeStorage for StreamExchangeStorage.StreamExchange; StreamExchangeStorage.StreamExchange internal _exchange; event UpdatedStream(address from, int96 newRate, int96 totalInflow); /// @param host is SuperFluid protocol host address /// @param cfa is SuperFluid Constant Flow Agreement (CFA) address /// @param ida is SuperFluid Instant Distribution Agreement (IDA) address /// @param inputToken is input SuperToken address /// @param outputToken is input SuperToken address /// @param subsidyToken is subsidy SuperToken address /// @param sushiRouter is SushiSwap router address /// @param oracle is the TellorMaster address /// @param requestId is Tellor Oracle requiest id /// @param registrationKey is SuperFluid protocol registration key constructor( ISuperfluid host, IConstantFlowAgreementV1 cfa, IInstantDistributionAgreementV1 ida, ISuperToken inputToken, ISuperToken outputToken, ISuperToken subsidyToken, IUniswapV2Router02 sushiRouter, address payable oracle, uint256 requestId, string memory registrationKey ) UsingTellor(oracle) { require(address(host) != address(0), "host"); require(address(cfa) != address(0), "cfa"); require(address(ida) != address(0), "ida"); require(address(inputToken) != address(0), "inputToken"); require(address(outputToken) != address(0), "output"); require(!host.isApp(ISuperApp(msg.sender)), "owner SA"); initVars( host, cfa, ida, inputToken, outputToken, subsidyToken, sushiRouter, oracle, requestId, registrationKey ); } // @dev the "initVars" function is not for a proxy, hence it's not called "initialize" function initVars( ISuperfluid host, IConstantFlowAgreementV1 cfa, IInstantDistributionAgreementV1 ida, ISuperToken inputToken, ISuperToken outputToken, ISuperToken subsidyToken, IUniswapV2Router02 sushiRouter, address payable oracle, uint256 requestId, string memory registrationKey ) private onlyOwner initializer { _exchange.sushiRouter = sushiRouter; _exchange.host = host; _exchange.cfa = cfa; _exchange.ida = ida; _exchange.inputToken = inputToken; _exchange.outputToken = outputToken; _exchange.subsidyToken = subsidyToken; _exchange.oracle = ITellor(oracle); _exchange.requestId = requestId; _exchange.feeRate = 20000; _exchange.rateTolerance = 10000; _exchange.subsidyIndexId = 1; _exchange.subsidyRate = 4e17; // 0.4 tokens/second ~ 1,000,000 tokens in a month _exchange.owner = msg.sender; // Unlimited approve for sushiswap ERC20(_exchange.inputToken.getUnderlyingToken()).safeIncreaseAllowance( address(_exchange.sushiRouter), 2**256 - 1 ); ERC20(_exchange.outputToken.getUnderlyingToken()).safeIncreaseAllowance( address(_exchange.sushiRouter), 2**256 - 1 ); // and Supertoken upgrades ERC20(_exchange.inputToken.getUnderlyingToken()).safeIncreaseAllowance( address(_exchange.inputToken), 2**256 - 1 ); ERC20(_exchange.outputToken.getUnderlyingToken()).safeIncreaseAllowance( address(_exchange.outputToken), 2**256 - 1 ); uint256 configWord = SuperAppDefinitions.APP_LEVEL_FINAL | SuperAppDefinitions.BEFORE_AGREEMENT_CREATED_NOOP | SuperAppDefinitions.BEFORE_AGREEMENT_UPDATED_NOOP | SuperAppDefinitions.BEFORE_AGREEMENT_TERMINATED_NOOP; if (bytes(registrationKey).length > 0) { _exchange.host.registerAppWithKey(configWord, registrationKey); } else { _exchange.host.registerApp(configWord); } // Set up the IDA for sending tokens back _exchange._createIndex(_exchange.outputIndexId, _exchange.outputToken); // Give the owner 1 share just to start up the contract _exchange._updateSubscription( _exchange.outputIndexId, msg.sender, 1, _exchange.outputToken ); // Setup Liquidity Mining _exchange._initalizeLiquidityMining(); _exchange.lastDistributionAt = block.timestamp; } /************************************************************************** * Stream Exchange Logic *************************************************************************/ /// @dev If a new stream is opened, or an existing one is opened /// @param ctx is SuperFluid context data /// @param agreementData is SuperFluid agreement data (non-compressed) /// @param doDistributeFirst is distribution needed before outflow update /// @return newCtx updated SuperFluid context data function _updateOutflow( bytes calldata ctx, bytes calldata agreementData, bool doDistributeFirst ) private returns (bytes memory newCtx) { newCtx = ctx; (, , uint128 totalUnitsApproved, uint128 totalUnitsPending) = _exchange .ida .getIndex( _exchange.outputToken, address(this), _exchange.outputIndexId ); // Check balance and account for uint256 balance = ISuperToken(_exchange.inputToken).balanceOf( address(this) ) / (10 ** (18 - ERC20(_exchange.inputToken.getUnderlyingToken()) .decimals())); if ( doDistributeFirst && totalUnitsApproved + totalUnitsPending > 0 && balance > 0 ) { newCtx = _exchange._distribute(newCtx); } (address requester, address flowReceiver) = abi.decode( agreementData, (address, address) ); require(flowReceiver == address(this), "!appflow"); int96 appFlowRate = _exchange.cfa.getNetFlow( _exchange.inputToken, address(this) ); (, int96 requesterFlowRate, , ) = _exchange.cfa.getFlow( _exchange.inputToken, requester, address(this) ); // Make sure the requester has at least 8 hours of balance to stream require( int256(_exchange.inputToken.balanceOf(requester)) >= requesterFlowRate * 8 hours, "!enoughTokens" ); require(requesterFlowRate >= 0, "!negativeRates"); newCtx = _exchange._updateSubscriptionWithContext( newCtx, _exchange.outputIndexId, requester, uint128(uint256(int256(requesterFlowRate))), _exchange.outputToken ); newCtx = _exchange._updateSubscriptionWithContext( newCtx, _exchange.subsidyIndexId, requester, uint128(uint256(int256(requesterFlowRate))), _exchange.subsidyToken ); emit UpdatedStream(requester, requesterFlowRate, appFlowRate); } /// @dev Distribute a single `amount` of outputToken among all streamers /// @dev Calculates the amount to distribute /// @dev Usually called by Keeper function distribute() external { _exchange._distribute(new bytes(0)); } /// @dev Close stream from `streamer` address if balance is less than 8 hours of streaming /// @param streamer is stream source (streamer) address function closeStream(address streamer) public { _exchange._closeStream(streamer); } /// @dev Allows anyone to close any stream if the app is jailed. /// @param streamer is stream source (streamer) address function emergencyCloseStream(address streamer) public { _exchange._emergencyCloseStream(streamer); } /// @dev Drain contract's input and output tokens balance to owner if SuperApp dont have any input streams. function emergencyDrain() public { _exchange._emergencyDrain(); } /// @dev Set subsidy rate /// @param subsidyRate is new rate function setSubsidyRate(uint128 subsidyRate) external onlyOwner { _exchange.subsidyRate = subsidyRate; } /// @dev Set fee rate /// @param feeRate is new fee rate function setFeeRate(uint128 feeRate) external onlyOwner { _exchange.feeRate = feeRate; } /// @dev Set rate tolerance /// @param rateTolerance is new rate tolerance function setRateTolerance(uint128 rateTolerance) external onlyOwner { _exchange.rateTolerance = rateTolerance; } /// @dev Set Tellor Oracle address /// @param oracle new Tellor Oracle address function setOracle(address oracle) external onlyOwner { _exchange.oracle = ITellor(oracle); } /// @dev Set Tellor Oracle request ID /// @param requestId Tellor Oracle request ID function setRequestId(uint256 requestId) external onlyOwner { _exchange.requestId = requestId; } /// @dev Is app jailed in SuperFluid protocol /// @return is app jailed in SuperFluid protocol function isAppJailed() external view returns (bool) { return _exchange.host.isAppJailed(this); } /// @dev Get `streamer` IDA subscription info for token with index `index` /// @param index is token index in IDA /// @param streamer is streamer address /// @return exist Does the subscription exist? /// @return approved Is the subscription approved? /// @return units Units of the suscription. /// @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription. function getIDAShares(uint32 index, address streamer) external view returns ( bool exist, bool approved, uint128 units, uint256 pendingDistribution ) { ISuperToken idaToken; if (index == _exchange.outputIndexId) { idaToken = _exchange.outputToken; } else if (index == _exchange.subsidyIndexId) { idaToken = _exchange.subsidyToken; } else { return (exist, approved, units, pendingDistribution); } (exist, approved, units, pendingDistribution) = _exchange .ida .getSubscription(idaToken, address(this), index, streamer); } /// @dev Get input token address /// @return input token address function getInputToken() external view returns (ISuperToken) { return _exchange.inputToken; } /// @dev Get output token address /// @return output token address function getOuputToken() external view returns (ISuperToken) { return _exchange.outputToken; } /// @dev Get output token IDA index /// @return output token IDA index function getOuputIndexId() external view returns (uint32) { return _exchange.outputIndexId; } /// @dev Get subsidy token address /// @return subsidy token address function getSubsidyToken() external view returns (ISuperToken) { return _exchange.subsidyToken; } /// @dev Get subsidy token IDA index /// @return subsidy token IDA index function getSubsidyIndexId() external view returns (uint32) { return _exchange.subsidyIndexId; } /// @dev Get subsidy rate /// @return subsidy rate function getSubsidyRate() external view returns (uint256) { return _exchange.subsidyRate; } /// @dev Get total input flow rate /// @return input flow rate function getTotalInflow() external view returns (int96) { return _exchange.cfa.getNetFlow(_exchange.inputToken, address(this)); } /// @dev Get last distribution timestamp /// @return last distribution timestamp function getLastDistributionAt() external view returns (uint256) { return _exchange.lastDistributionAt; } /// @dev Get SushiSwap router address /// @return SushiSwap router address function getSushiRouter() external view returns (address) { return address(_exchange.sushiRouter); } /// @dev Get Tellor Oracle address /// @return Tellor Oracle address function getTellorOracle() external view returns (address) { return address(_exchange.oracle); } /// @dev Get Tellor Oracle request ID /// @dev Tellor Oracle request ID function getRequestId() external view returns (uint256) { return _exchange.requestId; } /// @dev Get Owner address /// @return owner address function getOwner() external view returns (address) { return _exchange.owner; } /// @dev Get fee rate /// @return fee rate function getFeeRate() external view returns (uint128) { return _exchange.feeRate; } /// @dev Get rate tolerance /// @return rate tolerance function getRateTolerance() external view returns (uint256) { return _exchange.rateTolerance; } /// @dev Get flow rate for `streamer` /// @param streamer is streamer address /// @return requesterFlowRate `streamer` flow rate function getStreamRate(address streamer) external view returns (int96 requesterFlowRate) { (, requesterFlowRate, , ) = _exchange.cfa.getFlow( _exchange.inputToken, streamer, address(this) ); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. * NOTE: Override this to add changing the */ function transferOwnership(address newOwner) public virtual override onlyOwner { super.transferOwnership(newOwner); _exchange.owner = newOwner; } /************************************************************************** * SuperApp callbacks *************************************************************************/ /// @dev SuperFluid protocol callback /// @dev Callback after a new agreement is created. /// @dev Can be called only by SuperFluid protocol host. /// @param _superToken The super token used for the agreement. /// @param _agreementClass The agreement class address. /// @param _agreementData The agreement data (non-compressed) /// @param _ctx The context data. /// @return newCtx The current context of the transaction. function afterAgreementCreated( ISuperToken _superToken, address _agreementClass, bytes32, // _agreementId, bytes calldata _agreementData, bytes calldata, // _cbdata, bytes calldata _ctx ) external override onlyExpected(_superToken, _agreementClass) onlyHost returns (bytes memory newCtx) { console.log("afterAgreementCreated"); if ( !_exchange._isInputToken(_superToken) || !_exchange._isCFAv1(_agreementClass) ) return _ctx; return _updateOutflow(_ctx, _agreementData, true); } /// @dev SuperFluid protocol callback /// @dev Callback after a new agreement is updated. /// @dev Can be called only by SuperFluid protocol host. /// @param _superToken The super token used for the agreement. /// @param _agreementClass The agreement class address. /// @param _agreementData The agreement data (non-compressed) /// @param _ctx The context data. /// @return newCtx The current context of the transaction. function afterAgreementUpdated( ISuperToken _superToken, address _agreementClass, bytes32, //_agreementId, bytes calldata _agreementData, bytes calldata, //_cbdata, bytes calldata _ctx ) external override onlyExpected(_superToken, _agreementClass) onlyHost returns (bytes memory newCtx) { console.log("afterAgreementUpdated"); console.log(_agreementClass); console.log((address(_superToken))); if ( !_exchange._isInputToken(_superToken) || !_exchange._isCFAv1(_agreementClass) ) return _ctx; console.log("_updateOutflow"); return _updateOutflow(_ctx, _agreementData, true); } /// @dev SuperFluid protocol callback /// @dev Callback after a new agreement is terminated. /// @dev Can be called only by SuperFluid protocol host. /// @param _superToken The super token used for the agreement. /// @param _agreementClass The agreement class address. /// @param _agreementData The agreement data (non-compressed) /// @param _ctx The context data. /// @return newCtx The current context of the transaction. function afterAgreementTerminated( ISuperToken _superToken, address _agreementClass, bytes32, //_agreementId, bytes calldata _agreementData, bytes calldata, //_cbdata, bytes calldata _ctx ) external override onlyHost returns (bytes memory newCtx) { console.log("afterAgreementTerminated"); // According to the app basic law, we should never revert in a termination callback if ( !_exchange._isInputToken(_superToken) || !_exchange._isCFAv1(_agreementClass) ) return _ctx; // Skip distribution when terminating to avoid reverts return _updateOutflow(_ctx, _agreementData, false); } /// @dev Restricts calls to only from SuperFluid host modifier onlyHost() { require(msg.sender == address(_exchange.host), "one host"); _; } /// @dev Accept only input token for CFA, output and subsidy tokens for IDA modifier onlyExpected(ISuperToken superToken, address agreementClass) { if (_exchange._isCFAv1(agreementClass)) { require(_exchange._isInputToken(superToken), "!inputAccepted"); } else if (_exchange._isIDAv1(agreementClass)) { require( _exchange._isOutputToken(superToken) || _exchange._isSubsidyToken(superToken), "!outputAccepted" ); } _; } }
// 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 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; */ }
// 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 ); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.7.0; import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol"; import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol"; /** * @title Superfluid's instant distribution agreement interface. * * @author Superfluid * * Notes: * - A publisher can create as many as indeces as possibily identifiable with `indexId`. * - `indexId` is deliberately limited to 32 bits, to avoid the chance for sha-3 collision. * Despite knowing sha-3 collision is only theoratical. * - A publisher can create subscription to an index for any subscriber. * - A subscription consists of: * - The index it subscribes to. * - Number of units subscribed. * - An index consists of: * - Current value as `uint128 indexValue`. * - Total units of the approved subscriptions as `uint128 totalUnitsApproved`. * - Total units of the non approved subscription as `uint128 totalUnitsPending`. * - A publisher can update index with new value that doesn't decrease. * - A publisher can update subscription with any number of units. * - A publisher or a subscriber can delete subscription and reset units to zero. * - A subscriber must approve the index in order to receive distributions from the publisher * each time the index is updated. * - The amount distributed is $$\Delta{index} * units$$ * - Distributions to a non approved subscription stays in the publisher's deposit until: * - the subscriber approve the subscription (side effect), * - the publisher update the subscription (side effect), * - the subscriber delete the subscription even if it is never approved (side effect), * - or the subscriber can explicitly claim them. */ abstract contract IInstantDistributionAgreementV1 is ISuperAgreement { /// @dev ISuperAgreement.agreementType implementation function agreementType() external override pure returns (bytes32) { return keccak256("org.superfluid-finance.agreements.InstantDistributionAgreement.v1"); } /************************************************************************** * Index operations *************************************************************************/ /** * @dev Create a new index for the publisher. * @param token Super token address. * @param indexId Id of the index. * * # App callbacks * * None */ function createIndex( ISuperfluidToken token, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); event IndexCreated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, bytes userData); /** * @dev Query the data of a index. * @param token Super token address. * @param publisher The publisher of the index. * @param indexId Id of the index. * @return exist Does the index exist. * @return indexValue Value of the current index. * @return totalUnitsApproved Total units approved for the index. * @return totalUnitsPending Total units pending approval for the index. */ function getIndex( ISuperfluidToken token, address publisher, uint32 indexId) external view virtual returns( bool exist, uint128 indexValue, uint128 totalUnitsApproved, uint128 totalUnitsPending); /** * @dev Calculate actual distribution amount * @param token Super token address. * @param publisher The publisher of the index. * @param indexId Id of the index. * @param amount The amount of tokens desired to be distributed. */ function calculateDistribution( ISuperfluidToken token, address publisher, uint32 indexId, uint256 amount) external view virtual returns( uint256 actualAmount, uint128 newIndexValue); /** * @dev Update index value of an index. * @param token Super token address. * @param indexId Id of the index. * @param indexValue Value of the index. * * # App callbacks * * None */ function updateIndex( ISuperfluidToken token, uint32 indexId, uint128 indexValue, bytes calldata ctx) external virtual returns(bytes memory newCtx); event IndexUpdated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, uint128 oldIndexValue, uint128 newIndexValue, uint128 totalUnitsPending, uint128 totalUnitsApproved, bytes userData); /** * @dev Distribute tokens through the index. * @param token Super token address. * @param indexId Id of the index. * @param amount The amount of tokens desired to be distributed. * * NOTE: * - This is a convenient version of updateIndex. It adds to the index * a delta that equals to `amount / totalUnits`. * - The actual amount distributed could be obtained via * `calculateDistribution`. This is due to precision error with index * value and units data range. * * # App callbacks * * None */ function distribute( ISuperfluidToken token, uint32 indexId, uint256 amount, bytes calldata ctx) external virtual returns(bytes memory newCtx); /************************************************************************** * Subscription operations *************************************************************************/ /** * @dev Approve the subscription of an index. * @param token Super token address. * @param publisher The publisher of the index. * @param indexId Id of the index. * * # App callbacks * * - if subscription exist * - AgreementCreated callback to the publisher: * - agreementId is for the subscription * - if subscription does not exist * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function approveSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); event IndexSubscribed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, bytes userData); event SubscriptionApproved( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, bytes userData); /** * @dev Revoke the subscription of an index. * @param token Super token address. * @param publisher The publisher of the index. * @param indexId Id of the index. * * # App callbacks * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function revokeSubscription( ISuperfluidToken token, address publisher, uint32 indexId, bytes calldata ctx) external virtual returns(bytes memory newCtx); event IndexUnsubscribed( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, bytes userData); event SubscriptionRevoked( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, bytes userData); /** * @dev Update the nuber of units of a subscription. * @param token Super token address. * @param indexId Id of the index. * @param subscriber The subscriber of the index. * @param units Number of units of the subscription. * * # App callbacks * * - if subscription exist * - AgreementCreated callback to the subscriber: * - agreementId is for the subscription * - if subscription does not exist * - AgreementUpdated callback to the subscriber: * - agreementId is for the subscription */ function updateSubscription( ISuperfluidToken token, uint32 indexId, address subscriber, uint128 units, bytes calldata ctx) external virtual returns(bytes memory newCtx); event IndexUnitsUpdated( ISuperfluidToken indexed token, address indexed publisher, uint32 indexed indexId, address subscriber, uint128 units, bytes userData); event SubscriptionUnitsUpdated( ISuperfluidToken indexed token, address indexed subscriber, address publisher, uint32 indexId, uint128 units, bytes userData); /** * @dev Get data of a subscription * @param token Super token address. * @param publisher The publisher of the index. * @param indexId Id of the index. * @param subscriber The subscriber of the index. * @return exist Does the subscription exist? * @return approved Is the subscription approved? * @return units Units of the suscription. * @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription. */ function getSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber) external view virtual returns( bool exist, bool approved, uint128 units, uint256 pendingDistribution ); /** * @dev Get data of a subscription by agreement ID * @param token Super token address. * @param agreementId The agreement ID. * @return publisher The publisher of the index. * @return indexId Id of the index. * @return approved Is the subscription approved? * @return units Units of the suscription. * @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription. */ function getSubscriptionByID( ISuperfluidToken token, bytes32 agreementId) external view virtual returns( address publisher, uint32 indexId, bool approved, uint128 units, uint256 pendingDistribution ); /** * @dev List subscriptions of an user. * @param token Super token address. * @param subscriber The user, a subscriber. * @return publishers Publishers of the subcriptions. * @return indexIds Indexes of the subscriptions. * @return unitsList Units of the subscriptions. */ function listSubscriptions( ISuperfluidToken token, address subscriber) external view virtual returns( address[] memory publishers, uint32[] memory indexIds, uint128[] memory unitsList); /** * @dev Delete the subscription of an user. * @param token Super token address. * @param publisher The publisher of the index. * @param indexId Id of the index. * @param subscriber The user, a subscriber. * * # App callbacks * * - if the subscriber called it * - AgreementTerminated callback to the publsiher: * - agreementId is for the subscription * - if the publisher called it * - AgreementTerminated callback to the subscriber: * - agreementId is for the subscription */ function deleteSubscription( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx) external virtual returns(bytes memory newCtx); /** * @dev Claim pending distributions. * @param token Super token address. * @param publisher The publisher of the index. * @param indexId Id of the index. * @param subscriber The user, a subscriber. * * The subscription should not exist yet. * * # App callbacks * * - AgreementUpdated callback to the publisher: * - agreementId is for the subscription */ function claim( ISuperfluidToken token, address publisher, uint32 indexId, address subscriber, bytes calldata ctx) external virtual returns(bytes memory newCtx); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.7.0; import { ISuperfluid, ISuperToken, ISuperApp, SuperAppDefinitions } from "../interfaces/superfluid/ISuperfluid.sol"; abstract contract SuperAppBase is ISuperApp { function beforeAgreementCreated( ISuperToken /*superToken*/, address /*agreementClass*/, bytes32 /*agreementId*/, bytes calldata /*agreementData*/, bytes calldata /*ctx*/ ) external view virtual override returns (bytes memory /*cbdata*/) { revert("Unsupported callback - Before Agreement Created"); } function afterAgreementCreated( ISuperToken /*superToken*/, address /*agreementClass*/, bytes32 /*agreementId*/, bytes calldata /*agreementData*/, bytes calldata /*cbdata*/, bytes calldata /*ctx*/ ) external virtual override returns (bytes memory /*newCtx*/) { revert("Unsupported callback - After Agreement Created"); } function beforeAgreementUpdated( ISuperToken /*superToken*/, address /*agreementClass*/, bytes32 /*agreementId*/, bytes calldata /*agreementData*/, bytes calldata /*ctx*/ ) external view virtual override returns (bytes memory /*cbdata*/) { revert("Unsupported callback - Before Agreement updated"); } function afterAgreementUpdated( ISuperToken /*superToken*/, address /*agreementClass*/, bytes32 /*agreementId*/, bytes calldata /*agreementData*/, bytes calldata /*cbdata*/, bytes calldata /*ctx*/ ) external virtual override returns (bytes memory /*newCtx*/) { revert("Unsupported callback - After Agreement Updated"); } function beforeAgreementTerminated( ISuperToken /*superToken*/, address /*agreementClass*/, bytes32 /*agreementId*/, bytes calldata /*agreementData*/, bytes calldata /*ctx*/ ) external view virtual override returns (bytes memory /*cbdata*/) { revert("Unsupported callback - Before Agreement Terminated"); } function afterAgreementTerminated( ISuperToken /*superToken*/, address /*agreementClass*/, bytes32 /*agreementId*/, bytes calldata /*agreementData*/, bytes calldata /*cbdata*/, bytes calldata /*ctx*/ ) external virtual override returns (bytes memory /*newCtx*/) { revert("Unsupported callback - After Agreement Terminated"); } }
pragma solidity >=0.5.0; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @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 this function is * overridden; * * 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() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @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) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @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) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ITellor.sol"; /** * @title UserContract * This contracts creates for easy integration to the Tellor System * by allowing smart contracts to read data off Tellor */ contract UsingTellor { ITellor private tellor; /*Constructor*/ /** * @dev the constructor sets the storage address and owner * @param _tellor is the TellorMaster address */ constructor(address payable _tellor) { tellor = ITellor(_tellor); } /** * @dev Retreive value from oracle based on requestId/timestamp * @param _requestId being requested * @param _timestamp to retreive data/value from * @return uint value for requestId/timestamp submitted */ function retrieveData(uint256 _requestId, uint256 _timestamp) public view returns (uint256) { return tellor.retrieveData(_requestId, _timestamp); } /** * @dev Gets the 5 miners who mined the value for the specified requestId/_timestamp * @param _requestId to looku p * @param _timestamp is the timestamp to look up miners for * @return bool true if requestId/timestamp is under dispute */ function isInDispute(uint256 _requestId, uint256 _timestamp) public view returns (bool) { return tellor.isInDispute(_requestId, _timestamp); } /** * @dev Counts the number of values that have been submited for the request * @param _requestId the requestId to look up * @return uint count of the number of values received for the requestId */ function getNewValueCountbyRequestId(uint256 _requestId) public view returns (uint256) { return tellor.getNewValueCountbyRequestId(_requestId); } /** * @dev Gets the timestamp for the value based on their index * @param _requestId is the requestId to look up * @param _index is the value index to look up * @return uint timestamp */ function getTimestampbyRequestIDandIndex(uint256 _requestId, uint256 _index) public view returns (uint256) { return tellor.getTimestampbyRequestIDandIndex(_requestId, _index); } /** * @dev Allows the user to get the latest value for the requestId specified * @param _requestId is the requestId to look up the value for * @return ifRetrieve bool true if it is able to retreive a value, the value, and the value's timestamp * @return value the value retrieved * @return _timestampRetrieved the value's timestamp */ function getCurrentValue(uint256 _requestId) public view returns ( bool ifRetrieve, uint256 value, uint256 _timestampRetrieved ) { uint256 _count = tellor.getNewValueCountbyRequestId(_requestId); uint256 _time = tellor.getTimestampbyRequestIDandIndex(_requestId, _count - 1); uint256 _value = tellor.retrieveData(_requestId, _time); if (_value > 0) return (true, _value, _time); return (false, 0, _time); } // slither-disable-next-line calls-loop function getIndexForDataBefore(uint256 _requestId, uint256 _timestamp) public view returns (bool found, uint256 index) { uint256 _count = tellor.getNewValueCountbyRequestId(_requestId); if (_count > 0) { uint256 middle; uint256 start = 0; uint256 end = _count - 1; uint256 _time; //Checking Boundaries to short-circuit the algorithm _time = tellor.getTimestampbyRequestIDandIndex(_requestId, start); if (_time >= _timestamp) return (false, 0); _time = tellor.getTimestampbyRequestIDandIndex(_requestId, end); if (_time < _timestamp) return (true, end); //Since the value is within our boundaries, do a binary search while (true) { middle = (end - start) / 2 + 1 + start; _time = tellor.getTimestampbyRequestIDandIndex( _requestId, middle ); if (_time < _timestamp) { //get imeadiate next value uint256 _nextTime = tellor.getTimestampbyRequestIDandIndex( _requestId, middle + 1 ); if (_nextTime >= _timestamp) { //_time is correct return (true, middle); } else { //look from middle + 1(next value) to end start = middle + 1; } } else { uint256 _prevTime = tellor.getTimestampbyRequestIDandIndex( _requestId, middle - 1 ); if (_prevTime < _timestamp) { // _prevtime is correct return (true, middle - 1); } else { //look from start to middle -1(prev value) end = middle - 1; } } //We couldn't found a value //if(middle - 1 == start || middle == _count) return (false, 0); } } return (false, 0); } /** * @dev Allows the user to get the first value for the requestId before the specified timestamp * @param _requestId is the requestId to look up the value for * @param _timestamp before which to search for first verified value * @return _ifRetrieve bool true if it is able to retreive a value, the value, and the value's timestamp * @return _value the value retrieved * @return _timestampRetrieved the value's timestamp */ function getDataBefore(uint256 _requestId, uint256 _timestamp) public view returns ( bool _ifRetrieve, uint256 _value, uint256 _timestampRetrieved ) { (bool _found, uint256 _index) = getIndexForDataBefore(_requestId, _timestamp); if (!_found) return (false, 0, 0); uint256 _time = tellor.getTimestampbyRequestIDandIndex(_requestId, _index); _value = tellor.retrieveData(_requestId, _time); //If value is diputed it'll return zero if (_value > 0) return (true, _value, _time); return (false, 0, 0); } }
import { ISuperfluid, ISuperToken, ISuperApp, ISuperAgreement, SuperAppDefinitions } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; import { IConstantFlowAgreementV1 } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/IConstantFlowAgreementV1.sol"; import { IInstantDistributionAgreementV1 } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/agreements/IInstantDistributionAgreementV1.sol"; import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol'; import "./tellor/ITellor.sol"; library StreamExchangeStorage { /// @dev Stream structure /// @param rate stream rate struct Stream { int96 rate; } /// @dev An exchange generate when StreamExchange is deployed /// @param host Superfluid host contract /// @param cfa The stored constant flow agreement class address /// @param ida The stored instant dist. agreement class address /// @param inputToken The input token (e.g. DAIx) /// @param outputToken The output token (e.g. ETHx) /// @param outputIndexId /// @param subsidyToken The token to use as the subsidy /// @param subsidyRate The number of tokens to distribute subsidy in units per second /// @param subsidyIndexId /// @param lastDistributionAt The last time a distribution was made /// @param sushiRouter Address of sushsiwap router /// @param oracle Address of deployed simple oracle for input/output token /// @param requestId The id of the tellor request that has input/output exchange rate /// @param feeRate The fee taken as a % with 6 decimals /// @param owner The owner of the exchange /// @param rateTolerance The percentage to deviate from the oracle scaled to 1e6 struct StreamExchange { ISuperfluid host; // Superfluid host contract IConstantFlowAgreementV1 cfa; // The stored constant flow agreement class address IInstantDistributionAgreementV1 ida; // The stored instant dist. agreement class address ISuperToken inputToken; // The input token (e.g. DAIx) ISuperToken outputToken; // The output token (e.g. ETHx) uint32 outputIndexId; ISuperToken subsidyToken; // The token to use as the subsidy uint256 subsidyRate; // The number of tokens to distribute subsidy in units per second uint32 subsidyIndexId; uint256 lastDistributionAt; // The last time a distribution was made IUniswapV2Router02 sushiRouter; // Address of sushsiwap router ITellor oracle; // Address of deployed simple oracle for input//output token uint256 requestId; // The id of the tellor request that has input/output exchange rate uint128 feeRate; // The fee taken as a % with 6 decimals address owner; // The owner of the exchange uint256 rateTolerance; // The percentage to deviate from the oracle scaled to 1e6 } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma abicoder v2; import "hardhat/console.sol"; import { ISuperfluid, ISuperToken, ISuperToken, ISuperAgreement } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./tellor/UsingTellor.sol"; import "./StreamExchangeStorage.sol"; /// @title Stream Exchange SuperApp helper library library StreamExchangeHelper { using SafeERC20 for ERC20; // TODO: Emit these events where appropriate /// @dev Distribution event. Emitted on each token distribution operation. /// @param totalAmount is total distributed amount /// @param feeCollected is fee amount collected during distribution /// @param token is distributed token address event Distribution(uint256 totalAmount, uint256 feeCollected, address token); /// @dev Stream update event. Emitted on each stream update. /// @param from is stream origin address /// @param newRate is new stream rate /// @param totalInflow is total incoming input token flow rate event UpdatedStream(address from, int96 newRate, int96 totalInflow); /// @dev Close stream from `streamer` address if balance is less than 8 hours of streaming /// @param streamer is stream source (streamer) address function _closeStream(StreamExchangeStorage.StreamExchange storage self, address streamer) public { // Only closable iff their balance is less than 8 hours of streaming (,int96 streamerFlowRate,,) = self.cfa.getFlow(self.inputToken, streamer, address(this)); require(int(self.inputToken.balanceOf(streamer)) <= streamerFlowRate * 8 hours, "!closable"); // Update Subscriptions _updateSubscription(self, self.subsidyIndexId, streamer, 0, self.subsidyToken); _updateSubscription(self, self.outputIndexId, streamer, 0, self.outputToken); emit UpdatedStream(streamer, 0, self.cfa.getNetFlow(self.inputToken, address(this))); // Close the streamers stream self.host.callAgreement( self.cfa, abi.encodeWithSelector( self.cfa.deleteFlow.selector, self.inputToken, streamer, address(this), new bytes(0) // placeholder ), "0x" ); emit UpdatedStream(streamer, 0, self.cfa.getNetFlow(self.inputToken, address(this))); } /// @dev Allows anyone to close any stream if the app is jailed. /// @param streamer is stream source (streamer) address function _emergencyCloseStream(StreamExchangeStorage.StreamExchange storage self, address streamer) public { // Allows anyone to close any stream if the app is jailed bool isJailed = self.host.isAppJailed(ISuperApp(address(this))); require(isJailed, "!jailed"); self.host.callAgreement( self.cfa, abi.encodeWithSelector( self.cfa.deleteFlow.selector, self.inputToken, streamer, address(this), new bytes(0) // placeholder ), "0x" ); } /// @dev Drain contract's input and output tokens balance to owner if SuperApp dont have any input streams. function _emergencyDrain(StreamExchangeStorage.StreamExchange storage self) public { require(self.cfa.getNetFlow(self.inputToken, address(this)) == 0, "!zeroStreamers"); self.inputToken.transfer(self.owner, self.inputToken.balanceOf(address(this))); self.outputToken.transfer(self.owner, self.outputToken.balanceOf(address(this))); } /// @dev Get currect value from Tellor Oracle /// @param _requestId is request ID in Tellor Oracle /// @return ifRetrieve is bool value that indicates that oracle returned value greater than 0. /// @return value last value for request ID /// @return _timestampRetrieved last value's timestamp function _getCurrentValue( StreamExchangeStorage.StreamExchange storage self, uint256 _requestId ) public view returns ( bool ifRetrieve, uint256 value, uint256 _timestampRetrieved ) { uint256 _count = self.oracle.getNewValueCountbyRequestId(_requestId); uint256 _time = self.oracle.getTimestampbyRequestIDandIndex(_requestId, _count - 1); uint256 _value = self.oracle.retrieveData(_requestId, _time); if (_value > 0) return (true, _value, _time); return (false, 0, _time); } /// @dev Distribute a single `amount` amount of output token among all streamers /// @dev Calculates the amount to distribute /// @param ctx SuperFluid context data /// @return newCtx updated SuperFluid context data function _distribute( StreamExchangeStorage.StreamExchange storage self, bytes memory ctx ) external returns (bytes memory newCtx) { newCtx = ctx; require(self.host.isCtxValid(newCtx) || newCtx.length == 0, "!distributeCtx"); // Get the exchange rate as inputToken per outputToken bool _didGet; uint _timestamp; uint _value; (_didGet, _value, _timestamp) = _getCurrentValue(self, self.requestId); require(_didGet, "!getCurrentValue"); require(_timestamp >= block.timestamp - 3600, "!currentValue"); _swap(self, ISuperToken(self.inputToken).balanceOf(address(this)), _value, block.timestamp + 3600); uint256 outputBalance = ISuperToken(self.outputToken).balanceOf(address(this)); (uint256 actualAmount,) = self.ida.calculateDistribution( self.outputToken, address(this), self.outputIndexId, outputBalance); console.log("outputBalance", outputBalance); console.log("actualAmount", actualAmount); // Return if there's not anything to actually distribute if (actualAmount == 0) { return newCtx; } // Calculate the fee for making the distribution uint256 feeCollected = actualAmount * self.feeRate / 1e6; uint256 distAmount = actualAmount - feeCollected; // Calculate subside uint256 subsidyAmount = (block.timestamp - self.lastDistributionAt) * self.subsidyRate; // Confirm the app has enough to distribute require(self.outputToken.balanceOf(address(this)) >= actualAmount, "!enough"); newCtx = _idaDistribute(self, self.outputIndexId, uint128(distAmount), self.outputToken, newCtx); emit Distribution(distAmount, feeCollected, address(self.outputToken)); // Distribute a subsidy if possible if(self.subsidyToken.balanceOf(address(this)) >= subsidyAmount) { newCtx = _idaDistribute(self, self.subsidyIndexId, uint128(subsidyAmount), self.subsidyToken, newCtx); emit Distribution(subsidyAmount, 0, address(self.subsidyToken)); } self.lastDistributionAt = block.timestamp; // Take the fee ISuperToken(self.outputToken).transfer(self.owner, feeCollected); // NOTE: After swapping any token with < 18 decimals, there may be dust left so just leave it require(self.inputToken.balanceOf(address(this)) / 10 ** (18 - ERC20(self.inputToken.getUnderlyingToken()).decimals()) == 0, "!sellAllInput"); return newCtx; } function _swap( StreamExchangeStorage.StreamExchange storage self, uint256 amount, // Assumes this is outputToken.balanceOf(address(this)) uint256 exchangeRate, uint256 deadline ) public returns(uint) { address inputToken; // The underlying input token address address outputToken; // The underlying output token address address[] memory path; // The path to take uint256 minOutput; // The minimum amount of output tokens based on Tellor uint256 outputAmount; // The balance before the swap inputToken = self.inputToken.getUnderlyingToken(); outputToken = self.outputToken.getUnderlyingToken(); // Downgrade and scale the input amount console.log("Amount", amount); self.inputToken.downgrade(amount); // Scale it to 1e18 for calculations amount = ERC20(inputToken).balanceOf(address(this)) * (10 ** (18 - ERC20(inputToken).decimals())); // TODO: This needs to be "invertable" // USD >> TOK minOutput = amount * 1e18 / exchangeRate / 1e12; // TOK >> USD // minOutput = amount * exchangeRate / 1e6; minOutput = minOutput * (1e6 - self.rateTolerance) / 1e6; // Scale back from 1e18 to outputToken decimals minOutput = minOutput * (10 ** (ERC20(outputToken).decimals())) / 1e18; // Scale it back to inputToken decimals amount = amount / (10 ** (18 - ERC20(inputToken).decimals())); path = new address[](3); path[0] = inputToken; path[1] = 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619; // WETH path[2] = outputToken; self.sushiRouter.swapExactTokensForTokens( amount, 0, // Accept any amount but fail if we're too far from the oracle price path, address(this), deadline ); // Assumes `amount` was outputToken.balanceOf(address(this)) outputAmount = ERC20(outputToken).balanceOf(address(this)); require(outputAmount >= minOutput, "BAD_EXCHANGE_RATE: Try again later"); // Convert the outputToken back to its supertoken version self.outputToken.upgrade(outputAmount * (10 ** (18 - ERC20(outputToken).decimals()))); return outputAmount; } /// @dev Creates SuperFluid IDA index for subsidy token and creates share for sender function _initalizeLiquidityMining(StreamExchangeStorage.StreamExchange storage self) internal { // Create the index for IDA _createIndex(self, self.subsidyIndexId, self.subsidyToken); // Give the initalizer 1 share to get it started _updateSubscription(self, self.subsidyIndexId, msg.sender, 1, self.subsidyToken); } /// @dev Distributes `distAmount` amount of `distToken` token among all IDA index subscribers /// @param index IDA index ID /// @param distAmount amount to distribute /// @param distToken distribute token address /// @param ctx SuperFluid context data /// @return newCtx updated SuperFluid context data function _idaDistribute(StreamExchangeStorage.StreamExchange storage self, uint32 index, uint128 distAmount, ISuperToken distToken, bytes memory ctx) internal returns (bytes memory newCtx) { newCtx = ctx; if (newCtx.length == 0) { // No context provided self.host.callAgreement( self.ida, abi.encodeWithSelector( self.ida.distribute.selector, distToken, index, distAmount, new bytes(0) // placeholder ctx ), new bytes(0) // user data ); } else { require(self.host.isCtxValid(newCtx) || newCtx.length == 0, "!distribute"); (newCtx, ) = self.host.callAgreementWithContext( self.ida, abi.encodeWithSelector( self.ida.distribute.selector, distToken, index, distAmount, new bytes(0) // placeholder ctx ), new bytes(0), // user data newCtx ); } } /// @dev Create new IDA index for `distToken` /// @param index IDA index ID /// @param distToken token address function _createIndex(StreamExchangeStorage.StreamExchange storage self, uint256 index, ISuperToken distToken) internal { self.host.callAgreement( self.ida, abi.encodeWithSelector( self.ida.createIndex.selector, distToken, index, new bytes(0) // placeholder ctx ), new bytes(0) // user data ); } /// @dev Set new `shares` share for `subscriber` address in IDA with `index` index /// @param index IDA index ID /// @param subscriber is subscriber address /// @param shares is distribution shares count /// @param distToken is distribution token address function _updateSubscription( StreamExchangeStorage.StreamExchange storage self, uint256 index, address subscriber, uint128 shares, ISuperToken distToken) internal { self.host.callAgreement( self.ida, abi.encodeWithSelector( self.ida.updateSubscription.selector, distToken, index, // one share for the to get it started subscriber, shares / 1e9, new bytes(0) // placeholder ctx ), new bytes(0) // user data ); } /// @dev Same as _updateSubscription but uses provided SuperFluid context data /// @param ctx SuperFluid context data /// @param index IDA index ID /// @param subscriber is subscriber address /// @param shares is distribution shares count /// @param distToken is distribution token address /// @return newCtx updated SuperFluid context data function _updateSubscriptionWithContext( StreamExchangeStorage.StreamExchange storage self, bytes memory ctx, uint256 index, address subscriber, uint128 shares, ISuperToken distToken) internal returns (bytes memory newCtx) { newCtx = ctx; (newCtx, ) = self.host.callAgreementWithContext( self.ida, abi.encodeWithSelector( self.ida.updateSubscription.selector, distToken, index, subscriber, shares / 1e9, // Number of shares is proportional to their rate new bytes(0) ), new bytes(0), // user data newCtx ); } /// @dev Cancel subscription for `receiver` to `index` IDA index /// @param ctx SuperFluid context data /// @param receiver index publisher address /// @param index IDA index ID /// @param subscriber subscriber address /// @param distToken is distribution token address /// @return newCtx updated SuperFluid context data function _deleteSubscriptionWithContext( StreamExchangeStorage.StreamExchange storage self, bytes memory ctx, address receiver, uint256 index, address subscriber, ISuperToken distToken) internal returns (bytes memory newCtx) { (newCtx, ) = self.host.callAgreementWithContext( self.ida, abi.encodeWithSelector( self.ida.deleteSubscription.selector, distToken, receiver, index, subscriber, new bytes(0) ), new bytes(0), // user data newCtx ); } /************************************************************************** * SuperApp callbacks *************************************************************************/ /// @dev Is `superToken` address an input token? /// @param superToken token address /// @return bool - is `superToken` address an input token function _isInputToken(StreamExchangeStorage.StreamExchange storage self, ISuperToken superToken) internal view returns (bool) { return address(superToken) == address(self.inputToken); } /// @dev Is `superToken` address an output token? /// @param superToken token address /// @return bool - is `superToken` address an output token function _isOutputToken(StreamExchangeStorage.StreamExchange storage self, ISuperToken superToken) internal view returns (bool) { return address(superToken) == address(self.outputToken); } /// @dev Is `superToken` address an subsidy token? /// @param superToken token address /// @return bool - is `superToken` address an subsidy token function _isSubsidyToken(StreamExchangeStorage.StreamExchange storage self, ISuperToken superToken) internal view returns (bool) { return address(superToken) == address(self.subsidyToken); } /// @dev Is provided agreement address an CFA? /// @param agreementClass agreement address /// @return bool - is provided address an CFA function _isCFAv1(StreamExchangeStorage.StreamExchange storage self, address agreementClass) internal view returns (bool) { return ISuperAgreement(agreementClass).agreementType() == keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1"); } /// @dev Is provided agreement address an IDA? /// @param agreementClass agreement address /// @return bool - is provided address an IDA function _isIDAv1(StreamExchangeStorage.StreamExchange storage self, address agreementClass) internal view returns (bool) { return ISuperAgreement(agreementClass).agreementType() == keccak256("org.superfluid-finance.agreements.InstantDistributionAgreement.v1"); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; interface ITellor { /** * @dev Helps initialize a dispute by assigning it a disputeId * when a miner returns a false on the validate array(in Tellor.ProofOfWork) it sends the * invalidated value information to POS voting * @param _requestId being disputed * @param _timestamp being disputed * @param _minerIndex the index of the miner that submitted the value being disputed. Since each official value * requires 5 miners to submit a value. */ function beginDispute( uint256 _requestId, uint256 _timestamp, uint256 _minerIndex ) external; /** * @dev Allows token holders to vote * @param _disputeId is the dispute id * @param _supportsDispute is the vote (true=the dispute has basis false = vote against dispute) */ function vote(uint256 _disputeId, bool _supportsDispute) external; /** * @dev tallies the votes. * @param _disputeId is the dispute id */ function tallyVotes(uint256 _disputeId) external; /** * @dev Allows for a fork to be proposed * @param _propNewTellorAddress address for new proposed Tellor */ function proposeFork(address _propNewTellorAddress) external; /** * @dev Add tip to Request value from oracle * @param _requestId being requested to be mined * @param _tip amount the requester is willing to pay to be get on queue. Miners * mine the onDeckQueryHash, or the api with the highest payout pool */ function addTip(uint256 _requestId, uint256 _tip) external; /** * @dev This is called by the miner when they submit the PoW solution (proof of work and value) * @param _nonce uint submitted by miner * @param _requestId the apiId being mined * @param _value of api query * */ function submitMiningSolution( string calldata _nonce, uint256 _requestId, uint256 _value ) external; /** * @dev This is called by the miner when they submit the PoW solution (proof of work and value) * @param _nonce uint submitted by miner * @param _requestId is the array of the 5 PSR's being mined * @param _value is an array of 5 values */ function submitMiningSolution( string calldata _nonce, uint256[5] calldata _requestId, uint256[5] calldata _value ) external; /** * @dev Allows the current owner to propose transfer control of the contract to a * newOwner and the ownership is pending until the new owner calls the claimOwnership * function * @param _pendingOwner The address to transfer ownership to. */ function proposeOwnership(address payable _pendingOwner) external; /** * @dev Allows the new owner to claim control of the contract */ function claimOwnership() external; /** * @dev This function allows miners to deposit their stake. */ function depositStake() external; /** * @dev This function allows stakers to request to withdraw their stake (no longer stake) * once they lock for withdraw(stakes.currentStatus = 2) they are locked for 7 days before they * can withdraw the stake */ function requestStakingWithdraw() external; /** * @dev This function allows users to withdraw their stake after a 7 day waiting period from request */ function withdrawStake() external; /** * @dev This function approves a _spender an _amount of tokens to use * @param _spender address * @param _amount amount the spender is being approved for * @return true if spender appproved successfully */ function approve(address _spender, uint256 _amount) external returns (bool); /** * @dev Allows for a transfer of tokens to _to * @param _to The address to send tokens to * @param _amount The amount of tokens to send * @return true if transfer is successful */ function transfer(address _to, uint256 _amount) external returns (bool); /** * @dev Sends _amount tokens to _to from _from on the condition it * is approved by _from * @param _from The address holding the tokens being transferred * @param _to The address of the recipient * @param _amount The amount of tokens to be transferred * @return True if the transfer was successful */ function transferFrom( address _from, address _to, uint256 _amount ) external returns (bool); /** * @dev Allows users to access the token's name */ function name() external pure returns (string memory); /** * @dev Allows users to access the token's symbol */ function symbol() external pure returns (string memory); /** * @dev Allows users to access the number of decimals */ function decimals() external pure returns (uint8); /** * @dev Getter for the current variables that include the 5 requests Id's * @return _challenge _requestIds _difficultky _tip the challenge, 5 requestsId, difficulty and tip */ function getNewCurrentVariables() external view returns ( bytes32 _challenge, uint256[5] memory _requestIds, uint256 _difficutly, uint256 _tip ); /** * @dev Getter for the top tipped 5 requests Id's * @return _requestIds the 5 requestsId */ function getTopRequestIDs() external view returns (uint256[5] memory _requestIds); /** * @dev Getter for the 5 requests Id's next in line to get mined * @return idsOnDeck tipsOnDeck the 5 requestsId */ function getNewVariablesOnDeck() external view returns (uint256[5] memory idsOnDeck, uint256[5] memory tipsOnDeck); /** * @dev Updates the Tellor address after a proposed fork has * passed the vote and day has gone by without a dispute * @param _disputeId the disputeId for the proposed fork */ function updateTellor(uint256 _disputeId) external; /** * @dev Allows disputer to unlock the dispute fee * @param _disputeId to unlock fee from */ function unlockDisputeFee(uint256 _disputeId) external; /** * @param _user address * @param _spender address * @return Returns the remaining allowance of tokens granted to the _spender from the _user */ function allowance(address _user, address _spender) external view returns (uint256); /** * @dev This function returns whether or not a given user is allowed to trade a given amount * @param _user address * @param _amount uint of amount * @return true if the user is alloed to trade the amount specified */ function allowedToTrade(address _user, uint256 _amount) external view returns (bool); /** * @dev Gets balance of owner specified * @param _user is the owner address used to look up the balance * @return Returns the balance associated with the passed in _user */ function balanceOf(address _user) external view returns (uint256); /** * @dev Queries the balance of _user at a specific _blockNumber * @param _user The address from which the balance will be retrieved * @param _blockNumber The block number when the balance is queried * @return The balance at _blockNumber */ function balanceOfAt(address _user, uint256 _blockNumber) external view returns (uint256); /** * @dev This function tells you if a given challenge has been completed by a given miner * @param _challenge the challenge to search for * @param _miner address that you want to know if they solved the challenge * @return true if the _miner address provided solved the */ function didMine(bytes32 _challenge, address _miner) external view returns (bool); /** * @dev Checks if an address voted in a given dispute * @param _disputeId to look up * @param _address to look up * @return bool of whether or not party voted */ function didVote(uint256 _disputeId, address _address) external view returns (bool); /** * @dev allows Tellor to read data from the addressVars mapping * @param _data is the keccak256("variable_name") of the variable that is being accessed. * These are examples of how the variables are saved within other functions: * addressVars[keccak256("_owner")] * addressVars[keccak256("tellorContract")] * return address */ function getAddressVars(bytes32 _data) external view returns (address); /** * @dev Gets all dispute variables * @param _disputeId to look up * @return bytes32 hash of dispute * @return bool executed where true if it has been voted on * @return bool disputeVotePassed * @return bool isPropFork true if the dispute is a proposed fork * @return address of reportedMiner * @return address of reportingParty * @return address of proposedForkAddress * uint of requestId * uint of timestamp * uint of value * uint of minExecutionDate * uint of numberOfVotes * uint of blocknumber * uint of minerSlot * uint of quorum * uint of fee * @return int count of the current tally */ function getAllDisputeVars(uint256 _disputeId) external view returns ( bytes32, bool, bool, bool, address, address, address, uint256[9] memory, int256 ); /** * @dev Getter function for variables for the requestId being currently mined(currentRequestId) * @return current challenge, curretnRequestId, level of difficulty, api/query string, and granularity(number of decimals requested), total tip for the request */ function getCurrentVariables() external view returns ( bytes32, uint256, uint256, string memory, uint256, uint256 ); /** * @dev Checks if a given hash of miner,requestId has been disputed * @param _hash is the sha256(abi.encodePacked(_miners[2],_requestId)); * @return uint disputeId */ function getDisputeIdByDisputeHash(bytes32 _hash) external view returns (uint256); /** * @dev Checks for uint variables in the disputeUintVars mapping based on the disuputeId * @param _disputeId is the dispute id; * @param _data the variable to pull from the mapping. _data = keccak256("variable_name") where variable_name is * the variables/strings used to save the data in the mapping. The variables names are * commented out under the disputeUintVars under the Dispute struct * @return uint value for the bytes32 data submitted */ function getDisputeUintVars(uint256 _disputeId, bytes32 _data) external view returns (uint256); /** * @dev Gets the a value for the latest timestamp available * @return value for timestamp of last proof of work submited * @return true if the is a timestamp for the lastNewValue */ function getLastNewValue() external view returns (uint256, bool); /** * @dev Gets the a value for the latest timestamp available * @param _requestId being requested * @return value for timestamp of last proof of work submited and if true if it exist or 0 and false if it doesn't */ function getLastNewValueById(uint256 _requestId) external view returns (uint256, bool); /** * @dev Gets blocknumber for mined timestamp * @param _requestId to look up * @param _timestamp is the timestamp to look up blocknumber * @return uint of the blocknumber which the dispute was mined */ function getMinedBlockNum(uint256 _requestId, uint256 _timestamp) external view returns (uint256); /** * @dev Gets the 5 miners who mined the value for the specified requestId/_timestamp * @param _requestId to look up * @param _timestamp is the timestamp to look up miners for * @return the 5 miners' addresses */ function getMinersByRequestIdAndTimestamp( uint256 _requestId, uint256 _timestamp ) external view returns (address[5] memory); /** * @dev Counts the number of values that have been submited for the request * if called for the currentRequest being mined it can tell you how many miners have submitted a value for that * request so far * @param _requestId the requestId to look up * @return uint count of the number of values received for the requestId */ function getNewValueCountbyRequestId(uint256 _requestId) external view returns (uint256); /** * @dev Getter function for the specified requestQ index * @param _index to look up in the requestQ array * @return uint of reqeuestId */ function getRequestIdByRequestQIndex(uint256 _index) external view returns (uint256); /** * @dev Getter function for requestId based on timestamp * @param _timestamp to check requestId * @return uint of reqeuestId */ function getRequestIdByTimestamp(uint256 _timestamp) external view returns (uint256); /** * @dev Getter function for requestId based on the queryHash * @param _request is the hash(of string api and granularity) to check if a request already exists * @return uint requestId */ function getRequestIdByQueryHash(bytes32 _request) external view returns (uint256); /** * @dev Getter function for the requestQ array * @return the requestQ arrray */ function getRequestQ() external view returns (uint256[51] memory); /** * @dev Allowes access to the uint variables saved in the apiUintVars under the requestDetails struct * for the requestId specified * @param _requestId to look up * @param _data the variable to pull from the mapping. _data = keccak256("variable_name") where variable_name is * the variables/strings used to save the data in the mapping. The variables names are * commented out under the apiUintVars under the requestDetails struct * @return uint value of the apiUintVars specified in _data for the requestId specified */ function getRequestUintVars(uint256 _requestId, bytes32 _data) external view returns (uint256); /** * @dev Gets the API struct variables that are not mappings * @param _requestId to look up * @return string of api to query * @return string of symbol of api to query * @return bytes32 hash of string * @return bytes32 of the granularity(decimal places) requested * @return uint of index in requestQ array * @return uint of current payout/tip for this requestId */ function getRequestVars(uint256 _requestId) external view returns ( string memory, string memory, bytes32, uint256, uint256, uint256 ); /** * @dev This function allows users to retireve all information about a staker * @param _staker address of staker inquiring about * @return uint current state of staker * @return uint startDate of staking */ function getStakerInfo(address _staker) external view returns (uint256, uint256); /** * @dev Gets the 5 miners who mined the value for the specified requestId/_timestamp * @param _requestId to look up * @param _timestamp is the timestampt to look up miners for * @return address[5] array of 5 addresses ofminers that mined the requestId */ function getSubmissionsByTimestamp(uint256 _requestId, uint256 _timestamp) external view returns (uint256[5] memory); /** * @dev Gets the timestamp for the value based on their index * @param _requestID is the requestId to look up * @param _index is the value index to look up * @return uint timestamp */ function getTimestampbyRequestIDandIndex(uint256 _requestID, uint256 _index) external view returns (uint256); /** * @dev Getter for the variables saved under the TellorStorageStruct uintVars variable * @param _data the variable to pull from the mapping. _data = keccak256("variable_name") where variable_name is * the variables/strings used to save the data in the mapping. The variables names are * commented out under the uintVars under the TellorStorageStruct struct * This is an example of how data is saved into the mapping within other functions: * self.uintVars[keccak256("stakerCount")] * @return uint of specified variable */ function getUintVar(bytes32 _data) external view returns (uint256); /** * @dev Getter function for next requestId on queue/request with highest payout at time the function is called * @return onDeck/info on request with highest payout-- RequestId, Totaltips, and API query string */ function getVariablesOnDeck() external view returns ( uint256, uint256, string memory ); /** * @dev Gets the 5 miners who mined the value for the specified requestId/_timestamp * @param _requestId to look up * @param _timestamp is the timestamp to look up miners for * @return bool true if requestId/timestamp is under dispute */ function isInDispute(uint256 _requestId, uint256 _timestamp) external view returns (bool); /** * @dev Retreive value from oracle based on timestamp * @param _requestId being requested * @param _timestamp to retreive data/value from * @return value for timestamp submitted */ function retrieveData(uint256 _requestId, uint256 _timestamp) external view returns (uint256); /** * @dev Getter for the total_supply of oracle tokens * @return uint total supply */ function totalSupply() external view returns (uint256); }
// 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 updateSuperTokenLogic( ISuperfluid host, ISuperToken token) external; /// @dev Get configuration as address value function getConfigAsAddress( ISuperfluid host, ISuperfluidToken superToken, bytes32 key) external view returns (address value); /// @dev Get configuration as uint256 value function getConfigAsUint256( ISuperfluid host, ISuperfluidToken superToken, bytes32 key) external view returns (uint256 value); }
// SPDX-License-Identifier: AGPLv3 pragma solidity >= 0.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; }
// 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 }
// 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); }
// 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 ); }
// 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); }
// 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 getAppWhiteListingSecretKey(address deployer, string memory registrationkey) internal pure returns (bytes32) { return keccak256(abi.encode( "org.superfluid-finance.superfluid.appWhiteListing.seed", deployer, registrationkey)); } }
// 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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC777Token standard as defined in the EIP. * * This contract uses the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let * token holders and recipients react to token movements by using setting implementers * for the associated interfaces in said registry. See {IERC1820Registry} and * {ERC1820Implementer}. */ interface IERC777 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * For most token contracts, this value will equal 1. */ function granularity() external view returns (uint256); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address owner) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send( address recipient, uint256 amount, bytes calldata data ) external; /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply. * * If a send hook is registered for the caller, the corresponding function * will be called with `data` and empty `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata data) external; /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * Emits an {AuthorizedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external; /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * Emits a {RevokedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function revokeOperator(address operator) external; /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `data` and `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; event Sent( address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData ); event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); event AuthorizedOperator(address indexed operator, address indexed tokenHolder); event RevokedOperator(address indexed operator, address indexed tokenHolder); }
// SPDX-License-Identifier: 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 {}
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity >= 0.4.22 <0.9.0; library console { address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); function _sendLogPayload(bytes memory payload) private view { uint256 payloadLength = payload.length; address consoleAddress = CONSOLE_ADDRESS; assembly { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } function log() internal view { _sendLogPayload(abi.encodeWithSignature("log()")); } function logInt(int p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); } function logUint(uint p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); } function logString(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function logBool(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function logAddress(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function logBytes(bytes memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } function logBytes1(bytes1 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } function logBytes2(bytes2 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } function logBytes3(bytes3 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } function logBytes4(bytes4 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } function logBytes5(bytes5 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } function logBytes6(bytes6 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } function logBytes7(bytes7 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } function logBytes8(bytes8 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } function logBytes9(bytes9 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } function logBytes10(bytes10 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } function logBytes11(bytes11 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } function logBytes12(bytes12 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } function logBytes13(bytes13 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } function logBytes14(bytes14 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } function logBytes15(bytes15 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } function logBytes16(bytes16 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } function logBytes17(bytes17 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } function logBytes18(bytes18 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } function logBytes19(bytes19 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } function logBytes20(bytes20 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } function logBytes21(bytes21 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } function logBytes22(bytes22 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } function logBytes23(bytes23 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } function logBytes24(bytes24 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } function logBytes25(bytes25 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } function logBytes26(bytes26 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } function logBytes27(bytes27 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } function logBytes28(bytes28 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } function logBytes29(bytes29 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } function logBytes30(bytes30 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } function logBytes31(bytes31 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } function logBytes32(bytes32 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } function log(uint p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); } function log(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function log(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function log(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function log(uint p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); } function log(uint p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); } function log(uint p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); } function log(uint p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); } function log(string memory p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); } function log(string memory p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } function log(string memory p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } function log(string memory p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } function log(bool p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); } function log(bool p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } function log(bool p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } function log(bool p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } function log(address p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); } function log(address p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } function log(address p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } function log(address p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } function log(uint p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); } function log(uint p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); } function log(uint p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); } function log(uint p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); } function log(uint p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); } function log(uint p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); } function log(uint p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); } function log(uint p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); } function log(uint p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); } function log(uint p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); } function log(uint p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); } function log(uint p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); } function log(uint p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); } function log(uint p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); } function log(uint p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); } function log(uint p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); } function log(string memory p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); } function log(string memory p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); } function log(string memory p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); } function log(string memory p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); } function log(string memory p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); } function log(string memory p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } function log(string memory p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } function log(string memory p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } function log(string memory p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); } function log(string memory p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } function log(string memory p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } function log(string memory p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } function log(string memory p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); } function log(string memory p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } function log(string memory p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } function log(string memory p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } function log(bool p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); } function log(bool p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); } function log(bool p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); } function log(bool p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); } function log(bool p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); } function log(bool p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } function log(bool p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } function log(bool p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } function log(bool p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); } function log(bool p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } function log(bool p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } function log(bool p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } function log(bool p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); } function log(bool p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } function log(bool p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } function log(bool p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } function log(address p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); } function log(address p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); } function log(address p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); } function log(address p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); } function log(address p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); } function log(address p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } function log(address p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } function log(address p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } function log(address p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); } function log(address p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } function log(address p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } function log(address p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } function log(address p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); } function log(address p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } function log(address p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } function log(address p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } function log(uint p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/StreamExchangeHelper.sol": { "StreamExchangeHelper": "0x7cd2532047b597003f6c91183af5327d91442718" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract ISuperfluid","name":"host","type":"address"},{"internalType":"contract IConstantFlowAgreementV1","name":"cfa","type":"address"},{"internalType":"contract IInstantDistributionAgreementV1","name":"ida","type":"address"},{"internalType":"contract ISuperToken","name":"inputToken","type":"address"},{"internalType":"contract ISuperToken","name":"outputToken","type":"address"},{"internalType":"contract ISuperToken","name":"subsidyToken","type":"address"},{"internalType":"contract IUniswapV2Router02","name":"sushiRouter","type":"address"},{"internalType":"address payable","name":"oracle","type":"address"},{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"string","name":"registrationKey","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"int96","name":"newRate","type":"int96"},{"indexed":false,"internalType":"int96","name":"totalInflow","type":"int96"}],"name":"UpdatedStream","type":"event"},{"inputs":[{"internalType":"contract ISuperToken","name":"_superToken","type":"address"},{"internalType":"address","name":"_agreementClass","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"_agreementData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"_ctx","type":"bytes"}],"name":"afterAgreementCreated","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"_superToken","type":"address"},{"internalType":"address","name":"_agreementClass","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"_agreementData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"_ctx","type":"bytes"}],"name":"afterAgreementTerminated","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"_superToken","type":"address"},{"internalType":"address","name":"_agreementClass","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"_agreementData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"_ctx","type":"bytes"}],"name":"afterAgreementUpdated","outputs":[{"internalType":"bytes","name":"newCtx","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"beforeAgreementCreated","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"beforeAgreementTerminated","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperToken","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"beforeAgreementUpdated","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"streamer","type":"address"}],"name":"closeStream","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"streamer","type":"address"}],"name":"emergencyCloseStream","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyDrain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getCurrentValue","outputs":[{"internalType":"bool","name":"ifRetrieve","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"_timestampRetrieved","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getDataBefore","outputs":[{"internalType":"bool","name":"_ifRetrieve","type":"bool"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_timestampRetrieved","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeRate","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"index","type":"uint32"},{"internalType":"address","name":"streamer","type":"address"}],"name":"getIDAShares","outputs":[{"internalType":"bool","name":"exist","type":"bool"},{"internalType":"bool","name":"approved","type":"bool"},{"internalType":"uint128","name":"units","type":"uint128"},{"internalType":"uint256","name":"pendingDistribution","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getIndexForDataBefore","outputs":[{"internalType":"bool","name":"found","type":"bool"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInputToken","outputs":[{"internalType":"contract ISuperToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastDistributionAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"}],"name":"getNewValueCountbyRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOuputIndexId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOuputToken","outputs":[{"internalType":"contract ISuperToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRateTolerance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"streamer","type":"address"}],"name":"getStreamRate","outputs":[{"internalType":"int96","name":"requesterFlowRate","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSubsidyIndexId","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSubsidyRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSubsidyToken","outputs":[{"internalType":"contract ISuperToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSushiRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTellorOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getTimestampbyRequestIDandIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalInflow","outputs":[{"internalType":"int96","name":"","type":"int96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isAppJailed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"isInDispute","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"retrieveData","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"feeRate","type":"uint128"}],"name":"setFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"oracle","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"rateTolerance","type":"uint128"}],"name":"setRateTolerance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"setRequestId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"subsidyRate","type":"uint128"}],"name":"setSubsidyRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200469b3803806200469b833981016040819052620000349162000ec5565b82620000403362000279565b600180546001600160a01b0319166001600160a01b039283161790558a166200009e5760405162461bcd60e51b815260040162000095906020808252600490820152631a1bdcdd60e21b604082015260600190565b60405180910390fd5b6001600160a01b038916620000dc5760405162461bcd60e51b815260206004820152600360248201526263666160e81b604482015260640162000095565b6001600160a01b0388166200011a5760405162461bcd60e51b815260206004820152600360248201526269646160e81b604482015260640162000095565b6001600160a01b0387166200015f5760405162461bcd60e51b815260206004820152600a60248201526934b7383aba2a37b5b2b760b11b604482015260640162000095565b6001600160a01b038616620001a05760405162461bcd60e51b81526020600482015260066024820152651bdd5d1c1d5d60d21b604482015260640162000095565b604051631e51d6a760e11b81523360048201526001600160a01b038b1690633ca3ad4e9060240160206040518083038186803b158015620001e057600080fd5b505afa158015620001f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200021b919062000e51565b15620002555760405162461bcd60e51b81526020600482015260086024820152676f776e657220534160c01b604482015260640162000095565b620002698a8a8a8a8a8a8a8a8a8a620002c9565b50505050505050505050620011b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b03163314620003255760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000095565b600154600160a81b900460ff1680620003485750600154600160a01b900460ff16155b620003ad5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840162000095565b600154600160a81b900460ff16158015620003d8576001805461ffff60a01b191661010160a01b1790555b600b80546001600160a01b038088166001600160a01b03199283168117909355600280548f8316908416179055600380548e8316908416179055600480548d8316908416178155600580548d84169085168117909155600680548d8516908616179055600780548c8516908616179055600c8054938a1693851693909317909255600d879055600e80546001600160801b031916614e201790556127106010556009805463ffffffff1916600117905567058d15e176280000600855600f8054909316331790925560408051631dce337960e31b81529051620005369493600019939263ee719bc89281830192602092829003018186803b158015620004dd57600080fd5b505afa158015620004f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000518919062000e32565b6001600160a01b0316620007b060201b62001b37179092919060201c565b600b5460065460408051631dce337960e31b815290516200058b936001600160a01b03908116936000199391169163ee719bc891600481810192602092909190829003018186803b158015620004dd57600080fd5b60055460408051631dce337960e31b81529051620005d9926001600160a01b03169160001991839163ee719bc8916004808301926020929190829003018186803b158015620004dd57600080fd5b60065460408051631dce337960e31b8152905162000627926001600160a01b03169160001991839163ee719bc8916004828101926020929190829003018186803b158015620004dd57600080fd5b81516415000000019015620006a45760025460405163bd1c448b60e01b81526001600160a01b039091169063bd1c448b906200066a9084908790600401620010e7565b600060405180830381600087803b1580156200068557600080fd5b505af11580156200069a573d6000803e3d6000fd5b5050505062000705565b6002546040516315a722b960e31b8152600481018390526001600160a01b039091169063ad3915c890602401600060405180830381600087803b158015620006eb57600080fd5b505af115801562000700573d6000803e3d6000fd5b505050505b6006546200073990600290600160a01b810463ffffffff16906001600160a01b0316620008a6602090811b62001c1a17901c565b6006546200077290600290600160a01b810463ffffffff169033906001906001600160a01b03166200099c602090811b62001d0817901c565b62000789600262000aab60201b62001e0d1760201c565b5042600a558015620007a3576001805460ff60a81b191690555b5050505050505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015620007fd57600080fd5b505afa15801562000812573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000838919062000fb3565b62000844919062001102565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620008a09186919062000b0516565b50505050565b825460028401546040805160008152602081019091526001600160a01b03928316926339255d5b921690636bc3c20560e11b90620008ec908690889060448101620010a0565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199586161790528151600081529081019182905260e086901b90931690526200094292916024810162001018565b600060405180830381600087803b1580156200095d57600080fd5b505af115801562000972573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620008a0919081019062000e73565b845460028601546001600160a01b03918216916339255d5b9116630465a56b60e31b848888620009d1633b9aca008a62001127565b604080516000815260208101909152620009f39493929190604481016200105c565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199586161790528151600081529081019182905260e086901b909316905262000a4992916024810162001018565b600060405180830381600087803b15801562000a6457600080fd5b505af115801562000a79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000aa3919081019062000e73565b505050505050565b6007810154600582015462000ad491839163ffffffff909116906001600160a01b0316620008a6565b6007810154600582015462000b0291839163ffffffff9091169033906001906001600160a01b03166200099c565b50565b600062000b61826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662000be860201b62001e60179092919060201c565b80519091501562000be3578080602001905181019062000b82919062000e51565b62000be35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000095565b505050565b606062000bf9848460008562000c03565b90505b9392505050565b60608247101562000c665760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000095565b62000c718562000d3f565b62000cbf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000095565b600080866001600160a01b0316858760405162000cdd919062000ffa565b60006040518083038185875af1925050503d806000811462000d1c576040519150601f19603f3d011682016040523d82523d6000602084013e62000d21565b606091505b50909250905062000d3482828662000d49565b979650505050505050565b803b15155b919050565b6060831562000d5a57508162000bfc565b82511562000d6b5782518084602001fd5b8160405162461bcd60e51b8152600401620000959190620010d2565b60006001600160401b038084111562000da45762000da462001189565b604051601f8501601f19908116603f0116810190828211818310171562000dcf5762000dcf62001189565b8160405280935085815286868601111562000de957600080fd5b62000df98660208301876200115a565b5050509392505050565b805162000d44816200119f565b600082601f83011262000e21578081fd5b62000bfc8383516020850162000d87565b60006020828403121562000e44578081fd5b815162000bfc816200119f565b60006020828403121562000e63578081fd5b8151801515811462000bfc578182fd5b60006020828403121562000e85578081fd5b81516001600160401b0381111562000e9b578182fd5b8201601f8101841362000eac578182fd5b62000ebd8482516020840162000d87565b949350505050565b6000806000806000806000806000806101408b8d03121562000ee5578586fd5b8a5162000ef2816200119f565b60208c0151909a5062000f05816200119f565b60408c015190995062000f18816200119f565b60608c015190985062000f2b816200119f565b60808c015190975062000f3e816200119f565b955062000f4e60a08c0162000e03565b945062000f5e60c08c0162000e03565b935062000f6e60e08c0162000e03565b6101008c01516101208d015191945092506001600160401b0381111562000f93578182fd5b62000fa18d828e0162000e10565b9150509295989b9194979a5092959850565b60006020828403121562000fc5578081fd5b5051919050565b6000815180845262000fe68160208601602086016200115a565b601f01601f19169290920160200192915050565b600082516200100e8184602087016200115a565b9190910192915050565b6001600160a01b03841681526060602082018190526000906200103e9083018562000fcc565b828103604084015262001052818562000fcc565b9695505050505050565b6001600160a01b03868116825260208201869052841660408201526001600160801b038316606082015260a06080820181905260009062000d349083018462000fcc565b600060018060a01b038516825283602083015260606040830152620010c9606083018462000fcc565b95945050505050565b60006020825262000bfc602083018462000fcc565b60008382526040602083015262000bf9604083018462000fcc565b600082198211156200112257634e487b7160e01b81526011600452602481fd5b500190565b60006001600160801b03838116806200114e57634e487b7160e01b83526012600452602483fd5b92169190910492915050565b60005b83811015620011775781810151838201526020016200115d565b83811115620008a05750506000910152565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811462000b0257600080fd5b6134d680620011c56000396000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c80637adbf97311610146578063a75d6daa116100c3578063cdf5bd7511610087578063cdf5bd751461058b578063d86ed3e514610593578063de4b9e93146105a6578063e4fc6b6d146105b9578063e52e43da146105c1578063f2fde38b146105d25761025e565b8063a75d6daa1461051c578063ad2ffd9c1461052a578063b3acf8021461053d578063b73e497914610550578063c277c3761461057a5761025e565b80638d21b5931161010a5780638d21b593146104b45780638da5cb5b146104bc57806390389187146104cd57806393fa4915146104f85780639c42a9991461050b5761025e565b80637adbf9731461045157806380f8620f1461046457806384e5eed014610475578063884d1f4014610490578063893d20e8146104a35761025e565b80633fcad964116101df5780635f9e7d77116101a35780635f9e7d77146103d857806366b44611146103eb57806369f07e05146103fe578063715018a61461041157806372667cdb1461041957806377fbb6631461043e5761025e565b80633fcad96414610354578063416c339d1461038457806346eee1c41461039f5780634933e08c146103b257806353c11f99146103c55761025e565b8063246497ed11610226578063246497ed1461030b57806329fe587b1461031e5780632caac08b1461032657806330d9c9151461032e5780633df0777b146103415761025e565b8063077001b9146102635780630c9dfd1e1461027a5780630f2dc3d6146102be57806315843a01146102d3578063230dbd29146102eb575b600080fd5b600d545b6040519081526020015b60405180910390f35b61028d610288366004612f9c565b6105e5565b6040516102719493929190931515845291151560208401526001600160801b03166040830152606082015260800190565b6102d16102cc366004612bb2565b6106f5565b005b6102db61076b565b6040519015158152602001610271565b6102fe6102f9366004612e2b565b6107ec565b604051610271919061302a565b6102d1610319366004612f0c565b6109f9565b600854610267565b6102d1610a31565b6102fe61033c366004612d8f565b610a96565b6102db61034f366004612f7b565b610af9565b610367610362366004612f28565b610b84565b604080519315158452602084019290925290820152606001610271565b61038c610d56565b604051600b9190910b8152602001610271565b6102676103ad366004612f28565b610de0565b6102d16103c0366004612f28565b610e65565b6102fe6103d3366004612e2b565b610e94565b6102fe6103e6366004612d8f565b610f86565b6103676103f9366004612f7b565b610fed565b61038c61040c366004612bb2565b61114e565b6102d16111ea565b600b546001600160a01b03165b6040516001600160a01b039091168152602001610271565b61026761044c366004612f7b565b611220565b6102d161045f366004612bb2565b6112a5565b600c546001600160a01b0316610426565b600e546040516001600160801b039091168152602001610271565b6102fe61049e366004612d8f565b6112f1565b600f546001600160a01b0316610426565b601054610267565b6000546001600160a01b0316610426565b6104e3600654600160a01b900463ffffffff1690565b60405163ffffffff9091168152602001610271565b610267610506366004612f7b565b611354565b6006546001600160a01b0316610426565b60095463ffffffff166104e3565b6102d1610538366004612f0c565b61138d565b6102d161054b366004612f0c565b6113c5565b61056361055e366004612f7b565b61141a565b604080519215158352602083019190915201610271565b6007546001600160a01b0316610426565b600a54610267565b6102fe6105a1366004612e2b565b611856565b6102d16105b4366004612bb2565b6119fd565b6102d1611a44565b6005546001600160a01b0316610426565b6102d16105e0366004612bb2565b611ae2565b600654600090819081908190819063ffffffff888116600160a01b90920416141561061c57506006546001600160a01b0316610647565b60095463ffffffff8881169116141561064157506007546001600160a01b0316610647565b506106ec565b60048054604051635b53405160e01b81526001600160a01b038481169382019390935230602482015263ffffffff8a1660448201528883166064820152911690635b5340519060840160806040518083038186803b1580156106a857600080fd5b505afa1580156106bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e09190612c3c565b92975090955093509150505b92959194509250565b604051631bfeffdb60e21b8152600260048201526001600160a01b0382166024820152737cd2532047b597003f6c91183af5327d9144271890636ffbff6c906044015b60006040518083038186803b15801561075057600080fd5b505af4158015610764573d6000803e3d6000fd5b5050505050565b600254604051636b4f333560e01b81523060048201526000916001600160a01b031690636b4f33359060240160206040518083038186803b1580156107af57600080fd5b505afa1580156107c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e79190612c22565b905090565b606089896107fb600282611e77565b15610858576005546001600160a01b038084169116146108535760405162461bcd60e51b815260206004820152600e60248201526d085a5b9c1d5d1058d8d95c1d195960921b60448201526064015b60405180910390fd5b6108cf565b610863600282611f13565b156108cf576006546001600160a01b038084169116148061089157506007546001600160a01b038084169116145b6108cf5760405162461bcd60e51b815260206004820152600f60248201526e085bdd5d1c1d5d1058d8d95c1d1959608a1b604482015260640161084a565b6002546001600160a01b031633146108f95760405162461bcd60e51b815260040161084a9061312f565b61092f6040518060400160405280601581526020017418599d195c9059dc99595b595b9d155c19185d1959605a1b815250611f6f565b6109388b611fb2565b6109418c611fb2565b6005546001600160a01b03808e169116141580610966575061096460028c611e77565b155b156109aa5784848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506109ea92505050565b6109d96040518060400160405280600e81526020016d5f7570646174654f7574666c6f7760901b815250611f6f565b6109e785858b8b6001611ffa565b92505b50509998505050505050505050565b6000546001600160a01b03163314610a235760405162461bcd60e51b815260040161084a90613151565b6001600160801b0316601055565b60405163110810d760e31b815260026004820152737cd2532047b597003f6c91183af5327d914427189063884086b89060240160006040518083038186803b158015610a7c57600080fd5b505af4158015610a90573d6000803e3d6000fd5b50505050565b60405162461bcd60e51b815260206004820152602f60248201527f556e737570706f727465642063616c6c6261636b202d204265666f726520416760448201526e1c99595b595b9d0810dc99585d1959608a1b606482015260609060840161084a565b600154604051633df0777b60e01b815260048101849052602481018390526000916001600160a01b031690633df0777b9060440160206040518083038186803b158015610b4557600080fd5b505afa158015610b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d9190612c22565b9392505050565b6001546040516311bbb87160e21b8152600481018390526000918291829182916001600160a01b03909116906346eee1c49060240160206040518083038186803b158015610bd157600080fd5b505afa158015610be5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c099190612ce3565b600180549192506000916001600160a01b0316906377fbb663908890610c2f90866133ce565b6040516001600160e01b031960e085901b1681526004810192909252602482015260440160206040518083038186803b158015610c6b57600080fd5b505afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca39190612ce3565b6001546040516393fa491560e01b815260048101899052602481018390529192506000916001600160a01b03909116906393fa49159060440160206040518083038186803b158015610cf457600080fd5b505afa158015610d08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2c9190612ce3565b90508015610d43576001955093509150610d4f9050565b50600094508493509150505b9193909250565b60035460055460405163e8e7e2d160e01b81526001600160a01b039182166004820152306024820152600092919091169063e8e7e2d19060440160206040518083038186803b158015610da857600080fd5b505afa158015610dbc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e79190612ef2565b6001546040516311bbb87160e21b8152600481018390526000916001600160a01b0316906346eee1c49060240160206040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d9190612ce3565b90505b919050565b6000546001600160a01b03163314610e8f5760405162461bcd60e51b815260040161084a90613151565b600d55565b6002546060906001600160a01b03163314610ec15760405162461bcd60e51b815260040161084a9061312f565b610eff6040518060400160405280601881526020017f616674657241677265656d656e745465726d696e617465640000000000000000815250611f6f565b6005546001600160a01b03808c169116141580610f245750610f2260028a611e77565b155b15610f685782828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929350610f7992505050565b610f76838389896000611ffa565b90505b9998505050505050505050565b60405162461bcd60e51b815260206004820152603360248201527f556e737570706f727465642063616c6c6261636b202d20204265666f7265204160448201527219dc99595b595b9d0815195c9b5a5b985d1959606a1b606482015260609060840161084a565b6000806000806000610fff878761141a565b915091508161101a5760008060009450945094505050611147565b6001546040516377fbb66360e01b815260048101899052602481018390526000916001600160a01b0316906377fbb6639060440160206040518083038186803b15801561106657600080fd5b505afa15801561107a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109e9190612ce3565b6001546040516393fa491560e01b8152600481018b9052602481018390529192506001600160a01b0316906393fa49159060440160206040518083038186803b1580156110ea57600080fd5b505afa1580156110fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111229190612ce3565b9450841561113857600195509250611147915050565b60008060009550955095505050505b9250925092565b600354600554604051631cd43d1160e31b81526001600160a01b0391821660048201528382166024820152306044820152600092919091169063e6a1e8889060640160806040518083038186803b1580156111a857600080fd5b505afa1580156111bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190612f40565b5090949350505050565b6000546001600160a01b031633146112145760405162461bcd60e51b815260040161084a90613151565b61121e600061267d565b565b6001546040516377fbb66360e01b815260048101849052602481018390526000916001600160a01b0316906377fbb663906044015b60206040518083038186803b15801561126d57600080fd5b505afa158015611281573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7d9190612ce3565b6000546001600160a01b031633146112cf5760405162461bcd60e51b815260040161084a90613151565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60405162461bcd60e51b815260206004820152602f60248201527f556e737570706f727465642063616c6c6261636b202d204265666f726520416760448201526e1c99595b595b9d081d5c19185d1959608a1b606482015260609060840161084a565b6001546040516393fa491560e01b815260048101849052602481018390526000916001600160a01b0316906393fa491590604401611255565b6000546001600160a01b031633146113b75760405162461bcd60e51b815260040161084a90613151565b6001600160801b0316600855565b6000546001600160a01b031633146113ef5760405162461bcd60e51b815260040161084a90613151565b600e80546fffffffffffffffffffffffffffffffff19166001600160801b0392909216919091179055565b6001546040516311bbb87160e21b815260048101849052600091829182916001600160a01b0316906346eee1c49060240160206040518083038186803b15801561146357600080fd5b505afa158015611477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149b9190612ce3565b9050801561184657600080806114b26001856133ce565b6001546040516377fbb66360e01b8152600481018b9052602481018590529192506000916001600160a01b03909116906377fbb6639060440160206040518083038186803b15801561150357600080fd5b505afa158015611517573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153b9190612ce3565b90508781106115555760008096509650505050505061184f565b6001546040516377fbb66360e01b8152600481018b9052602481018490526001600160a01b03909116906377fbb6639060440160206040518083038186803b1580156115a057600080fd5b505afa1580156115b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d89190612ce3565b9050878110156115f2575060019550935061184f92505050565b8260026115ff82856133ce565b6116099190613208565b6116149060016131ca565b61161e91906131ca565b6001546040516377fbb66360e01b8152600481018c9052602481018390529195506001600160a01b0316906377fbb6639060440160206040518083038186803b15801561166a57600080fd5b505afa15801561167e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a29190612ce3565b90508781101561177457600180546000916001600160a01b03909116906377fbb663908c906116d29089906131ca565b6040516001600160e01b031960e085901b1681526004810192909252602482015260440160206040518083038186803b15801561170e57600080fd5b505afa158015611722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117469190612ce3565b9050888110611761576001859750975050505050505061184f565b61176c8560016131ca565b935050611841565b600180546000916001600160a01b03909116906377fbb663908c9061179990896133ce565b6040516001600160e01b031960e085901b1681526004810192909252602482015260440160206040518083038186803b1580156117d557600080fd5b505afa1580156117e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180d9190612ce3565b90508881101561183257600161182381876133ce565b9750975050505050505061184f565b61183d6001866133ce565b9250505b6115f2565b60008092509250505b9250929050565b60608989611865600282611e77565b156118bd576005546001600160a01b038084169116146118b85760405162461bcd60e51b815260206004820152600e60248201526d085a5b9c1d5d1058d8d95c1d195960921b604482015260640161084a565b611934565b6118c8600282611f13565b15611934576006546001600160a01b03808416911614806118f657506007546001600160a01b038084169116145b6119345760405162461bcd60e51b815260206004820152600f60248201526e085bdd5d1c1d5d1058d8d95c1d1959608a1b604482015260640161084a565b6002546001600160a01b0316331461195e5760405162461bcd60e51b815260040161084a9061312f565b6119946040518060400160405280601581526020017418599d195c9059dc99595b595b9d10dc99585d1959605a1b815250611f6f565b6005546001600160a01b03808e1691161415806119b957506119b760028c611e77565b155b156109d95784848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506109ea92505050565b6040516319313f6d60e11b8152600260048201526001600160a01b0382166024820152737cd2532047b597003f6c91183af5327d91442718906332627eda90604401610738565b60408051600081526020810191829052637575b1c960e01b909152737cd2532047b597003f6c91183af5327d9144271890637575b1c990611a8b9060029060248101613186565b60006040518083038186803b158015611aa357600080fd5b505af4158015611ab7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611adf9190810190612cfb565b50565b6000546001600160a01b03163314611b0c5760405162461bcd60e51b815260040161084a90613151565b611b15816126cd565b600f80546001600160a01b0319166001600160a01b0392909216919091179055565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e9060440160206040518083038186803b158015611b8357600080fd5b505afa158015611b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbb9190612ce3565b611bc591906131ca565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052909150610a90908590612765565b825460028401546040805160008152602081019091526001600160a01b03928316926339255d5b921690636bc3c20560e11b90611c5e9086908890604481016130ff565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199586161790528151600081529081019182905260e086901b9093169052611cb292916024810161303d565b600060405180830381600087803b158015611ccc57600080fd5b505af1158015611ce0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a909190810190612cfb565b845460028601546001600160a01b03918216916339255d5b9116630465a56b60e31b848888611d3b633b9aca008a6131e2565b604080516000815260208101909152611d5b9493929190604481016130bd565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199586161790528151600081529081019182905260e086901b9093169052611daf92916024810161303d565b600060405180830381600087803b158015611dc957600080fd5b505af1158015611ddd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611e059190810190612cfb565b505050505050565b60078101546005820154611e3491839163ffffffff909116906001600160a01b0316611c1a565b60078101546005820154611adf91839163ffffffff9091169033906001906001600160a01b0316611d08565b6060611e6f848460008561283c565b949350505050565b60007fa9214cc96615e0085d3bb077758db69497dc2dce3b2b1e97bc93c3d18d83efd3826001600160a01b0316637730599e6040518163ffffffff1660e01b815260040160206040518083038186803b158015611ed357600080fd5b505afa158015611ee7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0b9190612ce3565b149392505050565b60007f8aedc3b5d4bf031e11a7e2940f7251c005698405d58e02e1c247fed3b1b3a674826001600160a01b0316637730599e6040518163ffffffff1660e01b815260040160206040518083038186803b158015611ed357600080fd5b611adf81604051602401611f83919061302a565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052612964565b6040516001600160a01b0382166024820152611adf9060440160408051601f198184030181529190526020810180516001600160e01b031663161765e160e11b179052612964565b606085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250600480546006546040516323fc23f360e01b81526001600160a01b0380831694820194909452306024820152600160a01b90910463ffffffff1660448201529697509195869550911692506323fc23f3915060640160806040518083038186803b15801561209b57600080fd5b505afa1580156120af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d39190612c88565b60055460408051631dce337960e31b81529051939750919550600094506001600160a01b0316925063ee719bc8916004808301926020929190829003018186803b15801561212057600080fd5b505afa158015612134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121589190612bce565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561219057600080fd5b505afa1580156121a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c89190612fc1565b6121d39060126133e5565b6121de90600a613262565b6005546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561222157600080fd5b505afa158015612235573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122599190612ce3565b6122639190613208565b905084801561228457506000612279838561319f565b6001600160801b0316115b80156122905750600081115b1561232657604051637575b1c960e01b8152737cd2532047b597003f6c91183af5327d9144271890637575b1c9906122cf906002908890600401613186565b60006040518083038186803b1580156122e757600080fd5b505af41580156122fb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123239190810190612cfb565b93505b600080612335888a018a612bea565b90925090506001600160a01b038116301461237d5760405162461bcd60e51b815260206004820152600860248201526721617070666c6f7760c01b604482015260640161084a565b60035460055460405163e8e7e2d160e01b81526001600160a01b039182166004820152306024820152600092919091169063e8e7e2d19060440160206040518083038186803b1580156123cf57600080fd5b505afa1580156123e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124079190612ef2565b600354600554604051631cd43d1160e31b81526001600160a01b039182166004820152868216602482015230604482015292935060009291169063e6a1e8889060640160806040518083038186803b15801561246257600080fd5b505afa158015612476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249a9190612f40565b5050915050806170806124ad9190613333565b6005546040516370a0823160e01b81526001600160a01b038781166004830152600b9390930b92909116906370a082319060240160206040518083038186803b1580156124f957600080fd5b505afa15801561250d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125319190612ce3565b121561256f5760405162461bcd60e51b815260206004820152600d60248201526c21656e6f756768546f6b656e7360981b604482015260640161084a565b600081600b0b12156125b45760405162461bcd60e51b815260206004820152600e60248201526d216e65676174697665526174657360901b604482015260640161084a565b6006546125e7906002908a9063ffffffff600160a01b82048116918991600b88900b916001600160a01b03169061298516565b60095460075491995061261c916002918b9163ffffffff918216918991600b88900b916001600160a01b039091169061298516565b604080516001600160a01b0387168152600b84810b602083015285900b8183015290519199507f757d2a43bda44890ff469605840d40a95d015029fcb64e04fb367a01b87ba983919081900360600190a15050505050505095945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146126f75760405162461bcd60e51b815260040161084a90613151565b6001600160a01b03811661275c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161084a565b611adf8161267d565b60006127ba826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611e609092919063ffffffff16565b80519091501561283757808060200190518101906127d89190612c22565b6128375760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161084a565b505050565b60608247101561289d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161084a565b843b6128eb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161084a565b600080866001600160a01b03168587604051612907919061300e565b60006040518083038185875af1925050503d8060008114612944576040519150601f19603f3d011682016040523d82523d6000602084013e612949565b606091505b5091509150612959828286612a91565b979650505050505050565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b8554600287015486916001600160a01b0390811691634329d2939116630465a56b60e31b8589896129ba633b9aca008b6131e2565b6040805160008152602081019091526129da9493929190604481016130bd565b60408051601f19818403018152918152602080830180516001600160e01b03166001600160e01b03199586161790528151600081529081019182905260e086901b9093169052612a2f92918660248201613073565b600060405180830381600087803b158015612a4957600080fd5b505af1158015612a5d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612a859190810190612d2e565b50979650505050505050565b60608315612aa0575081610b7d565b825115612ab05782518084602001fd5b8160405162461bcd60e51b815260040161084a919061302a565b80518015158114610e6057600080fd5b60008083601f840112612aeb578182fd5b50813567ffffffffffffffff811115612b02578182fd5b60208301915083602082850101111561184f57600080fd5b600082601f830112612b2a578081fd5b815167ffffffffffffffff80821115612b4557612b45613460565b604051601f8301601f19908116603f01168101908282118183101715612b6d57612b6d613460565b81604052838152866020858801011115612b85578485fd5b612b96846020830160208901613408565b9695505050505050565b8051600b81900b8114610e6057600080fd5b600060208284031215612bc3578081fd5b8135610b7d81613476565b600060208284031215612bdf578081fd5b8151610b7d81613476565b60008060408385031215612bfc578081fd5b8235612c0781613476565b91506020830135612c1781613476565b809150509250929050565b600060208284031215612c33578081fd5b610b7d82612aca565b60008060008060808587031215612c51578182fd5b612c5a85612aca565b9350612c6860208601612aca565b92506040850151612c788161348b565b6060959095015193969295505050565b60008060008060808587031215612c9d578384fd5b612ca685612aca565b93506020850151612cb68161348b565b6040860151909350612cc78161348b565b6060860151909250612cd88161348b565b939692955090935050565b600060208284031215612cf4578081fd5b5051919050565b600060208284031215612d0c578081fd5b815167ffffffffffffffff811115612d22578182fd5b611e6f84828501612b1a565b60008060408385031215612d40578182fd5b825167ffffffffffffffff80821115612d57578384fd5b612d6386838701612b1a565b93506020850151915080821115612d78578283fd5b50612d8585828601612b1a565b9150509250929050565b600080600080600080600060a0888a031215612da9578283fd5b8735612db481613476565b96506020880135612dc481613476565b955060408801359450606088013567ffffffffffffffff80821115612de7578485fd5b612df38b838c01612ada565b909650945060808a0135915080821115612e0b578384fd5b50612e188a828b01612ada565b989b979a50959850939692959293505050565b600080600080600080600080600060c08a8c031215612e48578283fd5b8935612e5381613476565b985060208a0135612e6381613476565b975060408a0135965060608a013567ffffffffffffffff80821115612e86578485fd5b612e928d838e01612ada565b909850965060808c0135915080821115612eaa578485fd5b612eb68d838e01612ada565b909650945060a08c0135915080821115612ece578384fd5b50612edb8c828d01612ada565b915080935050809150509295985092959850929598565b600060208284031215612f03578081fd5b610b7d82612ba0565b600060208284031215612f1d578081fd5b8135610b7d8161348b565b600060208284031215612f39578081fd5b5035919050565b60008060008060808587031215612f55578182fd5b84519350612f6560208601612ba0565b6040860151606090960151949790965092505050565b60008060408385031215612f8d578182fd5b50508035926020909101359150565b60008060408385031215612fae578182fd5b823563ffffffff81168114612c07578283fd5b600060208284031215612fd2578081fd5b815160ff81168114610b7d578182fd5b60008151808452612ffa816020860160208601613408565b601f01601f19169290920160200192915050565b60008251613020818460208701613408565b9190910192915050565b600060208252610b7d6020830184612fe2565b6001600160a01b038416815260606020820181905260009061306190830185612fe2565b8281036040840152612b968185612fe2565b6001600160a01b038516815260806020820181905260009061309790830186612fe2565b82810360408401526130a98186612fe2565b905082810360608401526129598185612fe2565b6001600160a01b03868116825260208201869052841660408201526001600160801b038316606082015260a06080820181905260009061295990830184612fe2565b600060018060a01b0385168252836020830152606060408301526131266060830184612fe2565b95945050505050565b6020808252600890820152671bdb99481a1bdcdd60c21b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600083825260406020830152611e6f6040830184612fe2565b60006001600160801b038083168185168083038211156131c1576131c1613434565b01949350505050565b600082198211156131dd576131dd613434565b500190565b60006001600160801b03808416806131fc576131fc61344a565b92169190910492915050565b6000826132175761321761344a565b500490565b80825b600180861161322e5750613259565b81870482111561324057613240613434565b8086161561324d57918102915b9490941c93800261321f565b94509492505050565b6000610b7d60001960ff85168460008261327e57506001610b7d565b8161328b57506000610b7d565b81600181146132a157600281146132ab576132d8565b6001915050610b7d565b60ff8411156132bc576132bc613434565b6001841b9150848211156132d2576132d2613434565b50610b7d565b5060208310610133831016604e8410600b841016171561330b575081810a8381111561330657613306613434565b610b7d565b613318848484600161321c565b80860482111561332a5761332a613434565b02949350505050565b600081600b0b83600b0b6b7fffffffffffffffffffffff8382138484138383048511828216161561336657613366613434565b6b7fffffffffffffffffffffff198685128281168783058712161561338d5761338d613434565b8787129250858205871284841616156133a8576133a8613434565b858505871281841616156133be576133be613434565b5050509290910295945050505050565b6000828210156133e0576133e0613434565b500390565b600060ff821660ff8416808210156133ff576133ff613434565b90039392505050565b60005b8381101561342357818101518382015260200161340b565b83811115610a905750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611adf57600080fd5b6001600160801b0381168114611adf57600080fdfea264697066735822122030d21cc243fd71f35e266c8d81acdf79209969b30da578ae2d165c2c40072fe964736f6c634300080300330000000000000000000000003e14dc1b13c488a8d5d310918780c983bd5982e70000000000000000000000006eee6060f715257b970700bc2656de21dedf074c000000000000000000000000b0aabba4b2783a72c52956cdef62d438eca2d7a1000000000000000000000000caa7349cea390f89641fe306d93591f87595dc1f000000000000000000000000b63e38d21b31719e6df314d3d2c351df0d4a9162000000000000000000000000263026e7e53dbfdce5ae55ade22493f8289229650000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b47997506000000000000000000000000acc2d27400029904919ea54ffc0b18bf07c57875000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000147269636f636865746674772d3039313232312d31000000000000000000000000
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003e14dc1b13c488a8d5d310918780c983bd5982e70000000000000000000000006eee6060f715257b970700bc2656de21dedf074c000000000000000000000000b0aabba4b2783a72c52956cdef62d438eca2d7a1000000000000000000000000caa7349cea390f89641fe306d93591f87595dc1f000000000000000000000000b63e38d21b31719e6df314d3d2c351df0d4a9162000000000000000000000000263026e7e53dbfdce5ae55ade22493f8289229650000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b47997506000000000000000000000000acc2d27400029904919ea54ffc0b18bf07c57875000000000000000000000000000000000000000000000000000000000000004f000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000147269636f636865746674772d3039313232312d31000000000000000000000000
-----Decoded View---------------
Arg [0] : host (address): 0x3e14dc1b13c488a8d5d310918780c983bd5982e7
Arg [1] : cfa (address): 0x6eee6060f715257b970700bc2656de21dedf074c
Arg [2] : ida (address): 0xb0aabba4b2783a72c52956cdef62d438eca2d7a1
Arg [3] : inputToken (address): 0xcaa7349cea390f89641fe306d93591f87595dc1f
Arg [4] : outputToken (address): 0xb63e38d21b31719e6df314d3d2c351df0d4a9162
Arg [5] : subsidyToken (address): 0x263026e7e53dbfdce5ae55ade22493f828922965
Arg [6] : sushiRouter (address): 0x1b02da8cb0d097eb8d57a175b88c7d8b47997506
Arg [7] : oracle (address): 0xacc2d27400029904919ea54ffc0b18bf07c57875
Arg [8] : requestId (uint256): 79
Arg [9] : registrationKey (string): ricochetftw-091221-1
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000003e14dc1b13c488a8d5d310918780c983bd5982e7
Arg [1] : 0000000000000000000000006eee6060f715257b970700bc2656de21dedf074c
Arg [2] : 000000000000000000000000b0aabba4b2783a72c52956cdef62d438eca2d7a1
Arg [3] : 000000000000000000000000caa7349cea390f89641fe306d93591f87595dc1f
Arg [4] : 000000000000000000000000b63e38d21b31719e6df314d3d2c351df0d4a9162
Arg [5] : 000000000000000000000000263026e7e53dbfdce5ae55ade22493f828922965
Arg [6] : 0000000000000000000000001b02da8cb0d097eb8d57a175b88c7d8b47997506
Arg [7] : 000000000000000000000000acc2d27400029904919ea54ffc0b18bf07c57875
Arg [8] : 000000000000000000000000000000000000000000000000000000000000004f
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [11] : 7269636f636865746674772d3039313232312d31000000000000000000000000
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.