Polygon Sponsored slots available. Book your slot here!
Overview
MATIC Balance
MATIC Value
$0.00More Info
Private Name Tags
ContractCreator:
Multi Chain
Multichain Addresses
4 addresses found via
Loading...
Loading
Contract Name:
Collector
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol'; import {Address} from 'solidity-utils/contracts/oz-common/Address.sol'; import {ICollector} from '../interfaces/ICollector.sol'; import {VersionedInitializable} from '../libs/VersionedInitializable.sol'; import {ReentrancyGuard} from '../libs/ReentrancyGuard.sol'; /** * @title Collector * @notice Stores ERC20 tokens of an ecosystem reserve and allows to dispose of them via approval * or transfer dynamics or streaming capabilities. * Modification of Sablier https://github.com/sablierhq/sablier/blob/develop/packages/protocol/contracts/Sablier.sol * Original can be found also deployed on https://etherscan.io/address/0xCD18eAa163733Da39c232722cBC4E8940b1D8888 * Modifications: * - Sablier "pulls" the funds from the creator of the stream at creation. In the Aave case, we already have the funds. * - Anybody can create streams on Sablier. Here, only the funds admin (Aave governance via controller) can * - Adapted codebase to Solidity 0.8.11, mainly removing SafeMath and CarefulMath to use native safe math * - Same as with creation, on Sablier the `sender` and `recipient` can cancel a stream. Here, only fund admin and recipient * @author BGD Labs **/ contract Collector is VersionedInitializable, ICollector, ReentrancyGuard { using SafeERC20 for IERC20; using Address for address payable; /*** Storage Properties ***/ /** * @notice Address of the current funds admin. */ address internal _fundsAdmin; /** * @notice Current revision of the contract. */ uint256 public constant REVISION = 5; /** * @notice Counter for new stream ids. */ uint256 private _nextStreamId; /** * @notice The stream objects identifiable by their unsigned integer ids. */ mapping(uint256 => Stream) private _streams; /// @inheritdoc ICollector address public constant ETH_MOCK_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /*** Modifiers ***/ /** * @dev Throws if the caller is not the funds admin. */ modifier onlyFundsAdmin() { require(msg.sender == _fundsAdmin, 'ONLY_BY_FUNDS_ADMIN'); _; } /** * @dev Throws if the caller is not the funds admin of the recipient of the stream. * @param streamId The id of the stream to query. */ modifier onlyAdminOrRecipient(uint256 streamId) { require( msg.sender == _fundsAdmin || msg.sender == _streams[streamId].recipient, 'caller is not the funds admin or the recipient of the stream' ); _; } /** * @dev Throws if the provided id does not point to a valid stream. */ modifier streamExists(uint256 streamId) { require(_streams[streamId].isEntity, 'stream does not exist'); _; } /*** Contract Logic Starts Here */ /// @inheritdoc ICollector function initialize(address fundsAdmin, uint256 nextStreamId) external initializer { if (nextStreamId != 0) { _nextStreamId = nextStreamId; } // can be removed after first deployment _initGuard(); _setFundsAdmin(fundsAdmin); } /*** View Functions ***/ /// @inheritdoc VersionedInitializable function getRevision() internal pure override returns (uint256) { return REVISION; } /// @inheritdoc ICollector function getFundsAdmin() external view returns (address) { return _fundsAdmin; } /// @inheritdoc ICollector function getNextStreamId() external view returns (uint256) { return _nextStreamId; } /// @inheritdoc ICollector function getStream( uint256 streamId ) external view streamExists(streamId) returns ( address sender, address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime, uint256 remainingBalance, uint256 ratePerSecond ) { sender = _streams[streamId].sender; recipient = _streams[streamId].recipient; deposit = _streams[streamId].deposit; tokenAddress = _streams[streamId].tokenAddress; startTime = _streams[streamId].startTime; stopTime = _streams[streamId].stopTime; remainingBalance = _streams[streamId].remainingBalance; ratePerSecond = _streams[streamId].ratePerSecond; } /** * @notice Returns either the delta in seconds between `block.timestamp` and `startTime` or * between `stopTime` and `startTime, whichever is smaller. If `block.timestamp` is before * `startTime`, it returns 0. * @dev Throws if the id does not point to a valid stream. * @param streamId The id of the stream for which to query the delta. * @notice Returns the time delta in seconds. */ function deltaOf(uint256 streamId) public view streamExists(streamId) returns (uint256 delta) { Stream memory stream = _streams[streamId]; if (block.timestamp <= stream.startTime) return 0; if (block.timestamp < stream.stopTime) return block.timestamp - stream.startTime; return stream.stopTime - stream.startTime; } struct BalanceOfLocalVars { uint256 recipientBalance; uint256 withdrawalAmount; uint256 senderBalance; } /// @inheritdoc ICollector function balanceOf( uint256 streamId, address who ) public view streamExists(streamId) returns (uint256 balance) { Stream memory stream = _streams[streamId]; BalanceOfLocalVars memory vars; uint256 delta = deltaOf(streamId); vars.recipientBalance = delta * stream.ratePerSecond; /* * If the stream `balance` does not equal `deposit`, it means there have been withdrawals. * We have to subtract the total amount withdrawn from the amount of money that has been * streamed until now. */ if (stream.deposit > stream.remainingBalance) { vars.withdrawalAmount = stream.deposit - stream.remainingBalance; vars.recipientBalance = vars.recipientBalance - vars.withdrawalAmount; } if (who == stream.recipient) return vars.recipientBalance; if (who == stream.sender) { vars.senderBalance = stream.remainingBalance - vars.recipientBalance; return vars.senderBalance; } return 0; } /*** Public Effects & Interactions Functions ***/ /// @inheritdoc ICollector function approve(IERC20 token, address recipient, uint256 amount) external onlyFundsAdmin { token.safeApprove(recipient, amount); } /// @inheritdoc ICollector function transfer(IERC20 token, address recipient, uint256 amount) external onlyFundsAdmin { require(recipient != address(0), 'INVALID_0X_RECIPIENT'); if (address(token) == ETH_MOCK_ADDRESS) { payable(recipient).sendValue(amount); } else { token.safeTransfer(recipient, amount); } } /// @dev needed in order to receive ETH from the Aave v1 ecosystem reserve receive() external payable {} /// @inheritdoc ICollector function setFundsAdmin(address admin) external onlyFundsAdmin { _setFundsAdmin(admin); } /** * @dev Transfer the ownership of the funds administrator role. * @param admin The address of the new funds administrator */ function _setFundsAdmin(address admin) internal { _fundsAdmin = admin; emit NewFundsAdmin(admin); } struct CreateStreamLocalVars { uint256 duration; uint256 ratePerSecond; } /// @inheritdoc ICollector /** * @dev Throws if the recipient is the zero address, the contract itself or the caller. * Throws if the deposit is 0. * Throws if the start time is before `block.timestamp`. * Throws if the stop time is before the start time. * Throws if the duration calculation has a math error. * Throws if the deposit is smaller than the duration. * Throws if the deposit is not a multiple of the duration. * Throws if the rate calculation has a math error. * Throws if the next stream id calculation has a math error. * Throws if the contract is not allowed to transfer enough tokens. * Throws if there is a token transfer failure. */ function createStream( address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime ) external onlyFundsAdmin returns (uint256) { require(recipient != address(0), 'stream to the zero address'); require(recipient != address(this), 'stream to the contract itself'); require(recipient != msg.sender, 'stream to the caller'); require(deposit > 0, 'deposit is zero'); require(startTime >= block.timestamp, 'start time before block.timestamp'); require(stopTime > startTime, 'stop time before the start time'); CreateStreamLocalVars memory vars; vars.duration = stopTime - startTime; /* Without this, the rate per second would be zero. */ require(deposit >= vars.duration, 'deposit smaller than time delta'); /* This condition avoids dealing with remainders */ require(deposit % vars.duration == 0, 'deposit not multiple of time delta'); vars.ratePerSecond = deposit / vars.duration; /* Create and store the stream object. */ uint256 streamId = _nextStreamId; _streams[streamId] = Stream({ remainingBalance: deposit, deposit: deposit, isEntity: true, ratePerSecond: vars.ratePerSecond, recipient: recipient, sender: address(this), startTime: startTime, stopTime: stopTime, tokenAddress: tokenAddress }); /* Increment the next stream id. */ _nextStreamId++; emit CreateStream( streamId, address(this), recipient, deposit, tokenAddress, startTime, stopTime ); return streamId; } /// @inheritdoc ICollector /** * @dev Throws if the id does not point to a valid stream. * Throws if the caller is not the funds admin or the recipient of the stream. * Throws if the amount exceeds the available balance. * Throws if there is a token transfer failure. */ function withdrawFromStream( uint256 streamId, uint256 amount ) external nonReentrant streamExists(streamId) onlyAdminOrRecipient(streamId) returns (bool) { require(amount > 0, 'amount is zero'); Stream memory stream = _streams[streamId]; uint256 balance = balanceOf(streamId, stream.recipient); require(balance >= amount, 'amount exceeds the available balance'); _streams[streamId].remainingBalance = stream.remainingBalance - amount; if (_streams[streamId].remainingBalance == 0) delete _streams[streamId]; IERC20(stream.tokenAddress).safeTransfer(stream.recipient, amount); emit WithdrawFromStream(streamId, stream.recipient, amount); return true; } /// @inheritdoc ICollector /** * @dev Throws if the id does not point to a valid stream. * Throws if the caller is not the funds admin or the recipient of the stream. * Throws if there is a token transfer failure. */ function cancelStream( uint256 streamId ) external nonReentrant streamExists(streamId) onlyAdminOrRecipient(streamId) returns (bool) { Stream memory stream = _streams[streamId]; uint256 senderBalance = balanceOf(streamId, stream.sender); uint256 recipientBalance = balanceOf(streamId, stream.recipient); delete _streams[streamId]; IERC20 token = IERC20(stream.tokenAddress); if (recipientBalance > 0) token.safeTransfer(stream.recipient, recipientBalance); emit CancelStream(streamId, stream.sender, stream.recipient, senderBalance, recipientBalance); return true; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) // From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/8b778fa20d6d76340c5fac1ed66c80273f05b95a pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, 'Address: insufficient balance'); (bool success, ) = recipient.call{value: amount}(''); require(success, 'Address: unable to send value, recipient may have reverted'); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, 'Address: low-level call failed'); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, 'Address: low-level call with value failed'); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, 'Address: insufficient balance for call'); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, 'Address: low-level static call failed'); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, 'Address: low-level delegate call failed'); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), 'Address: call to non-contract'); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) // From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/3dac7bbed7b4c0dbf504180c33e8ed8e350b93eb pragma solidity ^0.8.0; import "./interfaces/IERC20.sol"; import "./interfaces/draft-IERC20Permit.sol"; import "./Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) // From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/a035b235b4f2c9af4ba88edc4447f02e37f8d124 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: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) // From commit https://github.com/OpenZeppelin/openzeppelin-contracts/commit/6bd6b76d1156e20e45d1016f355d154141c7e5b9 pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; interface ICollector { struct Stream { uint256 deposit; uint256 ratePerSecond; uint256 remainingBalance; uint256 startTime; uint256 stopTime; address recipient; address sender; address tokenAddress; bool isEntity; } /** @notice Emitted when the funds admin changes * @param fundsAdmin The new funds admin. **/ event NewFundsAdmin(address indexed fundsAdmin); /** @notice Emitted when the new stream is created * @param streamId The identifier of the stream. * @param sender The address of the collector. * @param recipient The address towards which the money is streamed. * @param deposit The amount of money to be streamed. * @param tokenAddress The ERC20 token to use as streaming currency. * @param startTime The unix timestamp for when the stream starts. * @param stopTime The unix timestamp for when the stream stops. **/ event CreateStream( uint256 indexed streamId, address indexed sender, address indexed recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime ); /** * @notice Emmitted when withdraw happens from the contract to the recipient's account. * @param streamId The id of the stream to withdraw tokens from. * @param recipient The address towards which the money is streamed. * @param amount The amount of tokens to withdraw. */ event WithdrawFromStream(uint256 indexed streamId, address indexed recipient, uint256 amount); /** * @notice Emmitted when the stream is canceled. * @param streamId The id of the stream to withdraw tokens from. * @param sender The address of the collector. * @param recipient The address towards which the money is streamed. * @param senderBalance The sender's balance at the moment of cancelling. * @param recipientBalance The recipient's balance at the moment of cancelling. */ event CancelStream( uint256 indexed streamId, address indexed sender, address indexed recipient, uint256 senderBalance, uint256 recipientBalance ); /** @notice Returns the mock ETH reference address * @return address The address **/ function ETH_MOCK_ADDRESS() external pure returns (address); /** @notice Initializes the contracts * @param fundsAdmin Funds admin address * @param nextStreamId StreamId to set, applied if greater than 0 **/ function initialize(address fundsAdmin, uint256 nextStreamId) external; /** * @notice Return the funds admin, only entity to be able to interact with this contract (controller of reserve) * @return address The address of the funds admin **/ function getFundsAdmin() external view returns (address); /** * @notice Returns the available funds for the given stream id and address. * @param streamId The id of the stream for which to query the balance. * @param who The address for which to query the balance. * @notice Returns the total funds allocated to `who` as uint256. */ function balanceOf(uint256 streamId, address who) external view returns (uint256 balance); /** * @dev Function for the funds admin to give ERC20 allowance to other parties * @param token The address of the token to give allowance from * @param recipient Allowance's recipient * @param amount Allowance to approve **/ function approve(IERC20 token, address recipient, uint256 amount) external; /** * @notice Function for the funds admin to transfer ERC20 tokens to other parties * @param token The address of the token to transfer * @param recipient Transfer's recipient * @param amount Amount to transfer **/ function transfer(IERC20 token, address recipient, uint256 amount) external; /** * @dev Transfer the ownership of the funds administrator role. This function should only be callable by the current funds administrator. * @param admin The address of the new funds administrator */ function setFundsAdmin(address admin) external; /** * @notice Creates a new stream funded by this contracts itself and paid towards `recipient`. * @param recipient The address towards which the money is streamed. * @param deposit The amount of money to be streamed. * @param tokenAddress The ERC20 token to use as streaming currency. * @param startTime The unix timestamp for when the stream starts. * @param stopTime The unix timestamp for when the stream stops. * @return streamId the uint256 id of the newly created stream. */ function createStream( address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime ) external returns (uint256 streamId); /** * @notice Returns the stream with all its properties. * @dev Throws if the id does not point to a valid stream. * @param streamId The id of the stream to query. * @notice Returns the stream object. */ function getStream( uint256 streamId ) external view returns ( address sender, address recipient, uint256 deposit, address tokenAddress, uint256 startTime, uint256 stopTime, uint256 remainingBalance, uint256 ratePerSecond ); /** * @notice Withdraws from the contract to the recipient's account. * @param streamId The id of the stream to withdraw tokens from. * @param amount The amount of tokens to withdraw. * @return bool Returns true if successful. */ function withdrawFromStream(uint256 streamId, uint256 amount) external returns (bool); /** * @notice Cancels the stream and transfers the tokens back on a pro rata basis. * @param streamId The id of the stream to cancel. * @return bool Returns true if successful. */ function cancelStream(uint256 streamId) external returns (bool); /** * @notice Returns the next available stream id * @return nextStreamId Returns the stream id. */ function getNextStreamId() external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, 'ReentrancyGuard: reentrant call'); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev As we use the guard with the proxy we need to init it with the empty value */ function _initGuard() internal { _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /** * @title VersionedInitializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. * * @author Aave, inspired by the OpenZeppelin Initializable contract */ abstract contract VersionedInitializable { /** * @dev Indicates that the contract has been initialized. */ uint256 internal lastInitializedRevision = 0; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { uint256 revision = getRevision(); require(revision > lastInitializedRevision, 'Contract instance has already been initialized'); lastInitializedRevision = revision; _; } /// @dev returns the revision number of the contract. /// Needs to be defined in the inherited class as a constant. function getRevision() internal pure virtual returns (uint256); // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
{ "remappings": [ "@aave/core-v2/=lib/protocol-v2/", "@aave/core-v3/=lib/aave-address-book/lib/aave-v3-core/", "@aave/periphery-v3/=lib/aave-address-book/lib/aave-v3-periphery/", "aave-address-book/=lib/aave-address-book/src/", "aave-helpers/=lib/aave-helpers/src/", "aave-v3-core/=lib/aave-address-book/lib/aave-v3-core/", "aave-v3-periphery/=lib/aave-address-book/lib/aave-v3-periphery/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "protocol-v2/=lib/protocol-v2/", "solidity-utils/=lib/solidity-utils/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"streamId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"senderBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"recipientBalance","type":"uint256"}],"name":"CancelStream","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"streamId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"deposit","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stopTime","type":"uint256"}],"name":"CreateStream","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fundsAdmin","type":"address"}],"name":"NewFundsAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"streamId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawFromStream","type":"event"},{"inputs":[],"name":"ETH_MOCK_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REVISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"streamId","type":"uint256"},{"internalType":"address","name":"who","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"streamId","type":"uint256"}],"name":"cancelStream","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"stopTime","type":"uint256"}],"name":"createStream","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"streamId","type":"uint256"}],"name":"deltaOf","outputs":[{"internalType":"uint256","name":"delta","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFundsAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextStreamId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"streamId","type":"uint256"}],"name":"getStream","outputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"stopTime","type":"uint256"},{"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"internalType":"uint256","name":"ratePerSecond","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fundsAdmin","type":"address"},{"internalType":"uint256","name":"nextStreamId","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"setFundsAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"streamId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFromStream","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040526000805534801561001457600080fd5b506001603355611bb9806100296000396000f3fe6080604052600436106100e15760003560e01c8063a82ccd4d1161007f578063cd6dc68711610059578063cd6dc687146102a8578063dde43cba146102c8578063e1f21c67146102dd578063ed0d2371146102fd57600080fd5b8063a82ccd4d14610246578063beabacc814610266578063cc1b4bf61461028857600080fd5b806351ee886b116100bb57806351ee886b146101635780636db9241b1461018b5780637a9b2c6c146101bb578063894e9a0d146101db57600080fd5b806306bc2ee0146100ed5780630932f92b146101245780633656eec21461014357600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b506034546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561013057600080fd5b506035545b60405190815260200161011b565b34801561014f57600080fd5b5061013561015e366004611831565b61031d565b34801561016f57600080fd5b5061010773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561019757600080fd5b506101ab6101a6366004611861565b6104cc565b604051901515815260200161011b565b3480156101c757600080fd5b506101ab6101d636600461187a565b610756565b3480156101e757600080fd5b506101fb6101f6366004611861565b610a7d565b604080516001600160a01b03998a1681529789166020890152870195909552959092166060850152608084015260a083015260c082019290925260e08101919091526101000161011b565b34801561025257600080fd5b50610135610261366004611861565b610b26565b34801561027257600080fd5b5061028661028136600461189c565b610c41565b005b34801561029457600080fd5b506101356102a33660046118dd565b610d09565b3480156102b457600080fd5b506102866102c336600461192f565b6111dc565b3480156102d457600080fd5b50610135600581565b3480156102e957600080fd5b506102866102f836600461189c565b61126b565b34801561030957600080fd5b5061028661031836600461195b565b6112a9565b6000828152603660205260408120600701548390600160a01b900460ff166103605760405162461bcd60e51b81526004016103579061197f565b60405180910390fd5b60008481526036602090815260408083208151610120810183528154815260018201548185015260028201548184015260038201546060808301919091526004830154608083015260058301546001600160a01b0390811660a08401526006840154811660c084015260079093015492831660e0830152600160a01b90920460ff161515610100820152825191820183528482529281018490529081019290925290600061040d87610b26565b905082602001518161041f91906119c4565b8252604083015183511115610455576040830151835161043f91906119e1565b60208301819052825161045291906119e1565b82525b8260a001516001600160a01b0316866001600160a01b03160361047d57505192506104c59050565b8260c001516001600160a01b0316866001600160a01b0316036104bd57815160408401516104ab91906119e1565b60409092018290525092506104c59050565b600094505050505b5092915050565b60006002603354036105205760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610357565b60026033556000828152603660205260409020600701548290600160a01b900460ff1661055f5760405162461bcd60e51b81526004016103579061197f565b60345483906001600160a01b031633148061059357506000818152603660205260409020600501546001600160a01b031633145b6105af5760405162461bcd60e51b8152600401610357906119f4565b600084815260366020908152604080832081516101208101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b0390811660a08401526006820154811660c0840181905260079092015490811660e0840152600160a01b900460ff16151561010083015290919061064a90879061031d565b9050600061065c878460a0015161031d565b600088815260366020526040812081815560018101829055600281018290556003810182905560048101919091556005810180546001600160a01b0319908116909155600682018054909116905560070180546001600160a81b031916905560e084015190915081156106e35760a08401516106e3906001600160a01b03831690846112df565b8360a001516001600160a01b03168460c001516001600160a01b0316897fca3e6079b726e7728802a0537949e2d1c7762304fa641fb06eb56daf2ba8c6b9868660405161073a929190918252602082015260400190565b60405180910390a4600196505050505050506001603355919050565b60006002603354036107aa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610357565b60026033556000838152603660205260409020600701548390600160a01b900460ff166107e95760405162461bcd60e51b81526004016103579061197f565b60345484906001600160a01b031633148061081d57506000818152603660205260409020600501546001600160a01b031633145b6108395760405162461bcd60e51b8152600401610357906119f4565b6000841161087a5760405162461bcd60e51b815260206004820152600e60248201526d616d6f756e74206973207a65726f60901b6044820152606401610357565b600085815260366020908152604080832081516101208101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b0390811660a084018190526006830154821660c085015260079092015490811660e0840152600160a01b900460ff16151561010083015290919061091590889061031d565b9050858110156109735760405162461bcd60e51b8152602060048201526024808201527f616d6f756e7420657863656564732074686520617661696c61626c652062616c604482015263616e636560e01b6064820152608401610357565b85826040015161098391906119e1565b6000888152603660205260408120600201829055036109fc57600087815260366020526040812081815560018101829055600281018290556003810182905560048101919091556005810180546001600160a01b0319908116909155600682018054909116905560070180546001600160a81b03191690555b610a228260a00151878460e001516001600160a01b03166112df9092919063ffffffff16565b8160a001516001600160a01b0316877f36c3ab437e6a424ed25dc4bfdeb62706aa06558660fab2dab229d2555adaf89c88604051610a6291815260200190565b60405180910390a36001945050505050600160335592915050565b600080600080600080600080886036600082815260200190815260200160002060070160149054906101000a900460ff16610aca5760405162461bcd60e51b81526004016103579061197f565b5050506000968752505060366020525050604090922060068101546005820154825460078401546003850154600486015460028701546001909701546001600160a01b039687169a958716995093975091909416949092909190565b6000818152603660205260408120600701548290600160a01b900460ff16610b605760405162461bcd60e51b81526004016103579061197f565b600083815260366020908152604091829020825161012081018452815481526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260058301546001600160a01b0390811660a08401526006840154811660c084015260079093015492831660e0830152600160a01b90920460ff161515610100820152904211610c00576000925050610c3b565b8060800151421015610c23576060810151610c1b90426119e1565b925050610c3b565b80606001518160800151610c3791906119e1565b9250505b50919050565b6034546001600160a01b03163314610c6b5760405162461bcd60e51b815260040161035790611a51565b6001600160a01b038216610cb85760405162461bcd60e51b81526020600482015260146024820152731253959053125117cc1617d49150d2541251539560621b6044820152606401610357565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610cf557610cf06001600160a01b03831682611342565b505050565b610cf06001600160a01b03841683836112df565b6034546000906001600160a01b03163314610d365760405162461bcd60e51b815260040161035790611a51565b6001600160a01b038616610d8c5760405162461bcd60e51b815260206004820152601a60248201527f73747265616d20746f20746865207a65726f20616464726573730000000000006044820152606401610357565b306001600160a01b03871603610de45760405162461bcd60e51b815260206004820152601d60248201527f73747265616d20746f2074686520636f6e747261637420697473656c660000006044820152606401610357565b336001600160a01b03871603610e335760405162461bcd60e51b815260206004820152601460248201527339ba3932b0b6903a37903a34329031b0b63632b960611b6044820152606401610357565b60008511610e755760405162461bcd60e51b815260206004820152600f60248201526e6465706f736974206973207a65726f60881b6044820152606401610357565b42831015610ecf5760405162461bcd60e51b815260206004820152602160248201527f73746172742074696d65206265666f726520626c6f636b2e74696d657374616d6044820152600760fc1b6064820152608401610357565b828211610f1e5760405162461bcd60e51b815260206004820152601f60248201527f73746f702074696d65206265666f7265207468652073746172742074696d65006044820152606401610357565b6040805180820190915260008082526020820152610f3c84846119e1565b808252861015610f8e5760405162461bcd60e51b815260206004820152601f60248201527f6465706f73697420736d616c6c6572207468616e2074696d652064656c7461006044820152606401610357565b8051610f9a9087611a94565b15610ff25760405162461bcd60e51b815260206004820152602260248201527f6465706f736974206e6f74206d756c7469706c65206f662074696d652064656c604482015261746160f01b6064820152608401610357565b8051610ffe9087611aa8565b8160200181815250506000603554905060405180610120016040528088815260200183602001518152602001888152602001868152602001858152602001896001600160a01b03168152602001306001600160a01b03168152602001876001600160a01b031681526020016001151581525060366000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c08201518160060160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160070160146101000a81548160ff0219169083151502179055509050506035600081548092919061117390611abc565b9091555050604080518881526001600160a01b0388811660208301529181018790526060810186905290891690309083907f7b01d409597969366dc268d7f957a990d1ca3d3449baf8fb45db67351aecfe789060800160405180910390a4979650505050505050565b60005460059081116112475760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b6064820152608401610357565b600081905581156112585760358290555b6112626001603355565b610cf08361145b565b6034546001600160a01b031633146112955760405162461bcd60e51b815260040161035790611a51565b610cf06001600160a01b03841683836114a5565b6034546001600160a01b031633146112d35760405162461bcd60e51b815260040161035790611a51565b6112dc8161145b565b50565b6040516001600160a01b038316602482015260448101829052610cf090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526115ba565b804710156113925760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610357565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146113df576040519150601f19603f3d011682016040523d82523d6000602084013e6113e4565b606091505b5050905080610cf05760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610357565b603480546001600160a01b0319166001600160a01b0383169081179091556040517f1ab77a654795da4cfe37c33188e862203ade9a5c7f1a9d4957669b3ccbec9e1190600090a250565b80158061151f5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156114f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151d9190611ad5565b155b61158a5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610357565b6040516001600160a01b038316602482015260448101829052610cf090849063095ea7b360e01b9060640161130b565b600061160f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661168c9092919063ffffffff16565b805190915015610cf0578080602001905181019061162d9190611aee565b610cf05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610357565b606061169b84846000856116a3565b949350505050565b6060824710156117045760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610357565b600080866001600160a01b031685876040516117209190611b34565b60006040518083038185875af1925050503d806000811461175d576040519150601f19603f3d011682016040523d82523d6000602084013e611762565b606091505b50915091506117738783838761177e565b979650505050505050565b606083156117ed5782516000036117e6576001600160a01b0385163b6117e65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610357565b508161169b565b61169b83838151156118025781518083602001fd5b8060405162461bcd60e51b81526004016103579190611b50565b6001600160a01b03811681146112dc57600080fd5b6000806040838503121561184457600080fd5b8235915060208301356118568161181c565b809150509250929050565b60006020828403121561187357600080fd5b5035919050565b6000806040838503121561188d57600080fd5b50508035926020909101359150565b6000806000606084860312156118b157600080fd5b83356118bc8161181c565b925060208401356118cc8161181c565b929592945050506040919091013590565b600080600080600060a086880312156118f557600080fd5b85356119008161181c565b94506020860135935060408601356119178161181c565b94979396509394606081013594506080013592915050565b6000806040838503121561194257600080fd5b823561194d8161181c565b946020939093013593505050565b60006020828403121561196d57600080fd5b81356119788161181c565b9392505050565b6020808252601590820152741cdd1c99585b48191bd95cc81b9bdd08195e1a5cdd605a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176119db576119db6119ae565b92915050565b818103818111156119db576119db6119ae565b6020808252603c908201527f63616c6c6572206973206e6f74207468652066756e64732061646d696e206f7260408201527f2074686520726563697069656e74206f66207468652073747265616d00000000606082015260800190565b60208082526013908201527227a7262cafa12cafa32aa72229afa0a226a4a760691b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082611aa357611aa3611a7e565b500690565b600082611ab757611ab7611a7e565b500490565b600060018201611ace57611ace6119ae565b5060010190565b600060208284031215611ae757600080fd5b5051919050565b600060208284031215611b0057600080fd5b8151801515811461197857600080fd5b60005b83811015611b2b578181015183820152602001611b13565b50506000910152565b60008251611b46818460208701611b10565b9190910192915050565b6020815260008251806020840152611b6f816040850160208701611b10565b601f01601f1916919091016040019291505056fea264697066735822122009d19ad83e96bd5f02a57854393a8f5345d10be88358642a442821c97aea4cc964736f6c63430008110033
Deployed Bytecode
0x6080604052600436106100e15760003560e01c8063a82ccd4d1161007f578063cd6dc68711610059578063cd6dc687146102a8578063dde43cba146102c8578063e1f21c67146102dd578063ed0d2371146102fd57600080fd5b8063a82ccd4d14610246578063beabacc814610266578063cc1b4bf61461028857600080fd5b806351ee886b116100bb57806351ee886b146101635780636db9241b1461018b5780637a9b2c6c146101bb578063894e9a0d146101db57600080fd5b806306bc2ee0146100ed5780630932f92b146101245780633656eec21461014357600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b506034546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561013057600080fd5b506035545b60405190815260200161011b565b34801561014f57600080fd5b5061013561015e366004611831565b61031d565b34801561016f57600080fd5b5061010773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561019757600080fd5b506101ab6101a6366004611861565b6104cc565b604051901515815260200161011b565b3480156101c757600080fd5b506101ab6101d636600461187a565b610756565b3480156101e757600080fd5b506101fb6101f6366004611861565b610a7d565b604080516001600160a01b03998a1681529789166020890152870195909552959092166060850152608084015260a083015260c082019290925260e08101919091526101000161011b565b34801561025257600080fd5b50610135610261366004611861565b610b26565b34801561027257600080fd5b5061028661028136600461189c565b610c41565b005b34801561029457600080fd5b506101356102a33660046118dd565b610d09565b3480156102b457600080fd5b506102866102c336600461192f565b6111dc565b3480156102d457600080fd5b50610135600581565b3480156102e957600080fd5b506102866102f836600461189c565b61126b565b34801561030957600080fd5b5061028661031836600461195b565b6112a9565b6000828152603660205260408120600701548390600160a01b900460ff166103605760405162461bcd60e51b81526004016103579061197f565b60405180910390fd5b60008481526036602090815260408083208151610120810183528154815260018201548185015260028201548184015260038201546060808301919091526004830154608083015260058301546001600160a01b0390811660a08401526006840154811660c084015260079093015492831660e0830152600160a01b90920460ff161515610100820152825191820183528482529281018490529081019290925290600061040d87610b26565b905082602001518161041f91906119c4565b8252604083015183511115610455576040830151835161043f91906119e1565b60208301819052825161045291906119e1565b82525b8260a001516001600160a01b0316866001600160a01b03160361047d57505192506104c59050565b8260c001516001600160a01b0316866001600160a01b0316036104bd57815160408401516104ab91906119e1565b60409092018290525092506104c59050565b600094505050505b5092915050565b60006002603354036105205760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610357565b60026033556000828152603660205260409020600701548290600160a01b900460ff1661055f5760405162461bcd60e51b81526004016103579061197f565b60345483906001600160a01b031633148061059357506000818152603660205260409020600501546001600160a01b031633145b6105af5760405162461bcd60e51b8152600401610357906119f4565b600084815260366020908152604080832081516101208101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b0390811660a08401526006820154811660c0840181905260079092015490811660e0840152600160a01b900460ff16151561010083015290919061064a90879061031d565b9050600061065c878460a0015161031d565b600088815260366020526040812081815560018101829055600281018290556003810182905560048101919091556005810180546001600160a01b0319908116909155600682018054909116905560070180546001600160a81b031916905560e084015190915081156106e35760a08401516106e3906001600160a01b03831690846112df565b8360a001516001600160a01b03168460c001516001600160a01b0316897fca3e6079b726e7728802a0537949e2d1c7762304fa641fb06eb56daf2ba8c6b9868660405161073a929190918252602082015260400190565b60405180910390a4600196505050505050506001603355919050565b60006002603354036107aa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610357565b60026033556000838152603660205260409020600701548390600160a01b900460ff166107e95760405162461bcd60e51b81526004016103579061197f565b60345484906001600160a01b031633148061081d57506000818152603660205260409020600501546001600160a01b031633145b6108395760405162461bcd60e51b8152600401610357906119f4565b6000841161087a5760405162461bcd60e51b815260206004820152600e60248201526d616d6f756e74206973207a65726f60901b6044820152606401610357565b600085815260366020908152604080832081516101208101835281548152600182015493810193909352600281015491830191909152600381015460608301526004810154608083015260058101546001600160a01b0390811660a084018190526006830154821660c085015260079092015490811660e0840152600160a01b900460ff16151561010083015290919061091590889061031d565b9050858110156109735760405162461bcd60e51b8152602060048201526024808201527f616d6f756e7420657863656564732074686520617661696c61626c652062616c604482015263616e636560e01b6064820152608401610357565b85826040015161098391906119e1565b6000888152603660205260408120600201829055036109fc57600087815260366020526040812081815560018101829055600281018290556003810182905560048101919091556005810180546001600160a01b0319908116909155600682018054909116905560070180546001600160a81b03191690555b610a228260a00151878460e001516001600160a01b03166112df9092919063ffffffff16565b8160a001516001600160a01b0316877f36c3ab437e6a424ed25dc4bfdeb62706aa06558660fab2dab229d2555adaf89c88604051610a6291815260200190565b60405180910390a36001945050505050600160335592915050565b600080600080600080600080886036600082815260200190815260200160002060070160149054906101000a900460ff16610aca5760405162461bcd60e51b81526004016103579061197f565b5050506000968752505060366020525050604090922060068101546005820154825460078401546003850154600486015460028701546001909701546001600160a01b039687169a958716995093975091909416949092909190565b6000818152603660205260408120600701548290600160a01b900460ff16610b605760405162461bcd60e51b81526004016103579061197f565b600083815260366020908152604091829020825161012081018452815481526001820154928101929092526002810154928201929092526003820154606082018190526004830154608083015260058301546001600160a01b0390811660a08401526006840154811660c084015260079093015492831660e0830152600160a01b90920460ff161515610100820152904211610c00576000925050610c3b565b8060800151421015610c23576060810151610c1b90426119e1565b925050610c3b565b80606001518160800151610c3791906119e1565b9250505b50919050565b6034546001600160a01b03163314610c6b5760405162461bcd60e51b815260040161035790611a51565b6001600160a01b038216610cb85760405162461bcd60e51b81526020600482015260146024820152731253959053125117cc1617d49150d2541251539560621b6044820152606401610357565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610cf557610cf06001600160a01b03831682611342565b505050565b610cf06001600160a01b03841683836112df565b6034546000906001600160a01b03163314610d365760405162461bcd60e51b815260040161035790611a51565b6001600160a01b038616610d8c5760405162461bcd60e51b815260206004820152601a60248201527f73747265616d20746f20746865207a65726f20616464726573730000000000006044820152606401610357565b306001600160a01b03871603610de45760405162461bcd60e51b815260206004820152601d60248201527f73747265616d20746f2074686520636f6e747261637420697473656c660000006044820152606401610357565b336001600160a01b03871603610e335760405162461bcd60e51b815260206004820152601460248201527339ba3932b0b6903a37903a34329031b0b63632b960611b6044820152606401610357565b60008511610e755760405162461bcd60e51b815260206004820152600f60248201526e6465706f736974206973207a65726f60881b6044820152606401610357565b42831015610ecf5760405162461bcd60e51b815260206004820152602160248201527f73746172742074696d65206265666f726520626c6f636b2e74696d657374616d6044820152600760fc1b6064820152608401610357565b828211610f1e5760405162461bcd60e51b815260206004820152601f60248201527f73746f702074696d65206265666f7265207468652073746172742074696d65006044820152606401610357565b6040805180820190915260008082526020820152610f3c84846119e1565b808252861015610f8e5760405162461bcd60e51b815260206004820152601f60248201527f6465706f73697420736d616c6c6572207468616e2074696d652064656c7461006044820152606401610357565b8051610f9a9087611a94565b15610ff25760405162461bcd60e51b815260206004820152602260248201527f6465706f736974206e6f74206d756c7469706c65206f662074696d652064656c604482015261746160f01b6064820152608401610357565b8051610ffe9087611aa8565b8160200181815250506000603554905060405180610120016040528088815260200183602001518152602001888152602001868152602001858152602001896001600160a01b03168152602001306001600160a01b03168152602001876001600160a01b031681526020016001151581525060366000838152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c08201518160060160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060e08201518160070160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506101008201518160070160146101000a81548160ff0219169083151502179055509050506035600081548092919061117390611abc565b9091555050604080518881526001600160a01b0388811660208301529181018790526060810186905290891690309083907f7b01d409597969366dc268d7f957a990d1ca3d3449baf8fb45db67351aecfe789060800160405180910390a4979650505050505050565b60005460059081116112475760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201526d195b881a5b9a5d1a585b1a5e995960921b6064820152608401610357565b600081905581156112585760358290555b6112626001603355565b610cf08361145b565b6034546001600160a01b031633146112955760405162461bcd60e51b815260040161035790611a51565b610cf06001600160a01b03841683836114a5565b6034546001600160a01b031633146112d35760405162461bcd60e51b815260040161035790611a51565b6112dc8161145b565b50565b6040516001600160a01b038316602482015260448101829052610cf090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526115ba565b804710156113925760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610357565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146113df576040519150601f19603f3d011682016040523d82523d6000602084013e6113e4565b606091505b5050905080610cf05760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610357565b603480546001600160a01b0319166001600160a01b0383169081179091556040517f1ab77a654795da4cfe37c33188e862203ade9a5c7f1a9d4957669b3ccbec9e1190600090a250565b80158061151f5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156114f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151d9190611ad5565b155b61158a5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610357565b6040516001600160a01b038316602482015260448101829052610cf090849063095ea7b360e01b9060640161130b565b600061160f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661168c9092919063ffffffff16565b805190915015610cf0578080602001905181019061162d9190611aee565b610cf05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610357565b606061169b84846000856116a3565b949350505050565b6060824710156117045760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610357565b600080866001600160a01b031685876040516117209190611b34565b60006040518083038185875af1925050503d806000811461175d576040519150601f19603f3d011682016040523d82523d6000602084013e611762565b606091505b50915091506117738783838761177e565b979650505050505050565b606083156117ed5782516000036117e6576001600160a01b0385163b6117e65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610357565b508161169b565b61169b83838151156118025781518083602001fd5b8060405162461bcd60e51b81526004016103579190611b50565b6001600160a01b03811681146112dc57600080fd5b6000806040838503121561184457600080fd5b8235915060208301356118568161181c565b809150509250929050565b60006020828403121561187357600080fd5b5035919050565b6000806040838503121561188d57600080fd5b50508035926020909101359150565b6000806000606084860312156118b157600080fd5b83356118bc8161181c565b925060208401356118cc8161181c565b929592945050506040919091013590565b600080600080600060a086880312156118f557600080fd5b85356119008161181c565b94506020860135935060408601356119178161181c565b94979396509394606081013594506080013592915050565b6000806040838503121561194257600080fd5b823561194d8161181c565b946020939093013593505050565b60006020828403121561196d57600080fd5b81356119788161181c565b9392505050565b6020808252601590820152741cdd1c99585b48191bd95cc81b9bdd08195e1a5cdd605a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176119db576119db6119ae565b92915050565b818103818111156119db576119db6119ae565b6020808252603c908201527f63616c6c6572206973206e6f74207468652066756e64732061646d696e206f7260408201527f2074686520726563697069656e74206f66207468652073747265616d00000000606082015260800190565b60208082526013908201527227a7262cafa12cafa32aa72229afa0a226a4a760691b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082611aa357611aa3611a7e565b500690565b600082611ab757611ab7611a7e565b500490565b600060018201611ace57611ace6119ae565b5060010190565b600060208284031215611ae757600080fd5b5051919050565b600060208284031215611b0057600080fd5b8151801515811461197857600080fd5b60005b83811015611b2b578181015183820152602001611b13565b50506000910152565b60008251611b46818460208701611b10565b9190910192915050565b6020815260008251806020840152611b6f816040850160208701611b10565b601f01601f1916919091016040019291505056fea264697066735822122009d19ad83e96bd5f02a57854393a8f5345d10be88358642a442821c97aea4cc964736f6c63430008110033
Loading...
Loading
Loading...
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.
[ 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.