Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ArbBridgedSuperTokenProxy
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
No with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;
import { IArbToken } from "./interfaces/IArbToken.sol";
import { BridgedSuperTokenProxy, IBridgedSuperToken, IXERC20 } from "./BridgedSuperToken.sol";
/**
* @title Extends BridgedSuperTokenProxy with the interface required by the Arbitrum Bridge
*/
contract ArbBridgedSuperTokenProxy is BridgedSuperTokenProxy, IArbToken {
address internal immutable _NATIVE_BRIDGE;
address internal immutable _REMOTE_TOKEN;
// initializes the immutables and sets max limit for the native bridge
constructor(address nativeBridge_, address remoteToken_) {
_NATIVE_BRIDGE = nativeBridge_;
_REMOTE_TOKEN = remoteToken_;
// the native bridge gets (de facto) unlimited mint/burn allowance
setLimits(nativeBridge_, _MAX_LIMIT, _MAX_LIMIT);
}
// ===== IArbToken =====
/// @inheritdoc IArbToken
function bridgeMint(address account, uint256 amount) external {
return super.mint(account, amount);
}
/// @inheritdoc IArbToken
function bridgeBurn(address account, uint256 amount) external {
return super.burn(account, amount);
}
/// @inheritdoc IArbToken
function l1Address() external view returns (address) {
return _REMOTE_TOKEN;
}
}
interface IArbBridgedSuperToken is IBridgedSuperToken, IArbToken { }// SPDX-License-Identifier: Apache-2.0
/*
* Copyright 2020, Offchain Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @title Minimum expected interface for L2 token that interacts with the L2 token bridge (this is the interface necessary
* for a custom token that interacts with the bridge, see TestArbCustomToken.sol for an example implementation).
* @dev For the token to be compatible out of the box with the tooling available (e.g., the Arbitrum bridge), it is
* recommended to keep the implementation of this interface as close as possible to the `TestArbCustomToken` example.
*/
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
interface IArbToken {
/**
* @notice should increase token supply by amount, and should (probably) only be callable by the L1 bridge.
*/
function bridgeMint(address account, uint256 amount) external;
/**
* @notice should decrease token supply by amount, and should (probably) only be callable by the L1 bridge.
*/
function bridgeBurn(address account, uint256 amount) external;
/**
* @return address of layer 1 token
*/
function l1Address() external view returns (address);
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;
import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol';
// This abstract contract provides storage padding for the proxy
import { CustomSuperTokenBase } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/CustomSuperTokenBase.sol";
// Implementation of UUPSProxy (see https://eips.ethereum.org/EIPS/eip-1822)
import { UUPSProxy } from "@superfluid-finance/ethereum-contracts/contracts/upgradability/UUPSProxy.sol";
// Superfluid framework interfaces we need
import { ISuperToken, ISuperTokenFactory, IERC20 } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol";
import { IXERC20 } from "./interfaces/IXERC20.sol";
/**
* @title The Proxy contract for a Pure SuperToken with preminted initial supply and with xERC20 support.
*/
contract BridgedSuperTokenProxy is CustomSuperTokenBase, UUPSProxy, Ownable, IXERC20 {
/// The duration it takes for the limits to fully replenish
uint256 internal constant _DURATION = 1 days;
uint256 internal constant _MAX_LIMIT = type(uint256).max / 2;
/// Maps bridge address to xERC20 bridge configurations
mapping(address => Bridge) public bridges;
error IXERC20_NoLockBox();
error IXERC20_LimitsTooHigh();
// This shall be invoked exactly once after deployment, needed for the token contract to become operational.
function initialize(
ISuperTokenFactory factory,
string memory name,
string memory symbol,
address receiver,
uint256 initialSupply
) external {
// This call to the factory invokes `UUPSProxy.initialize`, which connects the proxy to the canonical SuperToken implementation.
// It also emits an event which facilitates discovery of this token.
ISuperTokenFactory(factory).initializeCustomSuperToken(address(this));
// This initializes the token storage and sets the `initialized` flag of OpenZeppelin Initializable.
// This makes sure that it will revert if invoked more than once.
ISuperToken(address(this)).initialize(IERC20(address(0)), 18, name, symbol);
// This mints the specified initial supply to the specified receiver.
ISuperToken(address(this)).selfMint(receiver, initialSupply, "");
}
// ===== IXERC20 =====
/// @inheritdoc IXERC20
function setLockbox(address /*lockbox*/) external pure {
// no lockbox support needed
revert IXERC20_NoLockBox();
}
/// @inheritdoc IXERC20
function setLimits(address bridge, uint256 mintingLimit, uint256 burningLimit) public onlyOwner {
if (mintingLimit > _MAX_LIMIT || burningLimit > _MAX_LIMIT) {
revert IXERC20_LimitsTooHigh();
}
_changeMinterLimit(bridge, mintingLimit);
_changeBurnerLimit(bridge, burningLimit);
emit BridgeLimitsSet(mintingLimit, burningLimit, bridge);
}
/// @inheritdoc IXERC20
function mint(address user, uint256 amount) public virtual {
address bridge = msg.sender;
uint256 currentLimit = mintingCurrentLimitOf(bridge);
if (currentLimit < amount) revert IXERC20_NotHighEnoughLimits();
bridges[bridge].minterParams.timestamp = block.timestamp;
bridges[bridge].minterParams.currentLimit = currentLimit - amount;
ISuperToken(address(this)).selfMint(user, amount, "");
}
/// @inheritdoc IXERC20
function burn(address user, uint256 amount) public virtual {
address bridge = msg.sender;
uint256 currentLimit = burningCurrentLimitOf(bridge);
if (currentLimit < amount) revert IXERC20_NotHighEnoughLimits();
bridges[bridge].burnerParams.timestamp = block.timestamp;
bridges[bridge].burnerParams.currentLimit = currentLimit - amount;
// in order to enforce user allowance limitations, we first transfer to the bridge
// (fails if not enough allowance) and then let the bridge burn it.
ISuperToken(address(this)).selfTransferFrom(user, bridge, bridge, amount);
ISuperToken(address(this)).selfBurn(bridge, amount, "");
}
/// @inheritdoc IXERC20
function mintingMaxLimitOf(address bridge) external view returns (uint256 limit) {
limit = bridges[bridge].minterParams.maxLimit;
}
/// @inheritdoc IXERC20
function burningMaxLimitOf(address bridge) external view returns (uint256 limit) {
limit = bridges[bridge].burnerParams.maxLimit;
}
/// @inheritdoc IXERC20
function mintingCurrentLimitOf(address bridge) public view returns (uint256 limit) {
limit = _getCurrentLimit(
bridges[bridge].minterParams.currentLimit,
bridges[bridge].minterParams.maxLimit,
bridges[bridge].minterParams.timestamp,
bridges[bridge].minterParams.ratePerSecond
);
}
/// @inheritdoc IXERC20
function burningCurrentLimitOf(address bridge) public view returns (uint256 limit) {
limit = _getCurrentLimit(
bridges[bridge].burnerParams.currentLimit,
bridges[bridge].burnerParams.maxLimit,
bridges[bridge].burnerParams.timestamp,
bridges[bridge].burnerParams.ratePerSecond
);
}
// ===== INTERNAL FUNCTIONS =====
function _changeMinterLimit(address bridge, uint256 limit) internal {
uint256 oldLimit = bridges[bridge].minterParams.maxLimit;
uint256 currentLimit = mintingCurrentLimitOf(bridge);
bridges[bridge].minterParams.maxLimit = limit;
bridges[bridge].minterParams.currentLimit = _calculateNewCurrentLimit(limit, oldLimit, currentLimit);
bridges[bridge].minterParams.ratePerSecond = limit / _DURATION;
bridges[bridge].minterParams.timestamp = block.timestamp;
}
function _changeBurnerLimit(address bridge, uint256 limit) internal {
uint256 _oldLimit = bridges[bridge].burnerParams.maxLimit;
uint256 _currentLimit = burningCurrentLimitOf(bridge);
bridges[bridge].burnerParams.maxLimit = limit;
bridges[bridge].burnerParams.currentLimit = _calculateNewCurrentLimit(limit, _oldLimit, _currentLimit);
bridges[bridge].burnerParams.ratePerSecond = limit / _DURATION;
bridges[bridge].burnerParams.timestamp = block.timestamp;
}
function _calculateNewCurrentLimit(uint256 limit, uint256 oldLimit, uint256 currentLimit)
internal pure
returns (uint256 newCurrentLimit)
{
uint256 difference;
if (limit <= oldLimit) {
difference = oldLimit - limit;
newCurrentLimit = currentLimit > difference ? currentLimit - difference : 0;
} else {
difference = limit - oldLimit;
newCurrentLimit = currentLimit + difference;
}
}
function _getCurrentLimit(uint256 currentLimit, uint256 maxLimit, uint256 timestamp, uint256 ratePerSecond)
internal view
returns (uint256 limit)
{
limit = currentLimit;
if (limit == maxLimit) {
return limit;
} else if (timestamp + _DURATION <= block.timestamp) {
// the limit is fully replenished
limit = maxLimit;
} else if (timestamp + _DURATION > block.timestamp) {
// the limit is partially replenished
uint256 timePassed = block.timestamp - timestamp;
uint256 calculatedLimit = limit + (timePassed * ratePerSecond);
limit = calculatedLimit > maxLimit ? maxLimit : calculatedLimit;
}
}
}
// The token interface is just an alias of ISuperToken
// since we need no custom logic (other than for initialization) in the proxy.
interface IBridgedSuperToken is ISuperToken, IXERC20 {}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
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() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(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");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
// We export this too because it seems reasonable for a custom super token.
// solhint-disable-next-line no-unused-import
import { ISuperToken } from "../../interfaces/superfluid/ISuperToken.sol";
/**
* @title Custom super token base contract
* @author Superfluid
* NOTE:
* - Because of how solidity lays out its storage variables and how custom
* super tokens inherit the SuperToken standard implementation, it is
* required that the custom token proxy pads its implementation
* with reserved storage used by the Super Token implementation.
* - You will need to append your own proxy implementation after the base
* - Refer to SETH.sol for an example how it is used.
*/
abstract contract CustomSuperTokenBase {
// This (32) is the hard-coded number of storage slots used by the super token
uint256[32] internal _storagePaddings;
}// SPDX-License-Identifier: AGPLv3
pragma solidity ^0.8.23;
import { UUPSUtils } from "./UUPSUtils.sol";
import { Proxy } from "@openzeppelin/contracts/proxy/Proxy.sol";
/**
* @title UUPS (Universal Upgradeable Proxy Standard) Proxy
*
* NOTE:
* - Compliant with [Universal Upgradeable Proxy Standard](https://eips.ethereum.org/EIPS/eip-1822)
* - Compiiant with [Standard Proxy Storage Slots](https://eips.ethereum.org/EIPS/eip-1967)
* - Implements delegation of calls to other contracts, with proper forwarding of
* return values and bubbling of failures.
* - It defines a fallback function that delegates all calls to the implementation.
*/
contract UUPSProxy is Proxy {
/**
* @dev Proxy initialization function.
* This should only be called once and it is permission-less.
* @param initialAddress Initial logic contract code address to be used.
*/
function initializeProxy(address initialAddress) external {
require(initialAddress != address(0), "UUPSProxy: zero address");
require(UUPSUtils.implementation() == address(0), "UUPSProxy: already initialized");
UUPSUtils.setImplementation(initialAddress);
}
/// @dev Proxy._implementation implementation
function _implementation() internal virtual override view returns (address)
{
return UUPSUtils.implementation();
}
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
// ISuperfluid.sol can also be used as an umbrella-import for everything Superfluid, hence we should have these unused
// import.
//
// solhint-disable no-unused-import
/// Global definitions
import {
SuperAppDefinitions,
ContextDefinitions,
FlowOperatorDefinitions,
BatchOperation,
SuperfluidGovernanceConfigs
} from "./Definitions.sol";
/// Super token related interfaces:
/// Note: CustomSuperTokenBase is not included for people building CustomSuperToken.
import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol";
import { ISuperfluidToken } from "./ISuperfluidToken.sol";
import { ISuperToken } from "./ISuperToken.sol";
import { ISuperTokenFactory } from "./ISuperTokenFactory.sol";
import { ISETH } from "../tokens/ISETH.sol";
/// Superfluid/ERC20x NFTs
import { IPoolAdminNFT } from "../agreements/gdav1/IPoolAdminNFT.sol";
import { IPoolMemberNFT } from "../agreements/gdav1/IPoolMemberNFT.sol";
/// Superfluid agreement interfaces:
import { ISuperAgreement } from "./ISuperAgreement.sol";
import { IConstantFlowAgreementV1 } from "../agreements/IConstantFlowAgreementV1.sol";
import { IInstantDistributionAgreementV1 } from "../agreements/IInstantDistributionAgreementV1.sol";
import {
IGeneralDistributionAgreementV1,
PoolConfig,
PoolERC20Metadata
} from "../agreements/gdav1/IGeneralDistributionAgreementV1.sol";
import { ISuperfluidPool } from "../agreements/gdav1/ISuperfluidPool.sol";
/// Superfluid App interfaces:
import { ISuperApp } from "./ISuperApp.sol";
/// Superfluid governance
import { ISuperfluidGovernance } from "./ISuperfluidGovernance.sol";
/**
* @title Host interface
* @author Superfluid
* @notice This is the central contract of the system where super agreement, super app
* and super token features are connected.
*
* The Superfluid host contract is also the entry point for the protocol users,
* where batch call and meta transaction are provided for UX improvements.
*
*/
interface ISuperfluid {
/**************************************************************************
* Errors
*************************************************************************/
// Superfluid Custom Errors
error HOST_AGREEMENT_CALLBACK_IS_NOT_ACTION(); // 0xef4295f6
error HOST_CANNOT_DOWNGRADE_TO_NON_UPGRADEABLE(); // 0x474e7641
error HOST_CALL_AGREEMENT_WITH_CTX_FROM_WRONG_ADDRESS(); // 0x0cd0ebc2
error HOST_CALL_APP_ACTION_WITH_CTX_FROM_WRONG_ADDRESS(); // 0x473f7bd4
error HOST_INVALID_CONFIG_WORD(); // 0xf4c802a4
error HOST_MAX_256_AGREEMENTS(); // 0x7c281a78
error HOST_NON_UPGRADEABLE(); // 0x14f72c9f
error HOST_NON_ZERO_LENGTH_PLACEHOLDER_CTX(); // 0x67e9985b
error HOST_ONLY_GOVERNANCE(); // 0xc5d22a4e
error HOST_UNKNOWN_BATCH_CALL_OPERATION_TYPE(); // 0xb4770115
error HOST_AGREEMENT_ALREADY_REGISTERED(); // 0xdc9ddba8
error HOST_AGREEMENT_IS_NOT_REGISTERED(); // 0x1c9e9bea
error HOST_MUST_BE_CONTRACT(); // 0xd4f6b30c
error HOST_ONLY_LISTED_AGREEMENT(); // 0x619c5359
error HOST_NEED_MORE_GAS(); // 0xd4f5d496
// App Related Custom Errors
// uses SuperAppDefinitions' App Jail Reasons as _code
error APP_RULE(uint256 _code); // 0xa85ba64f
error HOST_NOT_A_SUPER_APP(); // 0x163cbe43
error HOST_NO_APP_REGISTRATION_PERMISSION(); // 0xb56455f0
error HOST_RECEIVER_IS_NOT_SUPER_APP(); // 0x96aa315e
error HOST_SENDER_IS_NOT_SUPER_APP(); // 0xbacfdc40
error HOST_SOURCE_APP_NEEDS_HIGHER_APP_LEVEL(); // 0x44725270
error HOST_SUPER_APP_IS_JAILED(); // 0x02384b64
error HOST_SUPER_APP_ALREADY_REGISTERED(); // 0x01b0a935
/**************************************************************************
* Time
*
* > The Oracle: You have the sight now, Neo. You are looking at the world without time.
* > Neo: Then why can't I see what happens to her?
* > The Oracle: We can never see past the choices we don't understand.
* > - The Oracle and Neo conversing about the future of Trinity and the effects of Neo's choices
*************************************************************************/
function getNow() external view returns (uint256);
/**************************************************************************
* Governance
*************************************************************************/
/**
* @dev Get the current governance address of the Superfluid host
*/
function getGovernance() external view returns(ISuperfluidGovernance governance);
/**
* @dev Replace the current governance with a new one
*/
function replaceGovernance(ISuperfluidGovernance newGov) external;
/**
* @dev Governance replaced event
* @param oldGov Address of the old governance contract
* @param newGov Address of the new governance contract
*/
event GovernanceReplaced(ISuperfluidGovernance oldGov, ISuperfluidGovernance newGov);
/**************************************************************************
* Agreement Whitelisting
*************************************************************************/
/**
* @dev Register a new agreement class to the system
* @param agreementClassLogic Initial agreement class code
*
* @custom:modifiers
* - onlyGovernance
*/
function registerAgreementClass(ISuperAgreement agreementClassLogic) external;
/**
* @notice Agreement class registered event
* @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>"
* @param agreementType The agreement type registered
* @param code Address of the new agreement
*/
event AgreementClassRegistered(bytes32 agreementType, address code);
/**
* @dev Update code of an agreement class
* @param agreementClassLogic New code for the agreement class
*
* @custom:modifiers
* - onlyGovernance
*/
function updateAgreementClass(ISuperAgreement agreementClassLogic) external;
/**
* @notice Agreement class updated event
* @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>"
* @param agreementType The agreement type updated
* @param code Address of the new agreement
*/
event AgreementClassUpdated(bytes32 agreementType, address code);
/**
* @notice Check if the agreement type is whitelisted
* @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>"
*/
function isAgreementTypeListed(bytes32 agreementType) external view returns(bool yes);
/**
* @dev Check if the agreement class is whitelisted
*/
function isAgreementClassListed(ISuperAgreement agreementClass) external view returns(bool yes);
/**
* @notice Get agreement class
* @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>"
*/
function getAgreementClass(bytes32 agreementType) external view returns(ISuperAgreement agreementClass);
/**
* @dev Map list of the agreement classes using a bitmap
* @param bitmap Agreement class bitmap
*/
function mapAgreementClasses(uint256 bitmap)
external view
returns (ISuperAgreement[] memory agreementClasses);
/**
* @notice Create a new bitmask by adding a agreement class to it
* @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>"
* @param bitmap Agreement class bitmap
*/
function addToAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType)
external view
returns (uint256 newBitmap);
/**
* @notice Create a new bitmask by removing a agreement class from it
* @dev agreementType is the keccak256 hash of: "org.superfluid-finance.agreements.<AGREEMENT_NAME>.<VERSION>"
* @param bitmap Agreement class bitmap
*/
function removeFromAgreementClassesBitmap(uint256 bitmap, bytes32 agreementType)
external view
returns (uint256 newBitmap);
/**************************************************************************
* Super Token Factory
**************************************************************************/
/**
* @dev Get the super token factory
* @return factory The factory
*/
function getSuperTokenFactory() external view returns (ISuperTokenFactory factory);
/**
* @dev Get the super token factory logic (applicable to upgradable deployment)
* @return logic The factory logic
*/
function getSuperTokenFactoryLogic() external view returns (address logic);
/**
* @dev Update super token factory
* @param newFactory New factory logic
*/
function updateSuperTokenFactory(ISuperTokenFactory newFactory) external;
/**
* @dev SuperToken factory updated event
* @param newFactory Address of the new factory
*/
event SuperTokenFactoryUpdated(ISuperTokenFactory newFactory);
/**
* @notice Update the super token logic to the latest (canonical) implementation
* if `newLogicOverride` is zero, or to `newLogicOverride` otherwise.
* or to the provided implementation `.
* @dev Refer to ISuperTokenFactory.Upgradability for expected behaviours
*/
function updateSuperTokenLogic(ISuperToken token, address newLogicOverride) external;
/**
* @notice Update the super token logic to the provided one
* @dev newLogic must implement UUPSProxiable with matching proxiableUUID
*/
event SuperTokenLogicUpdated(ISuperToken indexed token, address code);
/**
* @notice Change the SuperToken admin address
* @dev The admin is the only account allowed to update the token logic
* For backward compatibility, the "host" is the default "admin" if unset (address(0)).
*/
function changeSuperTokenAdmin(ISuperToken token, address newAdmin) external;
/**
* @notice Change the implementation address the pool beacon points to
* @dev Updating the logic the beacon points to will update the logic of all the Pool BeaconProxy instances
*/
function updatePoolBeaconLogic(address newBeaconLogic) external;
/**
* @dev Pool Beacon logic updated event
* @param beaconProxy addrss of the beacon proxy
* @param newBeaconLogic address of the new beacon logic
*/
event PoolBeaconLogicUpdated(address indexed beaconProxy, address newBeaconLogic);
/**************************************************************************
* App Registry
*************************************************************************/
/**
* @dev Message sender (must be a contract) registers itself as a super app.
* @param configWord The super app manifest configuration, flags are defined in
* `SuperAppDefinitions`
* @notice On some mainnet deployments, pre-authorization by governance may be needed for this to succeed.
* See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide
*/
function registerApp(uint256 configWord) external;
/**
* @dev Registers an app (must be a contract) as a super app.
* @param app The super app address
* @param configWord The super app manifest configuration, flags are defined in
* `SuperAppDefinitions`
* @notice On some mainnet deployments, pre-authorization by governance may be needed for this to succeed.
* See https://github.com/superfluid-finance/protocol-monorepo/wiki/Super-App-White-listing-Guide
*/
function registerApp(ISuperApp app, uint256 configWord) external;
/**
* @dev App registered event
* @param app Address of jailed app
*/
event AppRegistered(ISuperApp indexed app);
/**
* @dev DO NOT USE for new deployments
* @custom:deprecated you should use `registerApp(uint256 configWord) instead.
*/
function registerAppWithKey(uint256 configWord, string calldata registrationKey) external;
/**
* @dev DO NOT USE for new deployments
* @custom:deprecated you should use `registerApp(ISuperApp app, uint256 configWord) instead.
*/
function registerAppByFactory(ISuperApp app, uint256 configWord) external;
/**
* @dev Query if the app is registered
* @param app Super app address
*/
function isApp(ISuperApp app) external view returns(bool);
/**
* @dev Query app callbacklevel
* @param app Super app address
*/
function getAppCallbackLevel(ISuperApp app) external view returns(uint8 appCallbackLevel);
/**
* @dev Get the manifest of the super app
* @param app Super app address
*/
function getAppManifest(
ISuperApp app
)
external view
returns (
bool isSuperApp,
bool isJailed,
uint256 noopMask
);
/**
* @dev Query if the app has been jailed
* @param app Super app address
*/
function isAppJailed(ISuperApp app) external view returns (bool isJail);
/**
* @dev Whitelist the target app for app composition for the source app (msg.sender)
* @param targetApp The target super app address
*/
function allowCompositeApp(ISuperApp targetApp) external;
/**
* @dev Query if source app is allowed to call the target app as downstream app
* @param app Super app address
* @param targetApp The target super app address
*/
function isCompositeAppAllowed(
ISuperApp app,
ISuperApp targetApp
)
external view
returns (bool isAppAllowed);
/**************************************************************************
* Agreement Framework
*
* Agreements use these function to trigger super app callbacks, updates
* app credit and charge gas fees.
*
* These functions can only be called by registered agreements.
*************************************************************************/
/**
* @dev (For agreements) StaticCall the app before callback
* @param app The super app.
* @param callData The call data sending to the super app.
* @param isTermination Is it a termination callback?
* @param ctx Current ctx, it will be validated.
* @return cbdata Data returned from the callback.
*/
function callAppBeforeCallback(
ISuperApp app,
bytes calldata callData,
bool isTermination,
bytes calldata ctx
)
external
// onlyAgreement
// assertValidCtx(ctx)
returns(bytes memory cbdata);
/**
* @dev (For agreements) Call the app after callback
* @param app The super app.
* @param callData The call data sending to the super app.
* @param isTermination Is it a termination callback?
* @param ctx Current ctx, it will be validated.
* @return newCtx The current context of the transaction.
*/
function callAppAfterCallback(
ISuperApp app,
bytes calldata callData,
bool isTermination,
bytes calldata ctx
)
external
// onlyAgreement
// assertValidCtx(ctx)
returns(bytes memory newCtx);
/**
* @dev (For agreements) Create a new callback stack
* @param ctx The current ctx, it will be validated.
* @param app The super app.
* @param appCreditGranted App credit granted so far.
* @param appCreditUsed App credit used so far.
* @return newCtx The current context of the transaction.
*/
function appCallbackPush(
bytes calldata ctx,
ISuperApp app,
uint256 appCreditGranted,
int256 appCreditUsed,
ISuperfluidToken appCreditToken
)
external
// onlyAgreement
// assertValidCtx(ctx)
returns (bytes memory newCtx);
/**
* @dev (For agreements) Pop from the current app callback stack
* @param ctx The ctx that was pushed before the callback stack.
* @param appCreditUsedDelta App credit used by the app.
* @return newCtx The current context of the transaction.
*
* @custom:security
* - Here we cannot do assertValidCtx(ctx), since we do not really save the stack in memory.
* - Hence there is still implicit trust that the agreement handles the callback push/pop pair correctly.
*/
function appCallbackPop(
bytes calldata ctx,
int256 appCreditUsedDelta
)
external
// onlyAgreement
returns (bytes memory newCtx);
/**
* @dev (For agreements) Use app credit.
* @param ctx The current ctx, it will be validated.
* @param appCreditUsedMore See app credit for more details.
* @return newCtx The current context of the transaction.
*/
function ctxUseCredit(
bytes calldata ctx,
int256 appCreditUsedMore
)
external
// onlyAgreement
// assertValidCtx(ctx)
returns (bytes memory newCtx);
/**
* @dev (For agreements) Jail the app.
* @param app The super app.
* @param reason Jail reason code.
* @return newCtx The current context of the transaction.
*/
function jailApp(
bytes calldata ctx,
ISuperApp app,
uint256 reason
)
external
// onlyAgreement
// assertValidCtx(ctx)
returns (bytes memory newCtx);
/**
* @dev Jail event for the app
* @param app Address of jailed app
* @param reason Reason the app is jailed (see Definitions.sol for the full list)
*/
event Jail(ISuperApp indexed app, uint256 reason);
/**************************************************************************
* Contextless Call Proxies
*
* NOTE: For EOAs or non-app contracts, they are the entry points for interacting
* with agreements or apps.
*
* NOTE: The contextual call data should be generated using
* abi.encodeWithSelector. The context parameter should be set to "0x",
* an empty bytes array as a placeholder to be replaced by the host
* contract.
*************************************************************************/
/**
* @dev Call agreement function
* @param agreementClass The agreement address you are calling
* @param callData The contextual call data with placeholder ctx
* @param userData Extra user data being sent to the super app callbacks
*/
function callAgreement(
ISuperAgreement agreementClass,
bytes calldata callData,
bytes calldata userData
)
external
//cleanCtx
//isAgreement(agreementClass)
returns(bytes memory returnedData);
/**
* @notice Call app action
* @dev Main use case is calling app action in a batch call via the host
* @param callData The contextual call data
*
* @custom:note See "Contextless Call Proxies" above for more about contextual call data.
*/
function callAppAction(
ISuperApp app,
bytes calldata callData
)
external
//cleanCtx
//isAppActive(app)
//isValidAppAction(callData)
returns(bytes memory returnedData);
/**************************************************************************
* Contextual Call Proxies and Context Utilities
*
* For apps, they must use context they receive to interact with
* agreements or apps.
*
* The context changes must be saved and returned by the apps in their
* callbacks always, any modification to the context will be detected and
* the violating app will be jailed.
*************************************************************************/
/**
* @dev Context Struct
*
* @custom:note on backward compatibility:
* - Non-dynamic fields are padded to 32bytes and packed
* - Dynamic fields are referenced through a 32bytes offset to their "parents" field (or root)
* - The order of the fields hence should not be rearranged in order to be backward compatible:
* - non-dynamic fields will be parsed at the same memory location,
* - and dynamic fields will simply have a greater offset than it was.
* - We cannot change the structure of the Context struct because of ABI compatibility requirements
*/
struct Context {
//
// Call context
//
// app callback level
uint8 appCallbackLevel;
// type of call
uint8 callType;
// the system timestamp
uint256 timestamp;
// The intended message sender for the call
address msgSender;
//
// Callback context
//
// For callbacks it is used to know which agreement function selector is called
bytes4 agreementSelector;
// User provided data for app callbacks
bytes userData;
//
// App context
//
// app credit granted
uint256 appCreditGranted;
// app credit wanted by the app callback
uint256 appCreditWantedDeprecated;
// app credit used, allowing negative values over a callback session
// the appCreditUsed value over a callback sessions is calculated with:
// existing flow data owed deposit + sum of the callback agreements
// deposit deltas
// the final value used to modify the state is determined by the
// _adjustNewAppCreditUsed function (in AgreementLibrary.sol) which takes
// the appCreditUsed value reached in the callback session and the app
// credit granted
int256 appCreditUsed;
// app address
address appAddress;
// app credit in super token
ISuperfluidToken appCreditToken;
}
function callAgreementWithContext(
ISuperAgreement agreementClass,
bytes calldata callData,
bytes calldata userData,
bytes calldata ctx
)
external
// requireValidCtx(ctx)
// onlyAgreement(agreementClass)
returns (bytes memory newCtx, bytes memory returnedData);
function callAppActionWithContext(
ISuperApp app,
bytes calldata callData,
bytes calldata ctx
)
external
// requireValidCtx(ctx)
// isAppActive(app)
returns (bytes memory newCtx);
function decodeCtx(bytes memory ctx)
external pure
returns (Context memory context);
function isCtxValid(bytes calldata ctx) external view returns (bool);
/**************************************************************************
* Batch call
**************************************************************************/
/**
* @dev Batch operation data
*/
struct Operation {
// Operation type. Defined in BatchOperation (Definitions.sol)
uint32 operationType;
// Operation target
address target;
// Data specific to the operation
bytes data;
}
/**
* @dev Batch call function
* @param operations Array of batch operations
*
* NOTE: `batchCall` is `payable, because there's limited support for sending
* native tokens to batch operation targets.
* If value is > 0, the whole amount is sent to the first operation matching any of:
* - OPERATION_TYPE_SUPERFLUID_CALL_APP_ACTION
* - OPERATION_TYPE_SIMPLE_FORWARD_CALL
* - OPERATION_TYPE_ERC2771_FORWARD_CALL
* If the first such operation does not allow receiving native tokens,
* the transaction will revert.
* It's currently not possible to send native tokens to multiple operations, or to
* any but the first operation of one of the above mentioned types.
* If no such operation is included, the native tokens will be sent back to the sender.
*/
function batchCall(Operation[] calldata operations) external payable;
/**
* @dev Batch call function with EIP-2771 encoded msgSender
* @param operations Array of batch operations
*
* NOTE: This can be called only by contracts recognized as _trusted forwarder_
* by the host contract (see `Superfluid.isTrustedForwarder`).
* If native tokens are passed along, the same rules as for `batchCall` apply,
* with an optional refund going to the encoded msgSender.
*/
function forwardBatchCall(Operation[] calldata operations) external payable;
/**
* @dev returns the address of the forwarder contract used to route batch operations of type
* OPERATION_TYPE_ERC2771_FORWARD_CALL.
* Needs to be set as _trusted forwarder_ by the call targets of such operations.
*/
// solhint-disable func-name-mixedcase
function getERC2771Forwarder() external view returns(address);
/**************************************************************************
* Function modifiers for access control and parameter validations
*
* While they cannot be explicitly stated in function definitions, they are
* listed in function definition comments instead for clarity.
*
* TODO: turning these off because solidity-coverage doesn't like it
*************************************************************************/
/* /// @dev The current superfluid context is clean.
modifier cleanCtx() virtual;
/// @dev Require the ctx being valid.
modifier requireValidCtx(bytes memory ctx) virtual;
/// @dev Assert the ctx being valid.
modifier assertValidCtx(bytes memory ctx) virtual;
/// @dev The agreement is a listed agreement.
modifier isAgreement(ISuperAgreement agreementClass) virtual;
// onlyGovernance
/// @dev The msg.sender must be a listed agreement.
modifier onlyAgreement() virtual;
/// @dev The app is registered and not jailed.
modifier isAppActive(ISuperApp app) virtual; */
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity ^0.8.4;
interface IXERC20 {
/**
* @notice Emits when a lockbox is set
*
* @param _lockbox The address of the lockbox
*/
event LockboxSet(address _lockbox);
/**
* @notice Emits when a limit is set
*
* @param _mintingLimit The updated minting limit we are setting to the bridge
* @param _burningLimit The updated burning limit we are setting to the bridge
* @param _bridge The address of the bridge we are setting the limit too
*/
event BridgeLimitsSet(uint256 _mintingLimit, uint256 _burningLimit, address indexed _bridge);
/**
* @notice Reverts when a user with too low of a limit tries to call mint/burn
*/
error IXERC20_NotHighEnoughLimits();
struct Bridge {
BridgeParameters minterParams;
BridgeParameters burnerParams;
}
struct BridgeParameters {
// is set when the limit is set and on mint/burn
uint256 timestamp;
// is set when the limit is set
uint256 ratePerSecond;
// limit at the time of setting it
uint256 maxLimit;
// changed on mint/burn
uint256 currentLimit;
}
/**
* @notice Sets the lockbox address
*
* @param _lockbox The address of the lockbox (0x0 if no lockbox)
*/
function setLockbox(address _lockbox) external;
/**
* @notice Updates the limits of any bridge
* @dev Can only be called by the owner
* @param _mintingLimit The updated minting limit we are setting to the bridge
* @param _burningLimit The updated burning limit we are setting to the bridge
* @param _bridge The address of the bridge we are setting the limits too
*/
function setLimits(address _bridge, uint256 _mintingLimit, uint256 _burningLimit) external;
/**
* @notice Returns the max limit of a bridge
*
* @param _bridge The bridge we are viewing the limits of
* @return _limit The limit the bridge has
*/
function mintingMaxLimitOf(address _bridge) external view returns (uint256 _limit);
/**
* @notice Returns the max limit of a bridge
*
* @param _bridge the bridge we are viewing the limits of
* @return _limit The limit the bridge has
*/
function burningMaxLimitOf(address _bridge) external view returns (uint256 _limit);
/**
* @notice Returns the current limit of a bridge
*
* @param _bridge The bridge we are viewing the limits of
* @return _limit The limit the bridge has
*/
function mintingCurrentLimitOf(address _bridge) external view returns (uint256 _limit);
/**
* @notice Returns the current limit of a bridge
*
* @param _bridge the bridge we are viewing the limits of
* @return _limit The limit the bridge has
*/
function burningCurrentLimitOf(address _bridge) external view returns (uint256 _limit);
/**
* @notice Mints tokens for a user
* @dev Can only be called by a bridge
* @param _user The address of the user who needs tokens minted
* @param _amount The amount of tokens being minted
*/
function mint(address _user, uint256 _amount) external;
/**
* @notice Burns tokens for a user
* @dev Can only be called by a bridge
* @param _user The address of the user who needs tokens burned
* @param _amount The amount of tokens being burned
*/
function burn(address _user, uint256 _amount) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperfluidToken } from "./ISuperfluidToken.sol";
import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { IERC777 } from "@openzeppelin/contracts/token/ERC777/IERC777.sol";
import { IPoolAdminNFT } from "../agreements/gdav1/IPoolAdminNFT.sol";
import { IPoolMemberNFT } from "../agreements/gdav1/IPoolMemberNFT.sol";
/**
* @title Super token (Superfluid Token + ERC20 + ERC777) interface
* @author Superfluid
*/
interface ISuperToken is ISuperfluidToken, IERC20Metadata, IERC777 {
/**************************************************************************
* Errors
*************************************************************************/
error SUPER_TOKEN_CALLER_IS_NOT_OPERATOR_FOR_HOLDER(); // 0xf7f02227
error SUPER_TOKEN_NOT_ERC777_TOKENS_RECIPIENT(); // 0xfe737d05
error SUPER_TOKEN_INFLATIONARY_DEFLATIONARY_NOT_SUPPORTED(); // 0xe3e13698
error SUPER_TOKEN_NO_UNDERLYING_TOKEN(); // 0xf79cf656
error SUPER_TOKEN_ONLY_SELF(); // 0x7ffa6648
error SUPER_TOKEN_ONLY_ADMIN(); // 0x0484acab
error SUPER_TOKEN_ONLY_GOV_OWNER(); // 0xd9c7ed08
error SUPER_TOKEN_APPROVE_FROM_ZERO_ADDRESS(); // 0x81638627
error SUPER_TOKEN_APPROVE_TO_ZERO_ADDRESS(); // 0xdf070274
error SUPER_TOKEN_BURN_FROM_ZERO_ADDRESS(); // 0xba2ab184
error SUPER_TOKEN_MINT_TO_ZERO_ADDRESS(); // 0x0d243157
error SUPER_TOKEN_TRANSFER_FROM_ZERO_ADDRESS(); // 0xeecd6c9b
error SUPER_TOKEN_TRANSFER_TO_ZERO_ADDRESS(); // 0xe219bd39
error SUPER_TOKEN_NFT_PROXY_ADDRESS_CHANGED(); // 0x6bef249d
/**
* @dev Initialize the contract
*/
function initialize(
IERC20 underlyingToken,
uint8 underlyingDecimals,
string calldata n,
string calldata s
) external;
/**
* @dev Initialize the contract with an admin
*/
function initializeWithAdmin(
IERC20 underlyingToken,
uint8 underlyingDecimals,
string calldata n,
string calldata s,
address admin
) external;
/**
* @notice Changes the admin for the SuperToken
* @dev Only the current admin can call this function
* if admin is address(0), it is implicitly the host address
* @param newAdmin New admin address
*/
function changeAdmin(address newAdmin) external;
event AdminChanged(address indexed oldAdmin, address indexed newAdmin);
/**
* @dev Returns the admin address for the SuperToken
*/
function getAdmin() external view returns (address admin);
/**************************************************************************
* Immutable variables
*************************************************************************/
// solhint-disable-next-line func-name-mixedcase
function POOL_ADMIN_NFT() external view returns (IPoolAdminNFT);
// solhint-disable-next-line func-name-mixedcase
function POOL_MEMBER_NFT() external view returns (IPoolMemberNFT);
/**************************************************************************
* IERC20Metadata & ERC777
*************************************************************************/
/**
* @dev Returns the name of the token.
*/
function name() external view override(IERC777, IERC20Metadata) returns (string memory);
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() external view override(IERC777, IERC20Metadata) returns (string memory);
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
* called.
*
* @custom:note SuperToken always uses 18 decimals.
*
* This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() external view override(IERC20Metadata) returns (uint8);
/**************************************************************************
* ERC20 & ERC777
*************************************************************************/
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() external view override(IERC777, IERC20) returns (uint256);
/**
* @dev Returns the amount of tokens owned by an account (`owner`).
*/
function balanceOf(address account) external view override(IERC777, IERC20) returns(uint256 balance);
/**************************************************************************
* ERC20
*************************************************************************/
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* @return Returns Success a boolean value indicating whether the operation succeeded.
*
* @custom:emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external override(IERC20) returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* @notice This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external override(IERC20) view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* @return Returns Success a boolean value indicating whether the operation succeeded.
*
* @custom:note Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* @custom:emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external override(IERC20) returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* @return Returns Success a boolean value indicating whether the operation succeeded.
*
* @custom:emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external override(IERC20) returns (bool);
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* @custom:emits an {Approval} event indicating the updated allowance.
*
* @custom:requirements
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* @custom:emits an {Approval} event indicating the updated allowance.
*
* @custom:requirements
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
/**************************************************************************
* ERC777
*************************************************************************/
/**
* @dev Returns the smallest part of the token that is not divisible. This
* means all token operations (creation, movement and destruction) must have
* amounts that are a multiple of this number.
*
* @custom:note For super token contracts, this value is always 1
*/
function granularity() external view override(IERC777) returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* @dev If send or receive hooks are registered for the caller and `recipient`,
* the corresponding functions will be called with `userData` and empty
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* @custom:emits a {Sent} event.
*
* @custom:requirements
* - the caller must have at least `amount` tokens.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function send(address recipient, uint256 amount, bytes calldata userData) external override(IERC777);
/**
* @dev Destroys `amount` tokens from the caller's account, reducing the
* total supply and transfers the underlying token to the caller's account.
*
* If a send hook is registered for the caller, the corresponding function
* will be called with `userData` and empty `operatorData`. See {IERC777Sender}.
*
* @custom:emits a {Burned} event.
*
* @custom:requirements
* - the caller must have at least `amount` tokens.
*/
function burn(uint256 amount, bytes calldata userData) external override(IERC777);
/**
* @dev Returns true if an account is an operator of `tokenHolder`.
* Operators can send and burn tokens on behalf of their owners. All
* accounts are their own operator.
*
* See {operatorSend} and {operatorBurn}.
*/
function isOperatorFor(address operator, address tokenHolder) external override(IERC777) view returns (bool);
/**
* @dev Make an account an operator of the caller.
*
* See {isOperatorFor}.
*
* @custom:emits an {AuthorizedOperator} event.
*
* @custom:requirements
* - `operator` cannot be calling address.
*/
function authorizeOperator(address operator) external override(IERC777);
/**
* @dev Revoke an account's operator status for the caller.
*
* See {isOperatorFor} and {defaultOperators}.
*
* @custom:emits a {RevokedOperator} event.
*
* @custom:requirements
* - `operator` cannot be calling address.
*/
function revokeOperator(address operator) external override(IERC777);
/**
* @dev Returns the list of default operators. These accounts are operators
* for all token holders, even if {authorizeOperator} was never called on
* them.
*
* This list is immutable, but individual holders may revoke these via
* {revokeOperator}, in which case {isOperatorFor} will return false.
*/
function defaultOperators() external override(IERC777) view returns (address[] memory);
/**
* @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
* be an operator of `sender`.
*
* If send or receive hooks are registered for `sender` and `recipient`,
* the corresponding functions will be called with `userData` and
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* @custom:emits a {Sent} event.
*
* @custom:requirements
* - `sender` cannot be the zero address.
* - `sender` must have at least `amount` tokens.
* - the caller must be an operator for `sender`.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function operatorSend(
address sender,
address recipient,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external override(IERC777);
/**
* @dev Destroys `amount` tokens from `account`, reducing the total supply.
* The caller must be an operator of `account`.
*
* If a send hook is registered for `account`, the corresponding function
* will be called with `userData` and `operatorData`. See {IERC777Sender}.
*
* @custom:emits a {Burned} event.
*
* @custom:requirements
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
* - the caller must be an operator for `account`.
*/
function operatorBurn(
address account,
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
) external override(IERC777);
/**************************************************************************
* SuperToken custom token functions
*************************************************************************/
/**
* @dev Mint new tokens for the account
* If `userData` is not empty, the `tokensReceived` hook is invoked according to ERC777 semantics.
*
* @custom:modifiers
* - onlySelf
*/
function selfMint(
address account,
uint256 amount,
bytes memory userData
) external;
/**
* @dev Burn existing tokens for the account
* If `userData` is not empty, the `tokensToSend` hook is invoked according to ERC777 semantics.
*
* @custom:modifiers
* - onlySelf
*/
function selfBurn(
address account,
uint256 amount,
bytes memory userData
) external;
/**
* @dev Transfer `amount` tokens from the `sender` to `recipient`.
* If `spender` isn't the same as `sender`, checks if `spender` has allowance to
* spend tokens of `sender`.
*
* @custom:modifiers
* - onlySelf
*/
function selfTransferFrom(
address sender,
address spender,
address recipient,
uint256 amount
) external;
/**
* @dev Give `spender`, `amount` allowance to spend the tokens of
* `account`.
*
* @custom:modifiers
* - onlySelf
*/
function selfApproveFor(
address account,
address spender,
uint256 amount
) external;
/**************************************************************************
* SuperToken extra functions
*************************************************************************/
/**
* @dev Transfer all available balance from `msg.sender` to `recipient`
*/
function transferAll(address recipient) external;
/**************************************************************************
* ERC20 wrapping
*************************************************************************/
/**
* @dev Return the underlying token contract
* @return tokenAddr Underlying token address
*/
function getUnderlyingToken() external view returns(address tokenAddr);
/**
* @dev Return the underlying token decimals
* @return underlyingDecimals Underlying token decimals
*/
function getUnderlyingDecimals() external view returns (uint8 underlyingDecimals);
/**
* @dev Return the underlying token conversion rate
* @param amount Number of tokens to be upgraded (in 18 decimals)
* @return underlyingAmount The underlying token amount after scaling
* @return adjustedAmount The super token amount after scaling
*/
function toUnderlyingAmount(uint256 amount)
external
view
returns (uint256 underlyingAmount, uint256 adjustedAmount);
/**
* @dev Upgrade ERC20 to SuperToken.
* @param amount Number of tokens to be upgraded (in 18 decimals)
*
* @custom:note It will use `transferFrom` to get tokens. Before calling this
* function you should `approve` this contract
*/
function upgrade(uint256 amount) external;
/**
* @dev Upgrade ERC20 to SuperToken and transfer immediately
* @param to The account to receive upgraded tokens
* @param amount Number of tokens to be upgraded (in 18 decimals)
* @param userData User data for the TokensRecipient callback
*
* @custom:note It will use `transferFrom` to get tokens. Before calling this
* function you should `approve` this contract
*
* @custom:warning
* - there is potential of reentrancy IF the "to" account is a registered ERC777 recipient.
* @custom:requirements
* - if `userData` is NOT empty AND `to` is a contract, it MUST be a registered ERC777 recipient
* otherwise it reverts.
*/
function upgradeTo(address to, uint256 amount, bytes calldata userData) external;
/**
* @dev Token upgrade event
* @param account Account where tokens are upgraded to
* @param amount Amount of tokens upgraded (in 18 decimals)
*/
event TokenUpgraded(
address indexed account,
uint256 amount
);
/**
* @dev Downgrade SuperToken to ERC20.
* @dev It will call transfer to send tokens
* @param amount Number of tokens to be downgraded
*/
function downgrade(uint256 amount) external;
/**
* @dev Downgrade SuperToken to ERC20 and transfer immediately
* @param to The account to receive downgraded tokens
* @param amount Number of tokens to be downgraded (in 18 decimals)
*/
function downgradeTo(address to, uint256 amount) external;
/**
* @dev Token downgrade event
* @param account Account whose tokens are downgraded
* @param amount Amount of tokens downgraded
*/
event TokenDowngraded(
address indexed account,
uint256 amount
);
/**************************************************************************
* Batch Operations
*************************************************************************/
/**
* @dev Perform ERC20 approve by host contract.
* @param account The account owner to be approved.
* @param spender The spender of account owner's funds.
* @param amount Number of tokens to be approved.
*
* @custom:modifiers
* - onlyHost
*/
function operationApprove(
address account,
address spender,
uint256 amount
) external;
function operationIncreaseAllowance(
address account,
address spender,
uint256 addedValue
) external;
function operationDecreaseAllowance(
address account,
address spender,
uint256 subtractedValue
) external;
/**
* @dev Perform ERC20 transferFrom by host contract.
* @param account The account to spend sender's funds.
* @param spender The account where the funds is sent from.
* @param recipient The recipient of the funds.
* @param amount Number of tokens to be transferred.
*
* @custom:modifiers
* - onlyHost
*/
function operationTransferFrom(
address account,
address spender,
address recipient,
uint256 amount
) external;
/**
* @dev Perform ERC777 send by host contract.
* @param spender The account where the funds is sent from.
* @param recipient The recipient of the funds.
* @param amount Number of tokens to be transferred.
* @param userData Arbitrary user inputted data
*
* @custom:modifiers
* - onlyHost
*/
function operationSend(
address spender,
address recipient,
uint256 amount,
bytes memory userData
) external;
/**
* @dev Upgrade ERC20 to SuperToken by host contract.
* @param account The account to be changed.
* @param amount Number of tokens to be upgraded (in 18 decimals)
*
* @custom:modifiers
* - onlyHost
*/
function operationUpgrade(address account, uint256 amount) external;
/**
* @dev Downgrade ERC20 to SuperToken by host contract.
* @param account The account to be changed.
* @param amount Number of tokens to be downgraded (in 18 decimals)
*
* @custom:modifiers
* - onlyHost
*/
function operationDowngrade(address account, uint256 amount) external;
/**
* @dev Upgrade ERC20 to SuperToken by host contract and transfer immediately.
* @param account The account to be changed.
* @param to The account to receive upgraded tokens
* @param amount Number of tokens to be upgraded (in 18 decimals)
*
* @custom:modifiers
* - onlyHost
*/
function operationUpgradeTo(address account, address to, uint256 amount) external;
/**
* @dev Downgrade ERC20 to SuperToken by host contract and transfer immediately.
* @param account The account to be changed.
* @param to The account to receive downgraded tokens
* @param amount Number of tokens to be downgraded (in 18 decimals)
*
* @custom:modifiers
* - onlyHost
*/
function operationDowngradeTo(address account, address to, uint256 amount) external;
/**
* @dev Pool Admin NFT proxy created event
* @param poolAdminNFT pool admin nft address
*/
event PoolAdminNFTCreated(
IPoolAdminNFT indexed poolAdminNFT
);
/**
* @dev Pool Member NFT proxy created event
* @param poolMemberNFT pool member nft address
*/
event PoolMemberNFTCreated(
IPoolMemberNFT indexed poolMemberNFT
);
/**************************************************************************
* Function modifiers for access control and parameter validations
*
* While they cannot be explicitly stated in function definitions, they are
* listed in function definition comments instead for clarity.
*
* NOTE: solidity-coverage not supporting it
*************************************************************************/
/// @dev The msg.sender must be the contract itself
//modifier onlySelf() virtual
}// SPDX-License-Identifier: AGPLv3
pragma solidity ^0.8.23;
/**
* @title UUPS (Universal Upgradeable Proxy Standard) Shared Library
*/
library UUPSUtils {
/**
* @dev Implementation slot constant.
* Using https://eips.ethereum.org/EIPS/eip-1967 standard
* Storage slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc
* (obtained as bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)).
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/// @dev Get implementation address.
function implementation() internal view returns (address impl) {
assembly { // solium-disable-line
impl := sload(_IMPLEMENTATION_SLOT)
}
}
/// @dev Set new implementation address.
function setImplementation(address codeAddress) internal {
assembly {
// solium-disable-line
sstore(
_IMPLEMENTATION_SLOT,
codeAddress
)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
pragma solidity ^0.8.0;
/**
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
* instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
* be specified by overriding the virtual {_implementation} function.
*
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
* different contract through the {_delegate} function.
*
* The success and return data of the delegated call will be returned back to the caller of the proxy.
*/
abstract contract Proxy {
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
* and {_fallback} should delegate.
*/
function _implementation() internal view virtual returns (address);
/**
* @dev Delegates the current call to the address returned by `_implementation()`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _fallback() internal virtual {
_beforeFallback();
_delegate(_implementation());
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
* function in the contract matches the call data.
*/
fallback() external payable virtual {
_fallback();
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
* is empty.
*/
receive() external payable virtual {
_fallback();
}
/**
* @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
* call, or as part of the Solidity `fallback` or `receive` functions.
*
* If overridden should call `super._beforeFallback()`.
*/
function _beforeFallback() internal virtual {}
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
/**
* @title Super app definitions library
* @author Superfluid
*/
library SuperAppDefinitions {
/**************************************************************************
/ App manifest config word
/**************************************************************************/
/*
* App level is a way to allow the app to whitelist what other app it can
* interact with (aka. composite app feature).
*
* For more details, refer to the technical paper of superfluid protocol.
*/
uint256 constant internal APP_LEVEL_MASK = 0xFF;
// The app is at the final level, hence it doesn't want to interact with any other app
uint256 constant internal APP_LEVEL_FINAL = 1 << 0;
// The app is at the second level, it may interact with other final level apps if whitelisted
uint256 constant internal APP_LEVEL_SECOND = 1 << 1;
function getAppCallbackLevel(uint256 configWord) internal pure returns (uint8) {
return uint8(configWord & APP_LEVEL_MASK);
}
uint256 constant internal APP_JAIL_BIT = 1 << 15;
function isAppJailed(uint256 configWord) internal pure returns (bool) {
return (configWord & SuperAppDefinitions.APP_JAIL_BIT) > 0;
}
/**************************************************************************
/ Callback implementation bit masks
/**************************************************************************/
uint256 constant internal AGREEMENT_CALLBACK_NOOP_BITMASKS = 0xFF << 32;
uint256 constant internal BEFORE_AGREEMENT_CREATED_NOOP = 1 << (32 + 0);
uint256 constant internal AFTER_AGREEMENT_CREATED_NOOP = 1 << (32 + 1);
uint256 constant internal BEFORE_AGREEMENT_UPDATED_NOOP = 1 << (32 + 2);
uint256 constant internal AFTER_AGREEMENT_UPDATED_NOOP = 1 << (32 + 3);
uint256 constant internal BEFORE_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 4);
uint256 constant internal AFTER_AGREEMENT_TERMINATED_NOOP = 1 << (32 + 5);
/**************************************************************************
/ App Jail Reasons
/**************************************************************************/
uint256 constant internal APP_RULE_NO_REVERT_ON_TERMINATION_CALLBACK = 10;
uint256 constant internal APP_RULE_NO_CRITICAL_SENDER_ACCOUNT = 11;
uint256 constant internal APP_RULE_NO_CRITICAL_RECEIVER_ACCOUNT = 12;
uint256 constant internal APP_RULE_CTX_IS_READONLY = 20;
uint256 constant internal APP_RULE_CTX_IS_NOT_CLEAN = 21;
uint256 constant internal APP_RULE_CTX_IS_MALFORMATED = 22;
uint256 constant internal APP_RULE_COMPOSITE_APP_IS_NOT_WHITELISTED = 30;
uint256 constant internal APP_RULE_COMPOSITE_APP_IS_JAILED = 31;
uint256 constant internal APP_RULE_MAX_APP_LEVEL_REACHED = 40;
// Validate configWord cleaness for future compatibility, or else may introduce undefined future behavior
function isConfigWordClean(uint256 configWord) internal pure returns (bool) {
return (configWord & ~(APP_LEVEL_MASK | APP_JAIL_BIT | AGREEMENT_CALLBACK_NOOP_BITMASKS)) == uint256(0);
}
}
/**
* @title Context definitions library
* @author Superfluid
*/
library ContextDefinitions {
/**************************************************************************
/ Call info
/**************************************************************************/
// app level
uint256 constant internal CALL_INFO_APP_LEVEL_MASK = 0xFF;
// call type
uint256 constant internal CALL_INFO_CALL_TYPE_SHIFT = 32;
uint256 constant internal CALL_INFO_CALL_TYPE_MASK = 0xF << CALL_INFO_CALL_TYPE_SHIFT;
uint8 constant internal CALL_INFO_CALL_TYPE_AGREEMENT = 1;
uint8 constant internal CALL_INFO_CALL_TYPE_APP_ACTION = 2;
uint8 constant internal CALL_INFO_CALL_TYPE_APP_CALLBACK = 3;
function decodeCallInfo(uint256 callInfo)
internal pure
returns (uint8 appCallbackLevel, uint8 callType)
{
appCallbackLevel = uint8(callInfo & CALL_INFO_APP_LEVEL_MASK);
callType = uint8((callInfo & CALL_INFO_CALL_TYPE_MASK) >> CALL_INFO_CALL_TYPE_SHIFT);
}
function encodeCallInfo(uint8 appCallbackLevel, uint8 callType)
internal pure
returns (uint256 callInfo)
{
return uint256(appCallbackLevel) | (uint256(callType) << CALL_INFO_CALL_TYPE_SHIFT);
}
}
/**
* @title Flow Operator definitions library
* @author Superfluid
*/
library FlowOperatorDefinitions {
uint8 constant internal AUTHORIZE_FLOW_OPERATOR_CREATE = uint8(1) << 0;
uint8 constant internal AUTHORIZE_FLOW_OPERATOR_UPDATE = uint8(1) << 1;
uint8 constant internal AUTHORIZE_FLOW_OPERATOR_DELETE = uint8(1) << 2;
uint8 constant internal AUTHORIZE_FULL_CONTROL =
AUTHORIZE_FLOW_OPERATOR_CREATE | AUTHORIZE_FLOW_OPERATOR_UPDATE | AUTHORIZE_FLOW_OPERATOR_DELETE;
uint8 constant internal REVOKE_FLOW_OPERATOR_CREATE = ~(uint8(1) << 0);
uint8 constant internal REVOKE_FLOW_OPERATOR_UPDATE = ~(uint8(1) << 1);
uint8 constant internal REVOKE_FLOW_OPERATOR_DELETE = ~(uint8(1) << 2);
function isPermissionsClean(uint8 permissions) internal pure returns (bool) {
return (
permissions & ~(AUTHORIZE_FLOW_OPERATOR_CREATE
| AUTHORIZE_FLOW_OPERATOR_UPDATE
| AUTHORIZE_FLOW_OPERATOR_DELETE)
) == uint8(0);
}
}
/**
* @title Batch operation library
* @author Superfluid
*/
library BatchOperation {
/**
* @dev ERC20.approve batch operation type
*
* Call spec:
* ISuperToken(target).operationApprove(
* abi.decode(data, (address spender, uint256 amount))
* )
*/
uint32 constant internal OPERATION_TYPE_ERC20_APPROVE = 1;
/**
* @dev ERC20.transferFrom batch operation type
*
* Call spec:
* ISuperToken(target).operationTransferFrom(
* abi.decode(data, (address sender, address recipient, uint256 amount)
* )
*/
uint32 constant internal OPERATION_TYPE_ERC20_TRANSFER_FROM = 2;
/**
* @dev ERC777.send batch operation type
*
* Call spec:
* ISuperToken(target).operationSend(
* abi.decode(data, (address recipient, uint256 amount, bytes userData)
* )
*/
uint32 constant internal OPERATION_TYPE_ERC777_SEND = 3;
/**
* @dev ERC20.increaseAllowance batch operation type
*
* Call spec:
* ISuperToken(target).operationIncreaseAllowance(
* abi.decode(data, (address account, address spender, uint256 addedValue))
* )
*/
uint32 constant internal OPERATION_TYPE_ERC20_INCREASE_ALLOWANCE = 4;
/**
* @dev ERC20.decreaseAllowance batch operation type
*
* Call spec:
* ISuperToken(target).operationDecreaseAllowance(
* abi.decode(data, (address account, address spender, uint256 subtractedValue))
* )
*/
uint32 constant internal OPERATION_TYPE_ERC20_DECREASE_ALLOWANCE = 5;
/**
* @dev SuperToken.upgrade batch operation type
*
* Call spec:
* ISuperToken(target).operationUpgrade(
* abi.decode(data, (uint256 amount)
* )
*/
uint32 constant internal OPERATION_TYPE_SUPERTOKEN_UPGRADE = 1 + 100;
/**
* @dev SuperToken.downgrade batch operation type
*
* Call spec:
* ISuperToken(target).operationDowngrade(
* abi.decode(data, (uint256 amount)
* )
*/
uint32 constant internal OPERATION_TYPE_SUPERTOKEN_DOWNGRADE = 2 + 100;
/**
* @dev SuperToken.upgradeTo batch operation type
*
* Call spec:
* ISuperToken(target).operationUpgradeTo(
* abi.decode(data, (address to, uint256 amount)
* )
*/
uint32 constant internal OPERATION_TYPE_SUPERTOKEN_UPGRADE_TO = 3 + 100;
/**
* @dev SuperToken.downgradeTo batch operation type
*
* Call spec:
* ISuperToken(target).operationDowngradeTo(
* abi.decode(data, (address to, uint256 amount)
* )
*/
uint32 constant internal OPERATION_TYPE_SUPERTOKEN_DOWNGRADE_TO = 4 + 100;
/**
* @dev Superfluid.callAgreement batch operation type
*
* Call spec:
* callAgreement(
* ISuperAgreement(target)),
* abi.decode(data, (bytes callData, bytes userData)
* )
*/
uint32 constant internal OPERATION_TYPE_SUPERFLUID_CALL_AGREEMENT = 1 + 200;
/**
* @dev Superfluid.callAppAction batch operation type
*
* Call spec:
* callAppAction(
* ISuperApp(target)),
* data
* )
*/
uint32 constant internal OPERATION_TYPE_SUPERFLUID_CALL_APP_ACTION = 2 + 200;
/**
* @dev SimpleForwarder.forwardCall batch operation type
*
* Call spec:
* forwardCall(
* target,
* data
* )
* NOTE: This operation allows to make arbitrary calls to arbitrary targets.
* The calls are routed through a dedicated utility contract `SimpleForwarder`.
* This is important because the host contract has privileged access to other framework contracts,
* SuperTokens, SuperApps etc.
* Allowing arbitrary calls to arbitrary targets with the host as sender would thus be unsafe.
*/
uint32 constant internal OPERATION_TYPE_SIMPLE_FORWARD_CALL = 1 + 300;
/**
* @dev ERC2771Forwarder.forward2771Call batch operation type
*
* Call spec:
* forward2771Call(
* target,
* msgSender,
* data
* )
*
* NOTE: In the context of this operation, the `ERC2771Forwarder` contract acts as the
* _trusted forwarder_ which must be trusted by the _recipient contract_ (operation target).
* It shall do so by dynamically looking up the ERC2771Forwarder used by the host, like this:
*
* function isTrustedForwarder(address forwarder) public view returns(bool) {
* return forwarder == address(host.getERC2771Forwarder());
* }
*
* If used in the context of a `forwardBatchCall`, we effectively have a chaining/nesting
* of ERC-2771 calls where the host acts as _recipient contract_ of the enveloping 2771 call
* and the ERC2771Forwarder acts as the _trusted forwarder_ of the nested 2771 call(s).
* That's why `msgSender` could be either the actual `msg.sender` (if using `batchCall`)
* or the relayed sender address (if using `forwardBatchCall`).
*/
uint32 constant internal OPERATION_TYPE_ERC2771_FORWARD_CALL = 2 + 300;
}
/**
* @title Superfluid governance configs library
* @author Superfluid
*/
library SuperfluidGovernanceConfigs {
bytes32 constant internal SUPERFLUID_REWARD_ADDRESS_CONFIG_KEY =
keccak256("org.superfluid-finance.superfluid.rewardAddress");
bytes32 constant internal CFAV1_PPP_CONFIG_KEY =
keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1.PPPConfiguration");
bytes32 constant internal SUPERTOKEN_MINIMUM_DEPOSIT_KEY =
keccak256("org.superfluid-finance.superfluid.superTokenMinimumDeposit");
function getTrustedForwarderConfigKey(address forwarder) internal pure returns (bytes32) {
return keccak256(abi.encode(
"org.superfluid-finance.superfluid.trustedForwarder",
forwarder));
}
function getAppRegistrationConfigKey(address deployer, string memory registrationKey) internal pure
returns (bytes32)
{
return keccak256(abi.encode(
"org.superfluid-finance.superfluid.appWhiteListing.registrationKey",
deployer,
registrationKey));
}
function getAppFactoryConfigKey(address factory) internal pure returns (bytes32)
{
return keccak256(abi.encode(
"org.superfluid-finance.superfluid.appWhiteListing.factory",
factory));
}
function decodePPPConfig(uint256 pppConfig) internal pure
returns (uint256 liquidationPeriod, uint256 patricianPeriod)
{
liquidationPeriod = (pppConfig >> 32) & type(uint32).max;
patricianPeriod = pppConfig & type(uint32).max;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC777/IERC777.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC777Token standard as defined in the EIP.
*
* This contract uses the
* https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let
* token holders and recipients react to token movements by using setting implementers
* for the associated interfaces in said registry. See {IERC1820Registry} and
* {ERC1820Implementer}.
*/
interface IERC777 {
/**
* @dev Emitted when `amount` tokens are created by `operator` and assigned to `to`.
*
* Note that some additional user `data` and `operatorData` can be logged in the event.
*/
event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);
/**
* @dev Emitted when `operator` destroys `amount` tokens from `account`.
*
* Note that some additional user `data` and `operatorData` can be logged in the event.
*/
event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData);
/**
* @dev Emitted when `operator` is made operator for `tokenHolder`.
*/
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
/**
* @dev Emitted when `operator` is revoked its operator status for `tokenHolder`.
*/
event RevokedOperator(address indexed operator, address indexed tokenHolder);
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the smallest part of the token that is not divisible. This
* means all token operations (creation, movement and destruction) must have
* amounts that are a multiple of this number.
*
* For most token contracts, this value will equal 1.
*/
function granularity() external view returns (uint256);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by an account (`owner`).
*/
function balanceOf(address owner) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* If send or receive hooks are registered for the caller and `recipient`,
* the corresponding functions will be called with `data` and empty
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* Emits a {Sent} event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function send(address recipient, uint256 amount, bytes calldata data) external;
/**
* @dev Destroys `amount` tokens from the caller's account, reducing the
* total supply.
*
* If a send hook is registered for the caller, the corresponding function
* will be called with `data` and empty `operatorData`. See {IERC777Sender}.
*
* Emits a {Burned} event.
*
* Requirements
*
* - the caller must have at least `amount` tokens.
*/
function burn(uint256 amount, bytes calldata data) external;
/**
* @dev Returns true if an account is an operator of `tokenHolder`.
* Operators can send and burn tokens on behalf of their owners. All
* accounts are their own operator.
*
* See {operatorSend} and {operatorBurn}.
*/
function isOperatorFor(address operator, address tokenHolder) external view returns (bool);
/**
* @dev Make an account an operator of the caller.
*
* See {isOperatorFor}.
*
* Emits an {AuthorizedOperator} event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function authorizeOperator(address operator) external;
/**
* @dev Revoke an account's operator status for the caller.
*
* See {isOperatorFor} and {defaultOperators}.
*
* Emits a {RevokedOperator} event.
*
* Requirements
*
* - `operator` cannot be calling address.
*/
function revokeOperator(address operator) external;
/**
* @dev Returns the list of default operators. These accounts are operators
* for all token holders, even if {authorizeOperator} was never called on
* them.
*
* This list is immutable, but individual holders may revoke these via
* {revokeOperator}, in which case {isOperatorFor} will return false.
*/
function defaultOperators() external view returns (address[] memory);
/**
* @dev Moves `amount` tokens from `sender` to `recipient`. The caller must
* be an operator of `sender`.
*
* If send or receive hooks are registered for `sender` and `recipient`,
* the corresponding functions will be called with `data` and
* `operatorData`. See {IERC777Sender} and {IERC777Recipient}.
*
* Emits a {Sent} event.
*
* Requirements
*
* - `sender` cannot be the zero address.
* - `sender` must have at least `amount` tokens.
* - the caller must be an operator for `sender`.
* - `recipient` cannot be the zero address.
* - if `recipient` is a contract, it must implement the {IERC777Recipient}
* interface.
*/
function operatorSend(
address sender,
address recipient,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;
/**
* @dev Destroys `amount` tokens from `account`, reducing the total supply.
* The caller must be an operator of `account`.
*
* If a send hook is registered for `account`, the corresponding function
* will be called with `data` and `operatorData`. See {IERC777Sender}.
*
* Emits a {Burned} event.
*
* Requirements
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
* - the caller must be an operator for `account`.
*/
function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external;
event Sent(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperAgreement } from "./ISuperAgreement.sol";
/**
* @title Superfluid token interface
* @author Superfluid
*/
interface ISuperfluidToken {
/**************************************************************************
* Errors
*************************************************************************/
error SF_TOKEN_AGREEMENT_ALREADY_EXISTS(); // 0xf05521f6
error SF_TOKEN_AGREEMENT_DOES_NOT_EXIST(); // 0xdae18809
error SF_TOKEN_BURN_INSUFFICIENT_BALANCE(); // 0x10ecdf44
error SF_TOKEN_MOVE_INSUFFICIENT_BALANCE(); // 0x2f4cb941
error SF_TOKEN_ONLY_LISTED_AGREEMENT(); // 0xc9ff6644
error SF_TOKEN_ONLY_HOST(); // 0xc51efddd
/**************************************************************************
* Basic information
*************************************************************************/
/**
* @dev Get superfluid host contract address
*/
function getHost() external view returns(address host);
/**
* @dev Encoded liquidation type data mainly used for handling stack to deep errors
*
* @custom:note
* - version: 1
* - liquidationType key:
* - 0 = reward account receives reward (PIC period)
* - 1 = liquidator account receives reward (Pleb period)
* - 2 = liquidator account receives reward (Pirate period/bailout)
*/
struct LiquidationTypeData {
uint256 version;
uint8 liquidationType;
}
/**************************************************************************
* Real-time balance functions
*************************************************************************/
/**
* @dev Calculate the real balance of a user, taking in consideration all agreements of the account
* @param account for the query
* @param timestamp Time of balance
* @return availableBalance Real-time balance
* @return deposit Account deposit
* @return owedDeposit Account owed Deposit
*/
function realtimeBalanceOf(
address account,
uint256 timestamp
)
external view
returns (
int256 availableBalance,
uint256 deposit,
uint256 owedDeposit);
/**
* @notice Calculate the realtime balance given the current host.getNow() value
* @dev realtimeBalanceOf with timestamp equals to block timestamp
* @param account for the query
* @return availableBalance Real-time balance
* @return deposit Account deposit
* @return owedDeposit Account owed Deposit
*/
function realtimeBalanceOfNow(
address account
)
external view
returns (
int256 availableBalance,
uint256 deposit,
uint256 owedDeposit,
uint256 timestamp);
/**
* @notice Check if account is critical
* @dev A critical account is when availableBalance < 0
* @param account The account to check
* @param timestamp The time we'd like to check if the account is critical (should use future)
* @return isCritical Whether the account is critical
*/
function isAccountCritical(
address account,
uint256 timestamp
)
external view
returns(bool isCritical);
/**
* @notice Check if account is critical now (current host.getNow())
* @dev A critical account is when availableBalance < 0
* @param account The account to check
* @return isCritical Whether the account is critical
*/
function isAccountCriticalNow(
address account
)
external view
returns(bool isCritical);
/**
* @notice Check if account is solvent
* @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance
* @param account The account to check
* @param timestamp The time we'd like to check if the account is solvent (should use future)
* @return isSolvent True if the account is solvent, false otherwise
*/
function isAccountSolvent(
address account,
uint256 timestamp
)
external view
returns(bool isSolvent);
/**
* @notice Check if account is solvent now
* @dev An account is insolvent when the sum of deposits for a token can't cover the negative availableBalance
* @param account The account to check
* @return isSolvent True if the account is solvent, false otherwise
*/
function isAccountSolventNow(
address account
)
external view
returns(bool isSolvent);
/**
* @notice Get a list of agreements that is active for the account
* @dev An active agreement is one that has state for the account
* @param account Account to query
* @return activeAgreements List of accounts that have non-zero states for the account
*/
function getAccountActiveAgreements(address account)
external view
returns(ISuperAgreement[] memory activeAgreements);
/**************************************************************************
* Super Agreement hosting functions
*************************************************************************/
/**
* @dev Create a new agreement
* @param id Agreement ID
* @param data Agreement data
*/
function createAgreement(
bytes32 id,
bytes32[] calldata data
)
external;
/**
* @dev Agreement created event
* @param agreementClass Contract address of the agreement
* @param id Agreement ID
* @param data Agreement data
*/
event AgreementCreated(
address indexed agreementClass,
bytes32 id,
bytes32[] data
);
/**
* @dev Get data of the agreement
* @param agreementClass Contract address of the agreement
* @param id Agreement ID
* @return data Data of the agreement
*/
function getAgreementData(
address agreementClass,
bytes32 id,
uint dataLength
)
external view
returns(bytes32[] memory data);
/**
* @dev Create a new agreement
* @param id Agreement ID
* @param data Agreement data
*/
function updateAgreementData(
bytes32 id,
bytes32[] calldata data
)
external;
/**
* @dev Agreement updated event
* @param agreementClass Contract address of the agreement
* @param id Agreement ID
* @param data Agreement data
*/
event AgreementUpdated(
address indexed agreementClass,
bytes32 id,
bytes32[] data
);
/**
* @dev Close the agreement
* @param id Agreement ID
*/
function terminateAgreement(
bytes32 id,
uint dataLength
)
external;
/**
* @dev Agreement terminated event
* @param agreementClass Contract address of the agreement
* @param id Agreement ID
*/
event AgreementTerminated(
address indexed agreementClass,
bytes32 id
);
/**
* @dev Update agreement state slot
* @param account Account to be updated
*
* @custom:note
* - To clear the storage out, provide zero-ed array of intended length
*/
function updateAgreementStateSlot(
address account,
uint256 slotId,
bytes32[] calldata slotData
)
external;
/**
* @dev Agreement account state updated event
* @param agreementClass Contract address of the agreement
* @param account Account updated
* @param slotId slot id of the agreement state
*/
event AgreementStateUpdated(
address indexed agreementClass,
address indexed account,
uint256 slotId
);
/**
* @dev Get data of the slot of the state of an agreement
* @param agreementClass Contract address of the agreement
* @param account Account to query
* @param slotId slot id of the state
* @param dataLength length of the state data
*/
function getAgreementStateSlot(
address agreementClass,
address account,
uint256 slotId,
uint dataLength
)
external view
returns (bytes32[] memory slotData);
/**
* @notice Settle balance from an account by the agreement
* @dev The agreement needs to make sure that the balance delta is balanced afterwards
* @param account Account to query.
* @param delta Amount of balance delta to be settled
*
* @custom:modifiers
* - onlyAgreement
*/
function settleBalance(
address account,
int256 delta
)
external;
/**
* @dev Make liquidation payouts (v2)
* @param id Agreement ID
* @param liquidationTypeData Data regarding the version of the liquidation schema and the type
* @param liquidatorAccount Address of the executor of the liquidation
* @param useDefaultRewardAccount Whether or not the default reward account receives the rewardAmount
* @param targetAccount Account to be liquidated
* @param rewardAmount The amount the rewarded account will receive
* @param targetAccountBalanceDelta The delta amount the target account balance should change by
*
* @custom:note
* - If a bailout is required (bailoutAmount > 0)
* - the actual reward (single deposit) goes to the executor,
* - while the reward account becomes the bailout account
* - total bailout include: bailout amount + reward amount
* - the targetAccount will be bailed out
* - If a bailout is not required
* - the targetAccount will pay the rewardAmount
* - the liquidator (reward account in PIC period) will receive the rewardAmount
*
* @custom:modifiers
* - onlyAgreement
*/
function makeLiquidationPayoutsV2
(
bytes32 id,
bytes memory liquidationTypeData,
address liquidatorAccount,
bool useDefaultRewardAccount,
address targetAccount,
uint256 rewardAmount,
int256 targetAccountBalanceDelta
) external;
/**
* @dev Agreement liquidation event v2 (including agent account)
* @param agreementClass Contract address of the agreement
* @param id Agreement ID
* @param liquidatorAccount Address of the executor of the liquidation
* @param targetAccount Account of the stream sender
* @param rewardAmountReceiver Account that collects the reward or bails out insolvent accounts
* @param rewardAmount The amount the reward recipient account balance should change by
* @param targetAccountBalanceDelta The amount the sender account balance should change by
* @param liquidationTypeData The encoded liquidation type data including the version (how to decode)
*
* @custom:note
* Reward account rule:
* - if the agreement is liquidated during the PIC period
* - the rewardAmountReceiver will get the rewardAmount (remaining deposit), regardless of the liquidatorAccount
* - the targetAccount will pay for the rewardAmount
* - if the agreement is liquidated after the PIC period AND the targetAccount is solvent
* - the rewardAmountReceiver will get the rewardAmount (remaining deposit)
* - the targetAccount will pay for the rewardAmount
* - if the targetAccount is insolvent
* - the liquidatorAccount will get the rewardAmount (single deposit)
* - the default reward account (governance) will pay for both the rewardAmount and bailoutAmount
* - the targetAccount will receive the bailoutAmount
*/
event AgreementLiquidatedV2(
address indexed agreementClass,
bytes32 id,
address indexed liquidatorAccount,
address indexed targetAccount,
address rewardAmountReceiver,
uint256 rewardAmount,
int256 targetAccountBalanceDelta,
bytes liquidationTypeData
);
/**************************************************************************
* Function modifiers for access control and parameter validations
*
* While they cannot be explicitly stated in function definitions, they are
* listed in function definition comments instead for clarity.
*
* NOTE: solidity-coverage not supporting it
*************************************************************************/
/// @dev The msg.sender must be host contract
//modifier onlyHost() virtual;
/// @dev The msg.sender must be a listed agreement.
//modifier onlyAgreement() virtual;
/**************************************************************************
* DEPRECATED
*************************************************************************/
/**
* @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedBy)
* @param agreementClass Contract address of the agreement
* @param id Agreement ID
* @param penaltyAccount Account of the agreement to be penalized
* @param rewardAccount Account that collect the reward
* @param rewardAmount Amount of liquidation reward
*
* @custom:deprecated Use AgreementLiquidatedV2 instead
*/
event AgreementLiquidated(
address indexed agreementClass,
bytes32 id,
address indexed penaltyAccount,
address indexed rewardAccount,
uint256 rewardAmount
);
/**
* @dev System bailout occurred (DEPRECATED BY AgreementLiquidatedBy)
* @param bailoutAccount Account that bailout the penalty account
* @param bailoutAmount Amount of account bailout
*
* @custom:deprecated Use AgreementLiquidatedV2 instead
*/
event Bailout(
address indexed bailoutAccount,
uint256 bailoutAmount
);
/**
* @dev Agreement liquidation event (DEPRECATED BY AgreementLiquidatedV2)
* @param liquidatorAccount Account of the agent that performed the liquidation.
* @param agreementClass Contract address of the agreement
* @param id Agreement ID
* @param penaltyAccount Account of the agreement to be penalized
* @param bondAccount Account that collect the reward or bailout accounts
* @param rewardAmount Amount of liquidation reward
* @param bailoutAmount Amount of liquidation bailouot
*
* @custom:deprecated Use AgreementLiquidatedV2 instead
*
* @custom:note
* Reward account rule:
* - if bailout is equal to 0, then
* - the bondAccount will get the rewardAmount,
* - the penaltyAccount will pay for the rewardAmount.
* - if bailout is larger than 0, then
* - the liquidatorAccount will get the rewardAmouont,
* - the bondAccount will pay for both the rewardAmount and bailoutAmount,
* - the penaltyAccount will pay for the rewardAmount while get the bailoutAmount.
*/
event AgreementLiquidatedBy(
address liquidatorAccount,
address indexed agreementClass,
bytes32 id,
address indexed penaltyAccount,
address indexed bondAccount,
uint256 rewardAmount,
uint256 bailoutAmount
);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { ISuperToken } from "./ISuperToken.sol";
/**
* @title Super token factory interface
* @author Superfluid
*/
interface ISuperTokenFactory {
/**************************************************************************
* Errors
*************************************************************************/
error SUPER_TOKEN_FACTORY_ALREADY_EXISTS(); // 0x91d67972
error SUPER_TOKEN_FACTORY_DOES_NOT_EXIST(); // 0x872cac48
error SUPER_TOKEN_FACTORY_UNINITIALIZED(); // 0x1b39b9b4
error SUPER_TOKEN_FACTORY_ONLY_HOST(); // 0x478b8e83
error SUPER_TOKEN_FACTORY_NON_UPGRADEABLE_IS_DEPRECATED(); // 0xc4901a43
error SUPER_TOKEN_FACTORY_ZERO_ADDRESS(); // 0x305c9e82
/**
* @dev Get superfluid host contract address
*/
function getHost() external view returns(address host);
/// @dev Initialize the contract
function initialize() external;
/**
* @notice Get the canonical super token logic.
*/
function getSuperTokenLogic() external view returns (ISuperToken superToken);
/**
* @dev Upgradability modes
*/
enum Upgradability {
/// Non upgradable super token, `host.updateSuperTokenLogic` will revert
NON_UPGRADABLE,
/// Upgradable through `host.updateSuperTokenLogic` operation
SEMI_UPGRADABLE,
/// Always using the latest super token logic
FULL_UPGRADABLE
}
/**
* @notice Create new super token wrapper for the underlying ERC20 token
* @param underlyingToken Underlying ERC20 token
* @param underlyingDecimals Underlying token decimals
* @param upgradability Upgradability mode
* @param name Super token name
* @param symbol Super token symbol
* @param admin Admin address
* @return superToken The deployed and initialized wrapper super token
*/
function createERC20Wrapper(
IERC20Metadata underlyingToken,
uint8 underlyingDecimals,
Upgradability upgradability,
string calldata name,
string calldata symbol,
address admin
)
external
returns (ISuperToken superToken);
/**
* @notice Create new super token wrapper for the underlying ERC20 token
* @param underlyingToken Underlying ERC20 token
* @param underlyingDecimals Underlying token decimals
* @param upgradability Upgradability mode
* @param name Super token name
* @param symbol Super token symbol
* @return superToken The deployed and initialized wrapper super token
*/
function createERC20Wrapper(
IERC20Metadata underlyingToken,
uint8 underlyingDecimals,
Upgradability upgradability,
string calldata name,
string calldata symbol
)
external
returns (ISuperToken superToken);
/**
* @notice Create new super token wrapper for the underlying ERC20 token
* @param underlyingToken Underlying ERC20 token
* @param upgradability Upgradability mode
* @param name Super token name
* @param symbol Super token symbol
* @param admin Admin address
* @return superToken The deployed and initialized wrapper super token
*/
function createERC20Wrapper(
IERC20Metadata underlyingToken,
Upgradability upgradability,
string calldata name,
string calldata symbol,
address admin
)
external
returns (ISuperToken superToken);
/**
* @notice Create new super token wrapper for the underlying ERC20 token with extra token info
* @param underlyingToken Underlying ERC20 token
* @param upgradability Upgradability mode
* @param name Super token name
* @param symbol Super token symbol
* @return superToken The deployed and initialized wrapper super token
* NOTE:
* - It assumes token provide the .decimals() function
*/
function createERC20Wrapper(
IERC20Metadata underlyingToken,
Upgradability upgradability,
string calldata name,
string calldata symbol
)
external
returns (ISuperToken superToken);
/**
* @notice Creates a wrapper super token AND sets it in the canonical list OR reverts if it already exists
* @dev salt for create2 is the keccak256 hash of abi.encode(address(_underlyingToken))
* @param _underlyingToken Underlying ERC20 token
* @return ISuperToken the created supertoken
*/
function createCanonicalERC20Wrapper(IERC20Metadata _underlyingToken)
external
returns (ISuperToken);
/**
* @notice Computes/Retrieves wrapper super token address given the underlying token address
* @dev We return from our canonical list if it already exists, otherwise we compute it
* @dev note that this function only computes addresses for SEMI_UPGRADABLE SuperTokens
* @param _underlyingToken Underlying ERC20 token address
* @return superTokenAddress Super token address
* @return isDeployed whether the super token is deployed AND set in the canonical mapping
*/
function computeCanonicalERC20WrapperAddress(address _underlyingToken)
external
view
returns (address superTokenAddress, bool isDeployed);
/**
* @notice Gets the canonical ERC20 wrapper super token address given the underlying token address
* @dev We return the address if it exists and the zero address otherwise
* @param _underlyingTokenAddress Underlying ERC20 token address
* @return superTokenAddress Super token address
*/
function getCanonicalERC20Wrapper(address _underlyingTokenAddress)
external
view
returns (address superTokenAddress);
/**
* @dev Creates a new custom super token
* @param customSuperTokenProxy address of the custom supertoken proxy
*/
function initializeCustomSuperToken(
address customSuperTokenProxy
)
external;
/**
* @dev Super token logic created event
* @param tokenLogic Token logic address
*/
event SuperTokenLogicCreated(ISuperToken indexed tokenLogic);
/**
* @dev Super token created event
* @param token Newly created super token address
*/
event SuperTokenCreated(ISuperToken indexed token);
/**
* @dev Custom super token created event
* @param token Newly created custom super token address
*/
event CustomSuperTokenCreated(ISuperToken indexed token);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperToken } from "../superfluid/ISuperToken.sol";
/**
* @title Super ETH (SETH) custom token interface
* @author Superfluid
*/
interface ISETHCustom {
// using native token
function upgradeByETH() external payable;
function upgradeByETHTo(address to) external payable;
function downgradeToETH(uint wad) external;
}
/**
* @title Super ETH (SETH) full interface
* @author Superfluid
*/
// solhint-disable-next-line no-empty-blocks
interface ISETH is ISETHCustom, ISuperToken {}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.11;
import { IPoolNFTBase } from "./IPoolNFTBase.sol";
interface IPoolAdminNFT is IPoolNFTBase {
// PoolAdminNFTData struct storage packing:
// b = bits
// WORD 1: | pool | FREE
// | 160b | 96b
// WORD 2: | admin | FREE
// | 160b | 96b
struct PoolAdminNFTData {
address pool;
address admin;
}
/// Write Functions ///
function mint(address pool) external;
function poolAdminDataByTokenId(uint256 tokenId) external view returns (PoolAdminNFTData memory data);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.11;
import { IPoolNFTBase } from "./IPoolNFTBase.sol";
interface IPoolMemberNFT is IPoolNFTBase {
// PoolMemberNFTData struct storage packing:
// b = bits
// WORD 1: | pool | FREE
// | 160b | 96b
// WORD 2: | member | FREE
// | 160b | 96b
// WORD 3: | units | FREE
// | 128b | 128b
struct PoolMemberNFTData {
address pool;
address member;
uint128 units;
}
/// Errors ///
error POOL_MEMBER_NFT_NO_ZERO_POOL();
error POOL_MEMBER_NFT_NO_ZERO_MEMBER();
error POOL_MEMBER_NFT_NO_UNITS();
error POOL_MEMBER_NFT_HAS_UNITS();
function onCreate(address pool, address member) external;
function onUpdate(address pool, address member) external;
function onDelete(address pool, address member) external;
/// View Functions ///
function poolMemberDataByTokenId(uint256 tokenId) external view returns (PoolMemberNFTData memory data);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperfluidToken } from "./ISuperfluidToken.sol";
/**
* @title Super agreement interface
* @author Superfluid
*/
interface ISuperAgreement {
/**
* @dev Get the type of the agreement class
*/
function agreementType() external view returns (bytes32);
/**
* @dev Calculate the real-time balance for the account of this agreement class
* @param account Account the state belongs to
* @param time Time used for the calculation
* @return dynamicBalance Dynamic balance portion of real-time balance of this agreement
* @return deposit Account deposit amount of this agreement
* @return owedDeposit Account owed deposit amount of this agreement
*/
function realtimeBalanceOf(
ISuperfluidToken token,
address account,
uint256 time
)
external
view
returns (
int256 dynamicBalance,
uint256 deposit,
uint256 owedDeposit
);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol";
import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol";
/**
* @title Constant Flow Agreement interface
* @author Superfluid
*/
abstract contract IConstantFlowAgreementV1 is ISuperAgreement {
/**************************************************************************
* Errors
*************************************************************************/
error CFA_ACL_NO_SENDER_CREATE(); // 0x4b993136
error CFA_ACL_NO_SENDER_UPDATE(); // 0xedfa0d3b
error CFA_ACL_OPERATOR_NO_CREATE_PERMISSIONS(); // 0xa3eab6ac
error CFA_ACL_OPERATOR_NO_UPDATE_PERMISSIONS(); // 0xac434b5f
error CFA_ACL_OPERATOR_NO_DELETE_PERMISSIONS(); // 0xe30f1bff
error CFA_ACL_FLOW_RATE_ALLOWANCE_EXCEEDED(); // 0xa0645c1f
error CFA_ACL_UNCLEAN_PERMISSIONS(); // 0x7939d66c
error CFA_ACL_NO_SENDER_FLOW_OPERATOR(); // 0xb0ed394d
error CFA_ACL_NO_NEGATIVE_ALLOWANCE(); // 0x86e0377d
error CFA_FLOW_ALREADY_EXISTS(); // 0x801b6863
error CFA_FLOW_DOES_NOT_EXIST(); // 0x5a32bf24
error CFA_INSUFFICIENT_BALANCE(); // 0xea76c9b3
error CFA_ZERO_ADDRESS_SENDER(); // 0x1ce9b067
error CFA_ZERO_ADDRESS_RECEIVER(); // 0x78e02b2a
error CFA_HOOK_OUT_OF_GAS(); // 0x9f76430b
error CFA_DEPOSIT_TOO_BIG(); // 0x752c2b9c
error CFA_FLOW_RATE_TOO_BIG(); // 0x0c9c55c1
error CFA_NON_CRITICAL_SENDER(); // 0xce11b5d1
error CFA_INVALID_FLOW_RATE(); // 0x91acad16
error CFA_NO_SELF_FLOW(); // 0xa47338ef
/// @dev ISuperAgreement.agreementType implementation
function agreementType() external override pure returns (bytes32) {
return keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1");
}
/**
* @notice Get the maximum flow rate allowed with the deposit
* @dev The deposit is clipped and rounded down
* @param deposit Deposit amount used for creating the flow
* @return flowRate The maximum flow rate
*/
function getMaximumFlowRateFromDeposit(
ISuperfluidToken token,
uint256 deposit)
external view virtual
returns (int96 flowRate);
/**
* @notice Get the deposit required for creating the flow
* @dev Calculates the deposit based on the liquidationPeriod and flowRate
* @param flowRate Flow rate to be tested
* @return deposit The deposit amount based on flowRate and liquidationPeriod
* @custom:note
* - if calculated deposit (flowRate * liquidationPeriod) is less
* than the minimum deposit, we use the minimum deposit otherwise
* we use the calculated deposit
*/
function getDepositRequiredForFlowRate(
ISuperfluidToken token,
int96 flowRate)
external view virtual
returns (uint256 deposit);
/**
* @dev Returns whether it is the patrician period based on host.getNow()
* @param account The account we are interested in
* @return isCurrentlyPatricianPeriod Whether it is currently the patrician period dictated by governance
* @return timestamp The value of host.getNow()
*/
function isPatricianPeriodNow(
ISuperfluidToken token,
address account)
external view virtual
returns (bool isCurrentlyPatricianPeriod, uint256 timestamp);
/**
* @dev Returns whether it is the patrician period based on timestamp
* @param account The account we are interested in
* @param timestamp The timestamp we are interested in observing the result of isPatricianPeriod
* @return bool Whether it is currently the patrician period dictated by governance
*/
function isPatricianPeriod(
ISuperfluidToken token,
address account,
uint256 timestamp
)
public view virtual
returns (bool);
/**
* @dev msgSender from `ctx` updates permissions for the `flowOperator` with `flowRateAllowance`
* @param token Super token address
* @param flowOperator The permission grantee address
* @param permissions A bitmask representation of the granted permissions
* @param flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down)
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*/
function updateFlowOperatorPermissions(
ISuperfluidToken token,
address flowOperator,
uint8 permissions,
int96 flowRateAllowance,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @notice msgSender from `ctx` increases flow rate allowance for the `flowOperator` by `addedFlowRateAllowance`
* @dev if `addedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE
* @param token Super token address
* @param flowOperator The permission grantee address
* @param addedFlowRateAllowance The flow rate allowance delta
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
* @return newCtx The new context bytes
*/
function increaseFlowRateAllowance(
ISuperfluidToken token,
address flowOperator,
int96 addedFlowRateAllowance,
bytes calldata ctx
) external virtual returns(bytes memory newCtx);
/**
* @dev msgSender from `ctx` decreases flow rate allowance for the `flowOperator` by `subtractedFlowRateAllowance`
* @dev if `subtractedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE
* @param token Super token address
* @param flowOperator The permission grantee address
* @param subtractedFlowRateAllowance The flow rate allowance delta
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
* @return newCtx The new context bytes
*/
function decreaseFlowRateAllowance(
ISuperfluidToken token,
address flowOperator,
int96 subtractedFlowRateAllowance,
bytes calldata ctx
) external virtual returns(bytes memory newCtx);
/**
* @dev msgSender from `ctx` increases flow rate allowance for the `flowOperator` by `addedFlowRateAllowance`
* @dev if `addedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE
* @param token Super token address
* @param flowOperator The permission grantee address
* @param permissionsToAdd A bitmask representation of the granted permissions to add as a delta
* @param addedFlowRateAllowance The flow rate allowance delta
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
* @return newCtx The new context bytes
*/
function increaseFlowRateAllowanceWithPermissions(
ISuperfluidToken token,
address flowOperator,
uint8 permissionsToAdd,
int96 addedFlowRateAllowance,
bytes calldata ctx
) external virtual returns(bytes memory newCtx);
/**
* @dev msgSender from `ctx` decreases flow rate allowance for the `flowOperator` by `subtractedFlowRateAllowance`
* @dev if `subtractedFlowRateAllowance` is negative, we revert with CFA_ACL_NO_NEGATIVE_ALLOWANCE
* @param token Super token address
* @param flowOperator The permission grantee address
* @param permissionsToRemove A bitmask representation of the granted permissions to remove as a delta
* @param subtractedFlowRateAllowance The flow rate allowance delta
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
* @return newCtx The new context bytes
*/
function decreaseFlowRateAllowanceWithPermissions(
ISuperfluidToken token,
address flowOperator,
uint8 permissionsToRemove,
int96 subtractedFlowRateAllowance,
bytes calldata ctx
) external virtual returns(bytes memory newCtx);
/**
* @dev msgSender from `ctx` grants `flowOperator` all permissions with flowRateAllowance as type(int96).max
* @param token Super token address
* @param flowOperator The permission grantee address
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*/
function authorizeFlowOperatorWithFullControl(
ISuperfluidToken token,
address flowOperator,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @notice msgSender from `ctx` revokes `flowOperator` create/update/delete permissions
* @dev `permissions` and `flowRateAllowance` will both be set to 0
* @param token Super token address
* @param flowOperator The permission grantee address
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*/
function revokeFlowOperatorWithFullControl(
ISuperfluidToken token,
address flowOperator,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @notice Get the permissions of a flow operator between `sender` and `flowOperator` for `token`
* @param token Super token address
* @param sender The permission granter address
* @param flowOperator The permission grantee address
* @return flowOperatorId The keccak256 hash of encoded string "flowOperator", sender and flowOperator
* @return permissions A bitmask representation of the granted permissions
* @return flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down)
*/
function getFlowOperatorData(
ISuperfluidToken token,
address sender,
address flowOperator
)
public view virtual
returns (
bytes32 flowOperatorId,
uint8 permissions,
int96 flowRateAllowance
);
/**
* @notice Get flow operator using flowOperatorId
* @param token Super token address
* @param flowOperatorId The keccak256 hash of encoded string "flowOperator", sender and flowOperator
* @return permissions A bitmask representation of the granted permissions
* @return flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down)
*/
function getFlowOperatorDataByID(
ISuperfluidToken token,
bytes32 flowOperatorId
)
external view virtual
returns (
uint8 permissions,
int96 flowRateAllowance
);
/**
* @notice Create a flow betwen ctx.msgSender and receiver
* @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver
* @param token Super token address
* @param receiver Flow receiver address
* @param flowRate New flow rate in amount per second
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* - AgreementCreated
* - agreementId - can be used in getFlowByID
* - agreementData - abi.encode(address flowSender, address flowReceiver)
*
* @custom:note
* - A deposit is taken as safety margin for the solvency agents
* - A extra gas fee may be taken to pay for solvency agent liquidations
*/
function createFlow(
ISuperfluidToken token,
address receiver,
int96 flowRate,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @notice Create a flow between sender and receiver
* @dev A flow created by an approved flow operator (see above for details on callbacks)
* @param token Super token address
* @param sender Flow sender address (has granted permissions)
* @param receiver Flow receiver address
* @param flowRate New flow rate in amount per second
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*/
function createFlowByOperator(
ISuperfluidToken token,
address sender,
address receiver,
int96 flowRate,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @notice Update the flow rate between ctx.msgSender and receiver
* @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver
* @param token Super token address
* @param receiver Flow receiver address
* @param flowRate New flow rate in amount per second
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* - AgreementUpdated
* - agreementId - can be used in getFlowByID
* - agreementData - abi.encode(address flowSender, address flowReceiver)
*
* @custom:note
* - Only the flow sender may update the flow rate
* - Even if the flow rate is zero, the flow is not deleted
* from the system
* - Deposit amount will be adjusted accordingly
* - No new gas fee is charged
*/
function updateFlow(
ISuperfluidToken token,
address receiver,
int96 flowRate,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @notice Update a flow between sender and receiver
* @dev A flow updated by an approved flow operator (see above for details on callbacks)
* @param token Super token address
* @param sender Flow sender address (has granted permissions)
* @param receiver Flow receiver address
* @param flowRate New flow rate in amount per second
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*/
function updateFlowByOperator(
ISuperfluidToken token,
address sender,
address receiver,
int96 flowRate,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @dev Get the flow data between `sender` and `receiver` of `token`
* @param token Super token address
* @param sender Flow sender
* @param receiver Flow receiver
* @return timestamp Timestamp of when the flow is updated
* @return flowRate The flow rate
* @return deposit The amount of deposit the flow
* @return owedDeposit The amount of owed deposit of the flow
*/
function getFlow(
ISuperfluidToken token,
address sender,
address receiver
)
external view virtual
returns (
uint256 timestamp,
int96 flowRate,
uint256 deposit,
uint256 owedDeposit
);
/**
* @notice Get flow data using agreementId
* @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver
* @param token Super token address
* @param agreementId The agreement ID
* @return timestamp Timestamp of when the flow is updated
* @return flowRate The flow rate
* @return deposit The deposit amount of the flow
* @return owedDeposit The owed deposit amount of the flow
*/
function getFlowByID(
ISuperfluidToken token,
bytes32 agreementId
)
external view virtual
returns (
uint256 timestamp,
int96 flowRate,
uint256 deposit,
uint256 owedDeposit
);
/**
* @dev Get the aggregated flow info of the account
* @param token Super token address
* @param account Account for the query
* @return timestamp Timestamp of when a flow was last updated for account
* @return flowRate The net flow rate of token for account
* @return deposit The sum of all deposits for account's flows
* @return owedDeposit The sum of all owed deposits for account's flows
*/
function getAccountFlowInfo(
ISuperfluidToken token,
address account
)
external view virtual
returns (
uint256 timestamp,
int96 flowRate,
uint256 deposit,
uint256 owedDeposit);
/**
* @dev Get the net flow rate of the account
* @param token Super token address
* @param account Account for the query
* @return flowRate Net flow rate
*/
function getNetFlow(
ISuperfluidToken token,
address account
)
external view virtual
returns (int96 flowRate);
/**
* @notice Delete the flow between sender and receiver
* @dev flowId (agreementId) is the keccak256 hash of encoded sender and receiver
* @param token Super token address
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
* @param receiver Flow receiver address
*
* @custom:callbacks
* - AgreementTerminated
* - agreementId - can be used in getFlowByID
* - agreementData - abi.encode(address flowSender, address flowReceiver)
*
* @custom:note
* - Both flow sender and receiver may delete the flow
* - If Sender account is insolvent or in critical state, a solvency agent may
* also terminate the agreement
* - Gas fee may be returned to the sender
*/
function deleteFlow(
ISuperfluidToken token,
address sender,
address receiver,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @notice Delete the flow between sender and receiver
* @dev A flow deleted by an approved flow operator (see above for details on callbacks)
* @param token Super token address
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
* @param receiver Flow receiver address
*/
function deleteFlowByOperator(
ISuperfluidToken token,
address sender,
address receiver,
bytes calldata ctx
)
external virtual
returns(bytes memory newCtx);
/**
* @dev Flow operator updated event
* @param token Super token address
* @param sender Flow sender address
* @param flowOperator Flow operator address
* @param permissions Octo bitmask representation of permissions
* @param flowRateAllowance The flow rate allowance the `flowOperator` is granted (only goes down)
*/
event FlowOperatorUpdated(
ISuperfluidToken indexed token,
address indexed sender,
address indexed flowOperator,
uint8 permissions,
int96 flowRateAllowance
);
/**
* @dev Flow updated event
* @param token Super token address
* @param sender Flow sender address
* @param receiver Flow recipient address
* @param flowRate Flow rate in amount per second for this flow
* @param totalSenderFlowRate Total flow rate in amount per second for the sender
* @param totalReceiverFlowRate Total flow rate in amount per second for the receiver
* @param userData The user provided data
*
*/
event FlowUpdated(
ISuperfluidToken indexed token,
address indexed sender,
address indexed receiver,
int96 flowRate,
int256 totalSenderFlowRate,
int256 totalReceiverFlowRate,
bytes userData
);
/**
* @dev Flow updated extension event
* @param flowOperator Flow operator address - the Context.msgSender
* @param deposit The deposit amount for the stream
*/
event FlowUpdatedExtension(
address indexed flowOperator,
uint256 deposit
);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperAgreement } from "../superfluid/ISuperAgreement.sol";
import { ISuperfluidToken } from "../superfluid/ISuperfluidToken.sol";
/**
* @title [DEPRECATED] Instant Distribution Agreement interface
* @custom:deprecated Use IGeneralDistributionAgreementV1 instead
* @author Superfluid
*
* @notice
* - A publisher can create as many as indices as possibly identifiable with `indexId`.
* - `indexId` is deliberately limited to 32 bits, to avoid the chance for sha-3 collision.
* Despite knowing sha-3 collision is only theoretical.
* - A publisher can create a subscription to an index for any subscriber.
* - A subscription consists of:
* - The index it subscribes to.
* - Number of units subscribed.
* - An index consists of:
* - Current value as `uint128 indexValue`.
* - Total units of the approved subscriptions as `uint128 totalUnitsApproved`.
* - Total units of the non approved subscription as `uint128 totalUnitsPending`.
* - A publisher can update an index with a new value that doesn't decrease.
* - A publisher can update a subscription with any number of units.
* - A publisher or a subscriber can delete a subscription and reset its units to zero.
* - A subscriber must approve the index in order to receive distributions from the publisher
* each time the index is updated.
* - The amount distributed is $$\Delta{index} * units$$
* - Distributions to a non approved subscription stays in the publisher's deposit until:
* - the subscriber approves the subscription (side effect),
* - the publisher updates the subscription (side effect),
* - the subscriber deletes the subscription even if it is never approved (side effect),
* - or the subscriber can explicitly claim them.
*/
abstract contract IInstantDistributionAgreementV1 is ISuperAgreement {
/**************************************************************************
* Errors
*************************************************************************/
error IDA_INDEX_SHOULD_GROW(); // 0xcfdca725
error IDA_OPERATION_NOT_ALLOWED(); // 0x92da6d17
error IDA_INDEX_ALREADY_EXISTS(); // 0x5c02a517
error IDA_INDEX_DOES_NOT_EXIST(); // 0xedeaa63b
error IDA_SUBSCRIPTION_DOES_NOT_EXIST(); // 0xb6c8c980
error IDA_SUBSCRIPTION_ALREADY_APPROVED(); // 0x3eb2f849
error IDA_SUBSCRIPTION_IS_NOT_APPROVED(); // 0x37412573
error IDA_INSUFFICIENT_BALANCE(); // 0x16e759bb
error IDA_ZERO_ADDRESS_SUBSCRIBER(); // 0xc90a4674
/// @dev ISuperAgreement.agreementType implementation
function agreementType() external override pure returns (bytes32) {
return keccak256("org.superfluid-finance.agreements.InstantDistributionAgreement.v1");
}
/**************************************************************************
* Index operations
*************************************************************************/
/**
* @dev Create a new index for the publisher
* @param token Super token address
* @param indexId Id of the index
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* None
*/
function createIndex(
ISuperfluidToken token,
uint32 indexId,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**
* @dev Index created event
* @param token Super token address
* @param publisher Index creator and publisher
* @param indexId The specified indexId of the newly created index
* @param userData The user provided data
*/
event IndexCreated(
ISuperfluidToken indexed token,
address indexed publisher,
uint32 indexed indexId,
bytes userData);
/**
* @dev Query the data of a index
* @param token Super token address
* @param publisher The publisher of the index
* @param indexId Id of the index
* @return exist Does the index exist
* @return indexValue Value of the current index
* @return totalUnitsApproved Total units approved for the index
* @return totalUnitsPending Total units pending approval for the index
*/
function getIndex(
ISuperfluidToken token,
address publisher,
uint32 indexId)
external
view
virtual
returns(
bool exist,
uint128 indexValue,
uint128 totalUnitsApproved,
uint128 totalUnitsPending);
/**
* @dev Calculate actual distribution amount
* @param token Super token address
* @param publisher The publisher of the index
* @param indexId Id of the index
* @param amount The amount of tokens desired to be distributed
* @return actualAmount The amount to be distributed after ensuring no rounding errors
* @return newIndexValue The index value given the desired amount of tokens to be distributed
*/
function calculateDistribution(
ISuperfluidToken token,
address publisher,
uint32 indexId,
uint256 amount)
external view
virtual
returns(
uint256 actualAmount,
uint128 newIndexValue);
/**
* @dev Update index value of an index
* @param token Super token address
* @param indexId Id of the index
* @param indexValue Value of the index
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* None
*/
function updateIndex(
ISuperfluidToken token,
uint32 indexId,
uint128 indexValue,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**
* @dev Index updated event
* @param token Super token address
* @param publisher Index updater and publisher
* @param indexId The specified indexId of the updated index
* @param oldIndexValue The previous index value
* @param newIndexValue The updated index value
* @param totalUnitsPending The total units pending when the indexValue was updated
* @param totalUnitsApproved The total units approved when the indexValue was updated
* @param userData The user provided data
*/
event IndexUpdated(
ISuperfluidToken indexed token,
address indexed publisher,
uint32 indexed indexId,
uint128 oldIndexValue,
uint128 newIndexValue,
uint128 totalUnitsPending,
uint128 totalUnitsApproved,
bytes userData);
/**
* @dev Distribute tokens through the index
* @param token Super token address
* @param indexId Id of the index
* @param amount The amount of tokens desired to be distributed
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:note
* - This is a convenient version of updateIndex. It adds to the index
* a delta that equals to `amount / totalUnits`
* - The actual amount distributed could be obtained via
* `calculateDistribution`. This is due to precision error with index
* value and units data range
*
* @custom:callbacks
* None
*/
function distribute(
ISuperfluidToken token,
uint32 indexId,
uint256 amount,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**************************************************************************
* Subscription operations
*************************************************************************/
/**
* @dev Approve the subscription of an index
* @param token Super token address
* @param publisher The publisher of the index
* @param indexId Id of the index
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* - if subscription exist
* - AgreementCreated callback to the publisher:
* - agreementId is for the subscription
* - if subscription does not exist
* - AgreementUpdated callback to the publisher:
* - agreementId is for the subscription
*/
function approveSubscription(
ISuperfluidToken token,
address publisher,
uint32 indexId,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**
* @dev Index subscribed event
* @param token Super token address
* @param publisher Index publisher
* @param indexId The specified indexId
* @param subscriber The approved subscriber
* @param userData The user provided data
*/
event IndexSubscribed(
ISuperfluidToken indexed token,
address indexed publisher,
uint32 indexed indexId,
address subscriber,
bytes userData);
/**
* @dev Subscription approved event
* @param token Super token address
* @param subscriber The approved subscriber
* @param publisher Index publisher
* @param indexId The specified indexId
* @param userData The user provided data
*/
event SubscriptionApproved(
ISuperfluidToken indexed token,
address indexed subscriber,
address publisher,
uint32 indexId,
bytes userData);
/**
* @notice Revoke the subscription of an index
* @dev "Unapproves" the subscription and moves approved units to pending
* @param token Super token address
* @param publisher The publisher of the index
* @param indexId Id of the index
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* - AgreementUpdated callback to the publisher:
* - agreementId is for the subscription
*/
function revokeSubscription(
ISuperfluidToken token,
address publisher,
uint32 indexId,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**
* @dev Index unsubscribed event
* @param token Super token address
* @param publisher Index publisher
* @param indexId The specified indexId
* @param subscriber The unsubscribed subscriber
* @param userData The user provided data
*/
event IndexUnsubscribed(
ISuperfluidToken indexed token,
address indexed publisher,
uint32 indexed indexId,
address subscriber,
bytes userData);
/**
* @dev Subscription approved event
* @param token Super token address
* @param subscriber The approved subscriber
* @param publisher Index publisher
* @param indexId The specified indexId
* @param userData The user provided data
*/
event SubscriptionRevoked(
ISuperfluidToken indexed token,
address indexed subscriber,
address publisher,
uint32 indexId,
bytes userData);
/**
* @dev Update the nuber of units of a subscription
* @param token Super token address
* @param indexId Id of the index
* @param subscriber The subscriber of the index
* @param units Number of units of the subscription
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* - if subscription exist
* - AgreementCreated callback to the subscriber:
* - agreementId is for the subscription
* - if subscription does not exist
* - AgreementUpdated callback to the subscriber:
* - agreementId is for the subscription
*/
function updateSubscription(
ISuperfluidToken token,
uint32 indexId,
address subscriber,
uint128 units,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**
* @dev Index units updated event
* @param token Super token address
* @param publisher Index publisher
* @param indexId The specified indexId
* @param subscriber The subscriber units updated
* @param units The new units amount
* @param userData The user provided data
*/
event IndexUnitsUpdated(
ISuperfluidToken indexed token,
address indexed publisher,
uint32 indexed indexId,
address subscriber,
uint128 units,
bytes userData);
/**
* @dev Subscription units updated event
* @param token Super token address
* @param subscriber The subscriber units updated
* @param indexId The specified indexId
* @param publisher Index publisher
* @param units The new units amount
* @param userData The user provided data
*/
event SubscriptionUnitsUpdated(
ISuperfluidToken indexed token,
address indexed subscriber,
address publisher,
uint32 indexId,
uint128 units,
bytes userData);
/**
* @dev Get data of a subscription
* @param token Super token address
* @param publisher The publisher of the index
* @param indexId Id of the index
* @param subscriber The subscriber of the index
* @return exist Does the subscription exist?
* @return approved Is the subscription approved?
* @return units Units of the suscription
* @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription
*/
function getSubscription(
ISuperfluidToken token,
address publisher,
uint32 indexId,
address subscriber)
external
view
virtual
returns(
bool exist,
bool approved,
uint128 units,
uint256 pendingDistribution
);
/**
* @notice Get data of a subscription by agreement ID
* @dev indexId (agreementId) is the keccak256 hash of encodePacked("publisher", publisher, indexId)
* @param token Super token address
* @param agreementId The agreement ID
* @return publisher The publisher of the index
* @return indexId Id of the index
* @return approved Is the subscription approved?
* @return units Units of the suscription
* @return pendingDistribution Pending amount of tokens to be distributed for unapproved subscription
*/
function getSubscriptionByID(
ISuperfluidToken token,
bytes32 agreementId)
external
view
virtual
returns(
address publisher,
uint32 indexId,
bool approved,
uint128 units,
uint256 pendingDistribution
);
/**
* @dev List subscriptions of an user
* @param token Super token address
* @param subscriber The subscriber's address
* @return publishers Publishers of the subcriptions
* @return indexIds Indexes of the subscriptions
* @return unitsList Units of the subscriptions
*/
function listSubscriptions(
ISuperfluidToken token,
address subscriber)
external
view
virtual
returns(
address[] memory publishers,
uint32[] memory indexIds,
uint128[] memory unitsList);
/**
* @dev Delete the subscription of an user
* @param token Super token address
* @param publisher The publisher of the index
* @param indexId Id of the index
* @param subscriber The subscriber's address
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:callbacks
* - if the subscriber called it
* - AgreementTerminated callback to the publsiher:
* - agreementId is for the subscription
* - if the publisher called it
* - AgreementTerminated callback to the subscriber:
* - agreementId is for the subscription
*/
function deleteSubscription(
ISuperfluidToken token,
address publisher,
uint32 indexId,
address subscriber,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**
* @dev Claim pending distributions
* @param token Super token address
* @param publisher The publisher of the index
* @param indexId Id of the index
* @param subscriber The subscriber's address
* @param ctx Context bytes (see ISuperfluid.sol for Context struct)
*
* @custom:note The subscription should not be approved yet
*
* @custom:callbacks
* - AgreementUpdated callback to the publisher:
* - agreementId is for the subscription
*/
function claim(
ISuperfluidToken token,
address publisher,
uint32 indexId,
address subscriber,
bytes calldata ctx)
external
virtual
returns(bytes memory newCtx);
/**
* @dev Index distribution claimed event
* @param token Super token address
* @param publisher Index publisher
* @param indexId The specified indexId
* @param subscriber The subscriber units updated
* @param amount The pending amount claimed
*/
event IndexDistributionClaimed(
ISuperfluidToken indexed token,
address indexed publisher,
uint32 indexed indexId,
address subscriber,
uint256 amount);
/**
* @dev Subscription distribution claimed event
* @param token Super token address
* @param subscriber The subscriber units updated
* @param publisher Index publisher
* @param indexId The specified indexId
* @param amount The pending amount claimed
*/
event SubscriptionDistributionClaimed(
ISuperfluidToken indexed token,
address indexed subscriber,
address publisher,
uint32 indexId,
uint256 amount);
}// SPDX-License-Identifier: AGPLv3
pragma solidity >=0.8.4;
import { ISuperAgreement } from "../../superfluid/ISuperAgreement.sol";
import { ISuperfluidToken } from "../../superfluid/ISuperfluidToken.sol";
import { ISuperfluidPool } from "../../agreements/gdav1/ISuperfluidPool.sol";
struct PoolConfig {
/// @dev if true, the pool members can transfer their owned units
/// else, only the pool admin can manipulate the units for pool members
bool transferabilityForUnitsOwner;
/// @dev if true, anyone can execute distributions via the pool
/// else, only the pool admin can execute distributions via the pool
bool distributionFromAnyAddress;
}
struct PoolERC20Metadata {
string name;
string symbol;
uint8 decimals;
}
/**
* @title General Distribution Agreement interface
* @author Superfluid
*/
abstract contract IGeneralDistributionAgreementV1 is ISuperAgreement {
// Custom Errors
error GDA_DISTRIBUTE_FOR_OTHERS_NOT_ALLOWED(); // 0xf67d263e
error GDA_DISTRIBUTE_FROM_ANY_ADDRESS_NOT_ALLOWED(); // 0x7761a5e5
error GDA_FLOW_DOES_NOT_EXIST(); // 0x29f4697e
error GDA_NON_CRITICAL_SENDER(); // 0x666f381d
error GDA_INSUFFICIENT_BALANCE(); // 0x33115c3f
error GDA_NO_NEGATIVE_FLOW_RATE(); // 0x15f25663
error GDA_ADMIN_CANNOT_BE_POOL(); // 0x9ab88a26
error GDA_NOT_POOL_ADMIN(); // 0x3a87e565
error GDA_NO_ZERO_ADDRESS_ADMIN(); // 0x82c5d837
error GDA_ONLY_SUPER_TOKEN_POOL(); // 0x90028c37
// Events
event InstantDistributionUpdated(
ISuperfluidToken indexed token,
ISuperfluidPool indexed pool,
address indexed distributor,
address operator,
uint256 requestedAmount,
uint256 actualAmount,
bytes userData
);
event FlowDistributionUpdated(
ISuperfluidToken indexed token,
ISuperfluidPool indexed pool,
address indexed distributor,
// operator's have permission to liquidate critical flows
// on behalf of others
address operator,
int96 oldFlowRate,
int96 newDistributorToPoolFlowRate,
int96 newTotalDistributionFlowRate,
address adjustmentFlowRecipient,
int96 adjustmentFlowRate,
bytes userData
);
event PoolCreated(ISuperfluidToken indexed token, address indexed admin, ISuperfluidPool pool);
event PoolConnectionUpdated(
ISuperfluidToken indexed token,
ISuperfluidPool indexed pool,
address indexed account,
bool connected,
bytes userData
);
event BufferAdjusted(
ISuperfluidToken indexed token,
ISuperfluidPool indexed pool,
address indexed from,
int256 bufferDelta,
uint256 newBufferAmount,
uint256 totalBufferAmount
);
/// @dev ISuperAgreement.agreementType implementation
function agreementType() external pure override returns (bytes32) {
return keccak256("org.superfluid-finance.agreements.GeneralDistributionAgreement.v1");
}
/// @dev Gets the GDA net flow rate of `account` for `token`.
/// @param token The token address
/// @param account The account address
/// @return net flow rate
function getNetFlow(ISuperfluidToken token, address account) external view virtual returns (int96);
/// @notice Gets the GDA flow rate of `from` to `to` for `token`.
/// @dev This is primarily used to get the flow distribution flow rate from a distributor to a pool or the
/// adjustment flow rate of a pool.
/// @param token The token address
/// @param from The sender address
/// @param to The receiver address (the pool)
/// @return flow rate
function getFlowRate(ISuperfluidToken token, address from, ISuperfluidPool to)
external
view
virtual
returns (int96);
/// @dev Gets the GDA flow data between `from` and `to` of `token`
/// @param token The token address
/// @param from The sender address
/// @param to The receiver address
/// @return lastUpdated The timestamp of when the flow was last updated
/// @return flowRate The flow rate
/// @return deposit The amount of deposit the flow
function getFlow(ISuperfluidToken token, address from, ISuperfluidPool to)
external
view
virtual
returns (uint256 lastUpdated, int96 flowRate, uint256 deposit);
/// @dev Gets the aggregated GDA flow info of `account` for `token`
/// @param token The token address
/// @param account The account address
/// @return timestamp The timestamp of when the flow was last updated for account
/// @return flowRate The net flow rate of token for account
/// @return deposit The sum of all deposits for account's flows
function getAccountFlowInfo(ISuperfluidToken token, address account)
external
view
virtual
returns (uint256 timestamp, int96 flowRate, uint256 deposit);
/// @notice Executes an optimistic estimation of what the actual flow distribution flow rate may be.
/// The actual flow distribution flow rate is the flow rate that will be sent from `from`.
/// NOTE: this is only precise in an atomic transaction. DO NOT rely on this if querying off-chain.
/// @dev The difference between the requested flow rate and the actual flow rate is the adjustment flow rate,
/// this adjustment flow rate goes to the pool admin.
/// @param token The token address
/// @param from The sender address
/// @param to The pool address
/// @param requestedFlowRate The requested flow rate
/// @return actualFlowRate and totalDistributionFlowRate
function estimateFlowDistributionActualFlowRate(
ISuperfluidToken token,
address from,
ISuperfluidPool to,
int96 requestedFlowRate
) external view virtual returns (int96 actualFlowRate, int96 totalDistributionFlowRate);
/// @notice Executes an optimistic estimation of what the actual amount distributed may be.
/// The actual amount distributed is the amount that will be sent from `from`.
/// NOTE: this is only precise in an atomic transaction. DO NOT rely on this if querying off-chain.
/// @dev The difference between the requested amount and the actual amount is the adjustment amount.
/// @param token The token address
/// @param from The sender address
/// @param to The pool address
/// @param requestedAmount The requested amount
/// @return actualAmount
function estimateDistributionActualAmount(
ISuperfluidToken token,
address from,
ISuperfluidPool to,
uint256 requestedAmount
) external view virtual returns (uint256 actualAmount);
/// @notice Gets the adjustment flow rate of `pool` for `token`.
/// @param pool The pool address
/// @return adjustment flow rate
function getPoolAdjustmentFlowRate(address pool) external view virtual returns (int96);
////////////////////////////////////////////////////////////////////////////////
// Pool Operations
////////////////////////////////////////////////////////////////////////////////
/// @notice Creates a new pool for `token` where the admin is `admin`.
/// @param token The token address
/// @param admin The admin of the pool
/// @param poolConfig The pool configuration (see PoolConfig struct)
function createPool(ISuperfluidToken token, address admin, PoolConfig memory poolConfig)
external
virtual
returns (ISuperfluidPool pool);
/// @notice Creates a new pool for `token` with custom ERC20 metadata.
/// @param token The token address
/// @param admin The admin of the pool
/// @param poolConfig The pool configuration (see PoolConfig struct)
/// @param poolERC20Metadata The pool ERC20 metadata (see PoolERC20Metadata struct)
/// @return pool The pool address
function createPoolWithCustomERC20Metadata(
ISuperfluidToken token,
address admin,
PoolConfig memory poolConfig,
PoolERC20Metadata memory poolERC20Metadata
) external virtual returns (ISuperfluidPool pool);
function updateMemberUnits(ISuperfluidPool pool, address memberAddress, uint128 newUnits, bytes calldata ctx)
external
virtual
returns (bytes memory newCtx);
function claimAll(ISuperfluidPool pool, address memberAddress, bytes calldata ctx)
external
virtual
returns (bytes memory newCtx);
/// @notice Connects `msg.sender` to `pool`.
/// @dev This is used to connect a pool to the GDA.
/// @param pool The pool address
/// @param ctx Context bytes (see ISuperfluid.sol for Context struct)
/// @return newCtx the new context bytes
function connectPool(ISuperfluidPool pool, bytes calldata ctx) external virtual returns (bytes memory newCtx);
/// @notice Disconnects `msg.sender` from `pool`.
/// @dev This is used to disconnect a pool from the GDA.
/// @param pool The pool address
/// @param ctx Context bytes (see ISuperfluidPoolAdmin for Context struct)
/// @return newCtx the new context bytes
function disconnectPool(ISuperfluidPool pool, bytes calldata ctx) external virtual returns (bytes memory newCtx);
/// @notice Checks whether `account` is a pool.
/// @param token The token address
/// @param account The account address
/// @return true if `account` is a pool
function isPool(ISuperfluidToken token, address account) external view virtual returns (bool);
/// Check if an address is connected to the pool
function isMemberConnected(ISuperfluidPool pool, address memberAddr) external view virtual returns (bool);
/// Get pool adjustment flow information: (recipient, flowHash, flowRate)
function getPoolAdjustmentFlowInfo(ISuperfluidPool pool) external view virtual returns (address, bytes32, int96);
////////////////////////////////////////////////////////////////////////////////
// Agreement Operations
////////////////////////////////////////////////////////////////////////////////
/// @notice Tries to distribute `requestedAmount` of `token` from `from` to `pool`.
/// @dev NOTE: The actual amount distributed may differ.
/// @param token The token address
/// @param from The sender address
/// @param pool The pool address
/// @param requestedAmount The requested amount
/// @param ctx Context bytes (see ISuperfluidPool for Context struct)
/// @return newCtx the new context bytes
function distribute(
ISuperfluidToken token,
address from,
ISuperfluidPool pool,
uint256 requestedAmount,
bytes calldata ctx
) external virtual returns (bytes memory newCtx);
/// @notice Tries to distributeFlow `requestedFlowRate` of `token` from `from` to `pool`.
/// @dev NOTE: The actual distribution flow rate may differ.
/// @param token The token address
/// @param from The sender address
/// @param pool The pool address
/// @param requestedFlowRate The requested flow rate
/// @param ctx Context bytes (see ISuperfluidPool for Context struct)
/// @return newCtx the new context bytes
function distributeFlow(
ISuperfluidToken token,
address from,
ISuperfluidPool pool,
int96 requestedFlowRate,
bytes calldata ctx
) external virtual returns (bytes memory newCtx);
////////////////////////////////////////////////////////////////////////////////
// Solvency Functions
////////////////////////////////////////////////////////////////////////////////
/**
* @dev Returns whether it is the patrician period based on host.getNow()
* @param account The account we are interested in
* @return isCurrentlyPatricianPeriod Whether it is currently the patrician period dictated by governance
* @return timestamp The value of host.getNow()
*/
function isPatricianPeriodNow(ISuperfluidToken token, address account)
external
view
virtual
returns (bool isCurrentlyPatricianPeriod, uint256 timestamp);
/**
* @dev Returns whether it is the patrician period based on timestamp
* @param account The account we are interested in
* @param timestamp The timestamp we are interested in observing the result of isPatricianPeriod
* @return bool Whether it is currently the patrician period dictated by governance
*/
function isPatricianPeriod(ISuperfluidToken token, address account, uint256 timestamp)
public
view
virtual
returns (bool);
}// SPDX-License-Identifier: AGPLv3
pragma solidity >=0.8.4;
import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { ISuperfluidToken } from "../../superfluid/ISuperfluidToken.sol";
/**
* @dev The interface for any super token pool regardless of the distribution schemes.
*/
interface ISuperfluidPool is IERC20, IERC20Metadata {
// Custom Errors
error SUPERFLUID_POOL_INVALID_TIME(); // 0x83c35016
error SUPERFLUID_POOL_NO_POOL_MEMBERS(); // 0xe10f405a
error SUPERFLUID_POOL_NO_ZERO_ADDRESS(); // 0x54eb6ee6
error SUPERFLUID_POOL_NOT_POOL_ADMIN_OR_GDA(); // 0x1c5fbdcb
error SUPERFLUID_POOL_NOT_GDA(); // 0xfcbe3f9e
error SUPERFLUID_POOL_TRANSFER_UNITS_NOT_ALLOWED(); // 0x2285efba
error SUPERFLUID_POOL_SELF_TRANSFER_NOT_ALLOWED(); // 0xceddc0be
// Events
event MemberUnitsUpdated(
ISuperfluidToken indexed token, address indexed member, uint128 oldUnits, uint128 newUnits
);
event DistributionClaimed(
ISuperfluidToken indexed token, address indexed member, int256 claimedAmount, int256 totalClaimed
);
/// @notice A boolean indicating whether pool members can transfer their units
function transferabilityForUnitsOwner() external view returns (bool);
/// @notice A boolean indicating whether addresses other than the pool admin can distribute via the pool
function distributionFromAnyAddress() external view returns (bool);
/// @notice The pool admin
/// @dev The admin is the creator of the pool and has permissions to update member units
/// and is the recipient of the adjustment flow rate
function admin() external view returns (address);
/// @notice The SuperToken for the pool
function superToken() external view returns (ISuperfluidToken);
/// @notice The total units of the pool
function getTotalUnits() external view returns (uint128);
/// @notice The total number of units of connected members
function getTotalConnectedUnits() external view returns (uint128);
/// @notice The total number of units of disconnected members
function getTotalDisconnectedUnits() external view returns (uint128);
/// @notice The total number of units for `memberAddr`
/// @param memberAddr The address of the member
function getUnits(address memberAddr) external view returns (uint128);
/// @notice The total flow rate of the pool
function getTotalFlowRate() external view returns (int96);
/// @notice The flow rate of the connected members
function getTotalConnectedFlowRate() external view returns (int96);
/// @notice The flow rate of the disconnected members
function getTotalDisconnectedFlowRate() external view returns (int96);
/// @notice The balance of all the disconnected members at `time`
/// @param time The time to query
function getDisconnectedBalance(uint32 time) external view returns (int256 balance);
/// @notice The total amount received by `memberAddr` in the pool
/// @param memberAddr The address of the member
/// @return totalAmountReceived The total amount received by the member
function getTotalAmountReceivedByMember(address memberAddr) external view returns (uint256 totalAmountReceived);
/// @notice The flow rate a member is receiving from the pool
/// @param memberAddr The address of the member
function getMemberFlowRate(address memberAddr) external view returns (int96);
/// @notice The claimable balance for `memberAddr` at `time` in the pool
/// @param memberAddr The address of the member
/// @param time The time to query
function getClaimable(address memberAddr, uint32 time) external view returns (int256);
/// @notice The claimable balance for `memberAddr` at `block.timestamp` in the pool
/// @param memberAddr The address of the member
function getClaimableNow(address memberAddr) external view returns (int256 claimableBalance, uint256 timestamp);
/// @notice Sets `memberAddr` ownedUnits to `newUnits`
/// @param memberAddr The address of the member
/// @param newUnits The new units for the member
function updateMemberUnits(address memberAddr, uint128 newUnits) external returns (bool);
/// @notice Claims the claimable balance for `memberAddr` at `block.timestamp`
/// @param memberAddr The address of the member
function claimAll(address memberAddr) external returns (bool);
/// @notice Claims the claimable balance for `msg.sender` at `block.timestamp`
function claimAll() external returns (bool);
/// @notice Increases the allowance of `spender` by `addedValue`
/// @param spender The address of the spender
/// @param addedValue The amount to increase the allowance by
/// @return true if successful
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
/// @notice Decreases the allowance of `spender` by `subtractedValue`
/// @param spender The address of the spender
/// @param subtractedValue The amount to decrease the allowance by
/// @return true if successful
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperToken } from "./ISuperToken.sol";
/**
* @title SuperApp interface
* @author Superfluid
* @dev Be aware of the app being jailed, when the word permitted is used.
*/
interface ISuperApp {
/**
* @dev Callback before a new agreement is created.
* @param superToken The super token used for the agreement.
* @param agreementClass The agreement class address.
* @param agreementId The agreementId
* @param agreementData The agreement data (non-compressed)
* @param ctx The context data.
* @return cbdata A free format in memory data the app can use to pass
* arbitary information to the after-hook callback.
*
* @custom:note
* - It will be invoked with `staticcall`, no state changes are permitted.
* - Only revert with a "reason" is permitted.
*/
function beforeAgreementCreated(
ISuperToken superToken,
address agreementClass,
bytes32 agreementId,
bytes calldata agreementData,
bytes calldata ctx
)
external
view
returns (bytes memory cbdata);
/**
* @dev Callback after a new agreement is created.
* @param superToken The super token used for the agreement.
* @param agreementClass The agreement class address.
* @param agreementId The agreementId
* @param agreementData The agreement data (non-compressed)
* @param cbdata The data returned from the before-hook callback.
* @param ctx The context data.
* @return newCtx The current context of the transaction.
*
* @custom:note
* - State changes is permitted.
* - Only revert with a "reason" is permitted.
*/
function afterAgreementCreated(
ISuperToken superToken,
address agreementClass,
bytes32 agreementId,
bytes calldata agreementData,
bytes calldata cbdata,
bytes calldata ctx
)
external
returns (bytes memory newCtx);
/**
* @dev Callback before a new agreement is updated.
* @param superToken The super token used for the agreement.
* @param agreementClass The agreement class address.
* @param agreementId The agreementId
* @param agreementData The agreement data (non-compressed)
* @param ctx The context data.
* @return cbdata A free format in memory data the app can use to pass
* arbitary information to the after-hook callback.
*
* @custom:note
* - It will be invoked with `staticcall`, no state changes are permitted.
* - Only revert with a "reason" is permitted.
*/
function beforeAgreementUpdated(
ISuperToken superToken,
address agreementClass,
bytes32 agreementId,
bytes calldata agreementData,
bytes calldata ctx
)
external
view
returns (bytes memory cbdata);
/**
* @dev Callback after a new agreement is updated.
* @param superToken The super token used for the agreement.
* @param agreementClass The agreement class address.
* @param agreementId The agreementId
* @param agreementData The agreement data (non-compressed)
* @param cbdata The data returned from the before-hook callback.
* @param ctx The context data.
* @return newCtx The current context of the transaction.
*
* @custom:note
* - State changes is permitted.
* - Only revert with a "reason" is permitted.
*/
function afterAgreementUpdated(
ISuperToken superToken,
address agreementClass,
bytes32 agreementId,
bytes calldata agreementData,
bytes calldata cbdata,
bytes calldata ctx
)
external
returns (bytes memory newCtx);
/**
* @dev Callback before a new agreement is terminated.
* @param superToken The super token used for the agreement.
* @param agreementClass The agreement class address.
* @param agreementId The agreementId
* @param agreementData The agreement data (non-compressed)
* @param ctx The context data.
* @return cbdata A free format in memory data the app can use to pass arbitary information to
* the after-hook callback.
*
* @custom:note
* - It will be invoked with `staticcall`, no state changes are permitted.
* - Revert is not permitted.
*/
function beforeAgreementTerminated(
ISuperToken superToken,
address agreementClass,
bytes32 agreementId,
bytes calldata agreementData,
bytes calldata ctx
)
external
view
returns (bytes memory cbdata);
/**
* @dev Callback after a new agreement is terminated.
* @param superToken The super token used for the agreement.
* @param agreementClass The agreement class address.
* @param agreementId The agreementId
* @param agreementData The agreement data (non-compressed)
* @param cbdata The data returned from the before-hook callback.
* @param ctx The context data.
* @return newCtx The current context of the transaction.
*
* @custom:note
* - State changes is permitted.
* - Revert is not permitted.
*/
function afterAgreementTerminated(
ISuperToken superToken,
address agreementClass,
bytes32 agreementId,
bytes calldata agreementData,
bytes calldata cbdata,
bytes calldata ctx
)
external
returns (bytes memory newCtx);
}// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.11;
import { ISuperfluid } from "./ISuperfluid.sol";
import { ISuperToken } from "./ISuperToken.sol";
import { ISuperfluidToken } from "./ISuperfluidToken.sol";
/**
* @title Superfluid governance interface
* @author Superfluid
*/
interface ISuperfluidGovernance {
/**************************************************************************
* Errors
*************************************************************************/
error SF_GOV_INVALID_LIQUIDATION_OR_PATRICIAN_PERIOD(); // 0xe171980a
error SF_GOV_MUST_BE_CONTRACT(); // 0x80dddd73
/**
* @dev Replace the current governance with a new governance
*/
function replaceGovernance(
ISuperfluid host,
address newGov) external;
/**
* @dev Register a new agreement class
*/
function registerAgreementClass(
ISuperfluid host,
address agreementClass) external;
/**
* @dev Update logics of the contracts
*
* @custom:note
* - Because they might have inter-dependencies, it is good to have one single function to update them all
*/
function updateContracts(
ISuperfluid host,
address hostNewLogic,
address[] calldata agreementClassNewLogics,
address superTokenFactoryNewLogic,
address beaconNewLogic
) external;
/**
* @dev Update supertoken logic contract to the latest that is managed by the super token factory
*/
function batchUpdateSuperTokenLogic(
ISuperfluid host,
ISuperToken[] calldata tokens) external;
/**
* @dev Update supertoken logic contract to the provided logic contracts.
* Note that this is an overloaded version taking an additional argument `tokenLogics`
*/
function batchUpdateSuperTokenLogic(
ISuperfluid host,
ISuperToken[] calldata tokens,
address[] calldata tokenLogics) external;
/**
* @dev Set configuration as address value
*/
function setConfig(
ISuperfluid host,
ISuperfluidToken superToken,
bytes32 key,
address value
) external;
/**
* @dev Set configuration as uint256 value
*/
function setConfig(
ISuperfluid host,
ISuperfluidToken superToken,
bytes32 key,
uint256 value
) external;
/**
* @dev Clear configuration
*/
function clearConfig(
ISuperfluid host,
ISuperfluidToken superToken,
bytes32 key
) external;
/**
* @dev Get configuration as address value
*/
function getConfigAsAddress(
ISuperfluid host,
ISuperfluidToken superToken,
bytes32 key) external view returns (address value);
/**
* @dev Get configuration as uint256 value
*/
function getConfigAsUint256(
ISuperfluid host,
ISuperfluidToken superToken,
bytes32 key) external view returns (uint256 value);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: AGPLv3
pragma solidity >=0.8.4;
import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
interface IPoolNFTBase is IERC721Metadata {
error POOL_NFT_APPROVE_TO_CALLER(); // 0x9212b333
error POOL_NFT_ONLY_SUPER_TOKEN_FACTORY(); // 0x1fd7e3d8
error POOL_NFT_INVALID_TOKEN_ID(); // 0x09275994
error POOL_NFT_APPROVE_TO_CURRENT_OWNER(); // 0x020226d3
error POOL_NFT_APPROVE_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0x1e82f255
error POOL_NFT_NOT_REGISTERED_POOL(); // 0x6421912e
error POOL_NFT_TRANSFER_NOT_ALLOWED(); // 0x432fb160
error POOL_NFT_TRANSFER_CALLER_NOT_OWNER_OR_APPROVED_FOR_ALL(); // 0x4028ee0e
/// @notice Informs third-party platforms that NFT metadata should be updated
/// @dev This event comes from https://eips.ethereum.org/EIPS/eip-4906
/// @param tokenId the id of the token that should have its metadata updated
event MetadataUpdate(uint256 tokenId);
function initialize(string memory nftName, string memory nftSymbol) external; // initializer;
function triggerMetadataUpdate(uint256 tokenId) external;
/// @notice Gets the token id
/// @dev For PoolAdminNFT, `account` is admin and for PoolMemberNFT, `account` is member
function getTokenId(address pool, address account) external view returns (uint256 tokenId);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@superfluid-finance/=lib/superfluid-protocol-monorepo/packages/",
"@openzeppelin-v5/contracts/=lib/openzeppelin-contracts-v5/contracts/",
"ds-test/=lib/openzeppelin-contracts-v5/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-v5/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts-v5/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts-v4/=lib/openzeppelin-contracts-v4/",
"openzeppelin-contracts-v5/=lib/openzeppelin-contracts-v5/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts-v4/contracts/",
"superfluid-protocol-monorepo.tmp/=lib/superfluid-protocol-monorepo.tmp/packages/solidity-semantic-money/src/",
"superfluid-protocol-monorepo/=lib/superfluid-protocol-monorepo/packages/solidity-semantic-money/src/"
],
"optimizer": {
"enabled": false,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"nativeBridge_","type":"address"},{"internalType":"address","name":"remoteToken_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"IXERC20_LimitsTooHigh","type":"error"},{"inputs":[],"name":"IXERC20_NoLockBox","type":"error"},{"inputs":[],"name":"IXERC20_NotHighEnoughLimits","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_mintingLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_burningLimit","type":"uint256"},{"indexed":true,"internalType":"address","name":"_bridge","type":"address"}],"name":"BridgeLimitsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_lockbox","type":"address"}],"name":"LockboxSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bridgeBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bridgeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bridges","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"currentLimit","type":"uint256"}],"internalType":"struct IXERC20.BridgeParameters","name":"minterParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"},{"internalType":"uint256","name":"maxLimit","type":"uint256"},{"internalType":"uint256","name":"currentLimit","type":"uint256"}],"internalType":"struct IXERC20.BridgeParameters","name":"burnerParams","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bridge","type":"address"}],"name":"burningCurrentLimitOf","outputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bridge","type":"address"}],"name":"burningMaxLimitOf","outputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISuperTokenFactory","name":"factory","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"initialSupply","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"initialAddress","type":"address"}],"name":"initializeProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l1Address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bridge","type":"address"}],"name":"mintingCurrentLimitOf","outputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bridge","type":"address"}],"name":"mintingMaxLimitOf","outputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"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":"address","name":"bridge","type":"address"},{"internalType":"uint256","name":"mintingLimit","type":"uint256"},{"internalType":"uint256","name":"burningLimit","type":"uint256"}],"name":"setLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"setLockbox","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c060405234801561000f575f80fd5b50604051612b31380380612b3183398181016040528101906100319190610a7a565b61004d61004261012560201b60201c565b61012c60201b60201c565b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505061011e8260027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6100e69190610b1b565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101139190610b1b565b6101ef60201b60201c565b5050610ca0565b5f33905090565b5f60205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6101fd61030e60201b60201c565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61022a9190610b1b565b821180610262575060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61025f9190610b1b565b81115b15610299576040517ff596480900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102a9838361039860201b60201c565b6102b9838261052f60201b60201c565b8273ffffffffffffffffffffffffffffffffffffffff167f93f3bbfe8cfb354ec059175107653f49f6eb479a8622a7d83866ea015435c9448383604051610301929190610b5a565b60405180910390a2505050565b61031c61012560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff166103406106cb60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614610396576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038d90610bdb565b60405180910390fd5b565b5f60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015490505f6103ee846106f360201b60201c565b90508260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002018190555061044883838361081460201b60201c565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160030181905550620151808361049d9190610b1b565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600101819055504260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f018190555050505050565b5f60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015490505f6105868461087160201b60201c565b90508260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201819055506105e183838361081460201b60201c565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003018190555062015180836106379190610b1b565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600101819055504260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f018190555050505050565b5f60205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f61080d60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016003015460215f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015460215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f015460215f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016001015461099660201b60201c565b9050919050565b5f8083851161084c5784846108299190610bf9565b9050808311610838575f610845565b80836108449190610bf9565b5b9150610869565b83856108589190610bf9565b905080836108669190610c2c565b91505b509392505050565b5f61098f60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003015460215f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015460215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f015460215f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016001015461099660201b60201c565b9050919050565b5f84905083810315610a14574262015180846109b29190610c2c565b116109bf57839050610a13565b4262015180846109cf9190610c2c565b1115610a12575f83426109e29190610bf9565b90505f83826109f19190610c5f565b836109fc9190610c2c565b9050858111610a0b5780610a0d565b855b925050505b5b5b949350505050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610a4982610a20565b9050919050565b610a5981610a3f565b8114610a63575f80fd5b50565b5f81519050610a7481610a50565b92915050565b5f8060408385031215610a9057610a8f610a1c565b5b5f610a9d85828601610a66565b9250506020610aae85828601610a66565b9150509250929050565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610b2582610ab8565b9150610b3083610ab8565b925082610b4057610b3f610ac1565b5b828204905092915050565b610b5481610ab8565b82525050565b5f604082019050610b6d5f830185610b4b565b610b7a6020830184610b4b565b9392505050565b5f82825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f610bc5602083610b81565b9150610bd082610b91565b602082019050919050565b5f6020820190508181035f830152610bf281610bb9565b9050919050565b5f610c0382610ab8565b9150610c0e83610ab8565b9250828203905081811115610c2657610c25610aee565b5b92915050565b5f610c3682610ab8565b9150610c4183610ab8565b9250828201905080821115610c5957610c58610aee565b5b92915050565b5f610c6982610ab8565b9150610c7483610ab8565b9250828202610c8281610ab8565b91508282048414831517610c9957610c98610aee565b5b5092915050565b60805160a051611e73610cbe5f395f610ddc01525f5050611e735ff3fe608060405260043610610101575f3560e01c80638c2a993e11610094578063a08d565411610063578063a08d565414610326578063c1eb71371461034e578063c2eeeebd1461038a578063ced67f0c146103b4578063f2fde38b146103f157610110565b80638c2a993e146102705780638da5cb5b14610298578063998955d3146102c25780639dc29fac146102fe57610110565b8063651fd268116100d0578063651fd268146101ce578063715018a61461020a57806374f4f5471461022057806375b30be61461024857610110565b80630c05f82c1461011a57806340c10f1914610156578063435350b71461017e5780634a0687ef146101a657610110565b366101105761010e610419565b005b610118610419565b005b348015610125575f80fd5b50610140600480360381019061013b9190611532565b610433565b60405161014d9190611575565b60405180910390f35b348015610161575f80fd5b5061017c600480360381019061017791906115b8565b61047e565b005b348015610189575f80fd5b506101a4600480360381019061019f9190611532565b6105ce565b005b3480156101b1575f80fd5b506101cc60048036038101906101c79190611532565b610600565b005b3480156101d9575f80fd5b506101f460048036038101906101ef9190611532565b6106ef565b6040516102019190611575565b60405180910390f35b348015610215575f80fd5b5061021e61080a565b005b34801561022b575f80fd5b50610246600480360381019061024191906115b8565b61081d565b005b348015610253575f80fd5b5061026e6004803603810190610269919061176d565b61082b565b005b34801561027b575f80fd5b50610296600480360381019061029191906115b8565b61096d565b005b3480156102a3575f80fd5b506102ac61097b565b6040516102b9919061182b565b60405180910390f35b3480156102cd575f80fd5b506102e860048036038101906102e39190611532565b6109a3565b6040516102f59190611575565b60405180910390f35b348015610309575f80fd5b50610324600480360381019061031f91906115b8565b610ac2565b005b348015610331575f80fd5b5061034c60048036038101906103479190611844565b610c80565b005b348015610359575f80fd5b50610374600480360381019061036f9190611532565b610d8d565b6040516103819190611575565b60405180910390f35b348015610395575f80fd5b5061039e610dd9565b6040516103ab919061182b565b60405180910390f35b3480156103bf575f80fd5b506103da60048036038101906103d59190611532565b610e00565b6040516103e89291906118f6565b60405180910390f35b3480156103fc575f80fd5b5061041760048036038101906104129190611532565b610e82565b005b610421610f04565b61043161042c610f06565b610f14565b565b5f60215f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201549050919050565b5f3390505f61048c826106ef565b9050828110156104c8576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4260215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f0181905550828161051a919061194b565b60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600301819055503073ffffffffffffffffffffffffffffffffffffffff1663c68d428385856040518363ffffffff1660e01b815260040161059b9291906119b1565b5f604051808303815f87803b1580156105b2575f80fd5b505af11580156105c4573d5f803e3d5ffd5b5050505050505050565b6040517fcd045eca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361066e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161066590611a45565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff1661068d610f33565b73ffffffffffffffffffffffffffffffffffffffff16146106e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106da90611aad565b60405180910390fd5b6106ec81610f5b565b50565b5f61080360215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016003015460215f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015460215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f015460215f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160010154610f81565b9050919050565b610812611007565b61081b5f611085565b565b6108278282610ac2565b5050565b8473ffffffffffffffffffffffffffffffffffffffff1663d412d344306040518263ffffffff1660e01b8152600401610864919061182b565b5f604051808303815f87803b15801561087b575f80fd5b505af115801561088d573d5f803e3d5ffd5b505050503073ffffffffffffffffffffffffffffffffffffffff166342fe09805f601287876040518563ffffffff1660e01b81526004016108d19493929190611bbb565b5f604051808303815f87803b1580156108e8575f80fd5b505af11580156108fa573d5f803e3d5ffd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663c68d428383836040518363ffffffff1660e01b81526004016109399291906119b1565b5f604051808303815f87803b158015610950575f80fd5b505af1158015610962573d5f803e3d5ffd5b505050505050505050565b610977828261047e565b5050565b5f60205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f610abb60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003015460215f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015460215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f015460215f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160010154610f81565b9050919050565b5f3390505f610ad0826109a3565b905082811015610b0c576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4260215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f01819055508281610b5f919061194b565b60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600301819055503073ffffffffffffffffffffffffffffffffffffffff166341b706be858485876040518563ffffffff1660e01b8152600401610be59493929190611c0c565b5f604051808303815f87803b158015610bfc575f80fd5b505af1158015610c0e573d5f803e3d5ffd5b505050503073ffffffffffffffffffffffffffffffffffffffff16639d87674183856040518363ffffffff1660e01b8152600401610c4d9291906119b1565b5f604051808303815f87803b158015610c64575f80fd5b505af1158015610c76573d5f803e3d5ffd5b5050505050505050565b610c88611007565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610cb59190611c7c565b821180610ced575060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610cea9190611c7c565b81115b15610d24576040517ff596480900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2e8383611148565b610d3883826112d3565b8273ffffffffffffffffffffffffffffffffffffffff167f93f3bbfe8cfb354ec059175107653f49f6eb479a8622a7d83866ea015435c9448383604051610d80929190611cac565b60405180910390a2505050565b5f60215f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201549050919050565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b6021602052805f5260405f205f91509050805f016040518060800160405290815f8201548152602001600182015481526020016002820154815260200160038201548152505090806004016040518060800160405290815f82015481526020016001820154815260200160028201548152602001600382015481525050905082565b610e8a611007565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ef8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eef90611d43565b60405180910390fd5b610f0181611085565b50565b565b5f610f0f610f33565b905090565b365f80375f80365f845af43d5f803e805f8114610f2f573d5ff35b3d5ffd5b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54905090565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5550565b5f84905083810315610fff57426201518084610f9d9190611d61565b11610faa57839050610ffe565b426201518084610fba9190611d61565b1115610ffd575f8342610fcd919061194b565b90505f8382610fdc9190611d94565b83610fe79190611d61565b9050858111610ff65780610ff8565b855b925050505b5b5b949350505050565b61100f611463565b73ffffffffffffffffffffffffffffffffffffffff1661102d61097b565b73ffffffffffffffffffffffffffffffffffffffff1614611083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107a90611e1f565b60405180910390fd5b565b5f60205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015490505f611198846106ef565b90508260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201819055506111ec83838361146a565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016003018190555062015180836112419190611c7c565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600101819055504260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f018190555050505050565b5f60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015490505f611324846109a3565b90508260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002018190555061137983838361146a565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003018190555062015180836113cf9190611c7c565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600101819055504260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f018190555050505050565b5f33905090565b5f808385116114a257848461147f919061194b565b905080831161148e575f61149b565b808361149a919061194b565b5b91506114bf565b83856114ae919061194b565b905080836114bc9190611d61565b91505b509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611501826114d8565b9050919050565b611511816114f7565b811461151b575f80fd5b50565b5f8135905061152c81611508565b92915050565b5f60208284031215611547576115466114d0565b5b5f6115548482850161151e565b91505092915050565b5f819050919050565b61156f8161155d565b82525050565b5f6020820190506115885f830184611566565b92915050565b6115978161155d565b81146115a1575f80fd5b50565b5f813590506115b28161158e565b92915050565b5f80604083850312156115ce576115cd6114d0565b5b5f6115db8582860161151e565b92505060206115ec858286016115a4565b9150509250929050565b5f611600826114f7565b9050919050565b611610816115f6565b811461161a575f80fd5b50565b5f8135905061162b81611607565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61167f82611639565b810181811067ffffffffffffffff8211171561169e5761169d611649565b5b80604052505050565b5f6116b06114c7565b90506116bc8282611676565b919050565b5f67ffffffffffffffff8211156116db576116da611649565b5b6116e482611639565b9050602081019050919050565b828183375f83830152505050565b5f61171161170c846116c1565b6116a7565b90508281526020810184848401111561172d5761172c611635565b5b6117388482856116f1565b509392505050565b5f82601f83011261175457611753611631565b5b81356117648482602086016116ff565b91505092915050565b5f805f805f60a08688031215611786576117856114d0565b5b5f6117938882890161161d565b955050602086013567ffffffffffffffff8111156117b4576117b36114d4565b5b6117c088828901611740565b945050604086013567ffffffffffffffff8111156117e1576117e06114d4565b5b6117ed88828901611740565b93505060606117fe8882890161151e565b925050608061180f888289016115a4565b9150509295509295909350565b611825816114f7565b82525050565b5f60208201905061183e5f83018461181c565b92915050565b5f805f6060848603121561185b5761185a6114d0565b5b5f6118688682870161151e565b9350506020611879868287016115a4565b925050604061188a868287016115a4565b9150509250925092565b61189d8161155d565b82525050565b608082015f8201516118b75f850182611894565b5060208201516118ca6020850182611894565b5060408201516118dd6040850182611894565b5060608201516118f06060850182611894565b50505050565b5f6101008201905061190a5f8301856118a3565b61191760808301846118a3565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6119558261155d565b91506119608361155d565b92508282039050818111156119785761197761191e565b5b92915050565b5f82825260208201905092915050565b50565b5f61199c5f8361197e565b91506119a78261198e565b5f82019050919050565b5f6060820190506119c45f83018561181c565b6119d16020830184611566565b81810360408301526119e281611991565b90509392505050565b5f82825260208201905092915050565b7f5555505350726f78793a207a65726f20616464726573730000000000000000005f82015250565b5f611a2f6017836119eb565b9150611a3a826119fb565b602082019050919050565b5f6020820190508181035f830152611a5c81611a23565b9050919050565b7f5555505350726f78793a20616c726561647920696e697469616c697a656400005f82015250565b5f611a97601e836119eb565b9150611aa282611a63565b602082019050919050565b5f6020820190508181035f830152611ac481611a8b565b9050919050565b5f819050919050565b5f611aee611ae9611ae4846114d8565b611acb565b6114d8565b9050919050565b5f611aff82611ad4565b9050919050565b5f611b1082611af5565b9050919050565b611b2081611b06565b82525050565b5f819050919050565b5f60ff82169050919050565b5f611b55611b50611b4b84611b26565b611acb565b611b2f565b9050919050565b611b6581611b3b565b82525050565b5f81519050919050565b8281835e5f83830152505050565b5f611b8d82611b6b565b611b9781856119eb565b9350611ba7818560208601611b75565b611bb081611639565b840191505092915050565b5f608082019050611bce5f830187611b17565b611bdb6020830186611b5c565b8181036040830152611bed8185611b83565b90508181036060830152611c018184611b83565b905095945050505050565b5f608082019050611c1f5f83018761181c565b611c2c602083018661181c565b611c39604083018561181c565b611c466060830184611566565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f611c868261155d565b9150611c918361155d565b925082611ca157611ca0611c4f565b5b828204905092915050565b5f604082019050611cbf5f830185611566565b611ccc6020830184611566565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f611d2d6026836119eb565b9150611d3882611cd3565b604082019050919050565b5f6020820190508181035f830152611d5a81611d21565b9050919050565b5f611d6b8261155d565b9150611d768361155d565b9250828201905080821115611d8e57611d8d61191e565b5b92915050565b5f611d9e8261155d565b9150611da98361155d565b9250828202611db78161155d565b91508282048414831517611dce57611dcd61191e565b5b5092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f611e096020836119eb565b9150611e1482611dd5565b602082019050919050565b5f6020820190508181035f830152611e3681611dfd565b905091905056fea2646970667358221220112af6897d8aa6730abb0400292af321697230b78e9ff993378b62f1e287385f64736f6c634300081a0033000000000000000000000000096760f208390250649e3e8763348e783aef55620000000000000000000000000bc4df77353ae96f31bc82bc2536bb23b2009919
Deployed Bytecode
0x608060405260043610610101575f3560e01c80638c2a993e11610094578063a08d565411610063578063a08d565414610326578063c1eb71371461034e578063c2eeeebd1461038a578063ced67f0c146103b4578063f2fde38b146103f157610110565b80638c2a993e146102705780638da5cb5b14610298578063998955d3146102c25780639dc29fac146102fe57610110565b8063651fd268116100d0578063651fd268146101ce578063715018a61461020a57806374f4f5471461022057806375b30be61461024857610110565b80630c05f82c1461011a57806340c10f1914610156578063435350b71461017e5780634a0687ef146101a657610110565b366101105761010e610419565b005b610118610419565b005b348015610125575f80fd5b50610140600480360381019061013b9190611532565b610433565b60405161014d9190611575565b60405180910390f35b348015610161575f80fd5b5061017c600480360381019061017791906115b8565b61047e565b005b348015610189575f80fd5b506101a4600480360381019061019f9190611532565b6105ce565b005b3480156101b1575f80fd5b506101cc60048036038101906101c79190611532565b610600565b005b3480156101d9575f80fd5b506101f460048036038101906101ef9190611532565b6106ef565b6040516102019190611575565b60405180910390f35b348015610215575f80fd5b5061021e61080a565b005b34801561022b575f80fd5b50610246600480360381019061024191906115b8565b61081d565b005b348015610253575f80fd5b5061026e6004803603810190610269919061176d565b61082b565b005b34801561027b575f80fd5b50610296600480360381019061029191906115b8565b61096d565b005b3480156102a3575f80fd5b506102ac61097b565b6040516102b9919061182b565b60405180910390f35b3480156102cd575f80fd5b506102e860048036038101906102e39190611532565b6109a3565b6040516102f59190611575565b60405180910390f35b348015610309575f80fd5b50610324600480360381019061031f91906115b8565b610ac2565b005b348015610331575f80fd5b5061034c60048036038101906103479190611844565b610c80565b005b348015610359575f80fd5b50610374600480360381019061036f9190611532565b610d8d565b6040516103819190611575565b60405180910390f35b348015610395575f80fd5b5061039e610dd9565b6040516103ab919061182b565b60405180910390f35b3480156103bf575f80fd5b506103da60048036038101906103d59190611532565b610e00565b6040516103e89291906118f6565b60405180910390f35b3480156103fc575f80fd5b5061041760048036038101906104129190611532565b610e82565b005b610421610f04565b61043161042c610f06565b610f14565b565b5f60215f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201549050919050565b5f3390505f61048c826106ef565b9050828110156104c8576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4260215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f0181905550828161051a919061194b565b60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600301819055503073ffffffffffffffffffffffffffffffffffffffff1663c68d428385856040518363ffffffff1660e01b815260040161059b9291906119b1565b5f604051808303815f87803b1580156105b2575f80fd5b505af11580156105c4573d5f803e3d5ffd5b5050505050505050565b6040517fcd045eca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361066e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161066590611a45565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff1661068d610f33565b73ffffffffffffffffffffffffffffffffffffffff16146106e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106da90611aad565b60405180910390fd5b6106ec81610f5b565b50565b5f61080360215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016003015460215f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015460215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f015460215f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0160010154610f81565b9050919050565b610812611007565b61081b5f611085565b565b6108278282610ac2565b5050565b8473ffffffffffffffffffffffffffffffffffffffff1663d412d344306040518263ffffffff1660e01b8152600401610864919061182b565b5f604051808303815f87803b15801561087b575f80fd5b505af115801561088d573d5f803e3d5ffd5b505050503073ffffffffffffffffffffffffffffffffffffffff166342fe09805f601287876040518563ffffffff1660e01b81526004016108d19493929190611bbb565b5f604051808303815f87803b1580156108e8575f80fd5b505af11580156108fa573d5f803e3d5ffd5b505050503073ffffffffffffffffffffffffffffffffffffffff1663c68d428383836040518363ffffffff1660e01b81526004016109399291906119b1565b5f604051808303815f87803b158015610950575f80fd5b505af1158015610962573d5f803e3d5ffd5b505050505050505050565b610977828261047e565b5050565b5f60205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f610abb60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003015460215f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015460215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f015460215f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060040160010154610f81565b9050919050565b5f3390505f610ad0826109a3565b905082811015610b0c576040517f0b6842aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4260215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f01819055508281610b5f919061194b565b60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600301819055503073ffffffffffffffffffffffffffffffffffffffff166341b706be858485876040518563ffffffff1660e01b8152600401610be59493929190611c0c565b5f604051808303815f87803b158015610bfc575f80fd5b505af1158015610c0e573d5f803e3d5ffd5b505050503073ffffffffffffffffffffffffffffffffffffffff16639d87674183856040518363ffffffff1660e01b8152600401610c4d9291906119b1565b5f604051808303815f87803b158015610c64575f80fd5b505af1158015610c76573d5f803e3d5ffd5b5050505050505050565b610c88611007565b60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610cb59190611c7c565b821180610ced575060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610cea9190611c7c565b81115b15610d24576040517ff596480900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2e8383611148565b610d3883826112d3565b8273ffffffffffffffffffffffffffffffffffffffff167f93f3bbfe8cfb354ec059175107653f49f6eb479a8622a7d83866ea015435c9448383604051610d80929190611cac565b60405180910390a2505050565b5f60215f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600201549050919050565b5f7f0000000000000000000000000bc4df77353ae96f31bc82bc2536bb23b2009919905090565b6021602052805f5260405f205f91509050805f016040518060800160405290815f8201548152602001600182015481526020016002820154815260200160038201548152505090806004016040518060800160405290815f82015481526020016001820154815260200160028201548152602001600382015481525050905082565b610e8a611007565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ef8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eef90611d43565b60405180910390fd5b610f0181611085565b50565b565b5f610f0f610f33565b905090565b365f80375f80365f845af43d5f803e805f8114610f2f573d5ff35b3d5ffd5b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54905090565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5550565b5f84905083810315610fff57426201518084610f9d9190611d61565b11610faa57839050610ffe565b426201518084610fba9190611d61565b1115610ffd575f8342610fcd919061194b565b90505f8382610fdc9190611d94565b83610fe79190611d61565b9050858111610ff65780610ff8565b855b925050505b5b5b949350505050565b61100f611463565b73ffffffffffffffffffffffffffffffffffffffff1661102d61097b565b73ffffffffffffffffffffffffffffffffffffffff1614611083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161107a90611e1f565b60405180910390fd5b565b5f60205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016002015490505f611198846106ef565b90508260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600201819055506111ec83838361146a565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f016003018190555062015180836112419190611c7c565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f01600101819055504260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f018190555050505050565b5f60215f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002015490505f611324846109a3565b90508260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016002018190555061137983838361146a565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004016003018190555062015180836113cf9190611c7c565b60215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600401600101819055504260215f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206004015f018190555050505050565b5f33905090565b5f808385116114a257848461147f919061194b565b905080831161148e575f61149b565b808361149a919061194b565b5b91506114bf565b83856114ae919061194b565b905080836114bc9190611d61565b91505b509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f611501826114d8565b9050919050565b611511816114f7565b811461151b575f80fd5b50565b5f8135905061152c81611508565b92915050565b5f60208284031215611547576115466114d0565b5b5f6115548482850161151e565b91505092915050565b5f819050919050565b61156f8161155d565b82525050565b5f6020820190506115885f830184611566565b92915050565b6115978161155d565b81146115a1575f80fd5b50565b5f813590506115b28161158e565b92915050565b5f80604083850312156115ce576115cd6114d0565b5b5f6115db8582860161151e565b92505060206115ec858286016115a4565b9150509250929050565b5f611600826114f7565b9050919050565b611610816115f6565b811461161a575f80fd5b50565b5f8135905061162b81611607565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61167f82611639565b810181811067ffffffffffffffff8211171561169e5761169d611649565b5b80604052505050565b5f6116b06114c7565b90506116bc8282611676565b919050565b5f67ffffffffffffffff8211156116db576116da611649565b5b6116e482611639565b9050602081019050919050565b828183375f83830152505050565b5f61171161170c846116c1565b6116a7565b90508281526020810184848401111561172d5761172c611635565b5b6117388482856116f1565b509392505050565b5f82601f83011261175457611753611631565b5b81356117648482602086016116ff565b91505092915050565b5f805f805f60a08688031215611786576117856114d0565b5b5f6117938882890161161d565b955050602086013567ffffffffffffffff8111156117b4576117b36114d4565b5b6117c088828901611740565b945050604086013567ffffffffffffffff8111156117e1576117e06114d4565b5b6117ed88828901611740565b93505060606117fe8882890161151e565b925050608061180f888289016115a4565b9150509295509295909350565b611825816114f7565b82525050565b5f60208201905061183e5f83018461181c565b92915050565b5f805f6060848603121561185b5761185a6114d0565b5b5f6118688682870161151e565b9350506020611879868287016115a4565b925050604061188a868287016115a4565b9150509250925092565b61189d8161155d565b82525050565b608082015f8201516118b75f850182611894565b5060208201516118ca6020850182611894565b5060408201516118dd6040850182611894565b5060608201516118f06060850182611894565b50505050565b5f6101008201905061190a5f8301856118a3565b61191760808301846118a3565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6119558261155d565b91506119608361155d565b92508282039050818111156119785761197761191e565b5b92915050565b5f82825260208201905092915050565b50565b5f61199c5f8361197e565b91506119a78261198e565b5f82019050919050565b5f6060820190506119c45f83018561181c565b6119d16020830184611566565b81810360408301526119e281611991565b90509392505050565b5f82825260208201905092915050565b7f5555505350726f78793a207a65726f20616464726573730000000000000000005f82015250565b5f611a2f6017836119eb565b9150611a3a826119fb565b602082019050919050565b5f6020820190508181035f830152611a5c81611a23565b9050919050565b7f5555505350726f78793a20616c726561647920696e697469616c697a656400005f82015250565b5f611a97601e836119eb565b9150611aa282611a63565b602082019050919050565b5f6020820190508181035f830152611ac481611a8b565b9050919050565b5f819050919050565b5f611aee611ae9611ae4846114d8565b611acb565b6114d8565b9050919050565b5f611aff82611ad4565b9050919050565b5f611b1082611af5565b9050919050565b611b2081611b06565b82525050565b5f819050919050565b5f60ff82169050919050565b5f611b55611b50611b4b84611b26565b611acb565b611b2f565b9050919050565b611b6581611b3b565b82525050565b5f81519050919050565b8281835e5f83830152505050565b5f611b8d82611b6b565b611b9781856119eb565b9350611ba7818560208601611b75565b611bb081611639565b840191505092915050565b5f608082019050611bce5f830187611b17565b611bdb6020830186611b5c565b8181036040830152611bed8185611b83565b90508181036060830152611c018184611b83565b905095945050505050565b5f608082019050611c1f5f83018761181c565b611c2c602083018661181c565b611c39604083018561181c565b611c466060830184611566565b95945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f611c868261155d565b9150611c918361155d565b925082611ca157611ca0611c4f565b5b828204905092915050565b5f604082019050611cbf5f830185611566565b611ccc6020830184611566565b9392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20615f8201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b5f611d2d6026836119eb565b9150611d3882611cd3565b604082019050919050565b5f6020820190508181035f830152611d5a81611d21565b9050919050565b5f611d6b8261155d565b9150611d768361155d565b9250828201905080821115611d8e57611d8d61191e565b5b92915050565b5f611d9e8261155d565b9150611da98361155d565b9250828202611db78161155d565b91508282048414831517611dce57611dcd61191e565b5b5092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65725f82015250565b5f611e096020836119eb565b9150611e1482611dd5565b602082019050919050565b5f6020820190508181035f830152611e3681611dfd565b905091905056fea2646970667358221220112af6897d8aa6730abb0400292af321697230b78e9ff993378b62f1e287385f64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000096760f208390250649e3e8763348e783aef55620000000000000000000000000bc4df77353ae96f31bc82bc2536bb23b2009919
-----Decoded View---------------
Arg [0] : nativeBridge_ (address): 0x096760F208390250649E3e8763348E783AEF5562
Arg [1] : remoteToken_ (address): 0x0Bc4dF77353ae96f31bC82bC2536bb23B2009919
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000096760f208390250649e3e8763348e783aef5562
Arg [1] : 0000000000000000000000000bc4df77353ae96f31bc82bc2536bb23b2009919
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.