Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
14722373 | 959 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
VestingModule
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.13; import {Clone} from "clones-with-immutable-args/Clone.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {FullMath} from "./lib/FullMath.sol"; /// /// @title VestingModule /// @author 0xSplits <[email protected]> /// @notice A maximally-composable vesting contract allowing multiple isolated /// streams of different tokens to reach a beneficiary over time. Streams share /// a vesting period but may begin or have funds released independently. /// @dev Funds pile up in the contract via `receive()` & simple ERC20 `transfer` /// until a caller creates a new vesting stream. The funds then vest linearly /// over {vestingPeriod} and may be withdrawn accordingly by anyone on behalf /// of the {beneficiary}. There is no limit on the number of simultaneous /// vesting streams which may be created, ongoing or withdrawn from in a single /// tx. /// This contract uses address(0) in some fns/events/mappings to refer to ETH. /// contract VestingModule is Clone { /// ----------------------------------------------------------------------- /// errors /// ----------------------------------------------------------------------- error InvalidVestingStreamId(uint256 id); /// ----------------------------------------------------------------------- /// libraries /// ----------------------------------------------------------------------- using SafeTransferLib for address; using SafeTransferLib for ERC20; /// ----------------------------------------------------------------------- /// events /// ----------------------------------------------------------------------- /// @notice New vesting stream created /// @param id Id of vesting stream /// @param token Address of token to vest (0x0 for ETH) /// @param amount Amount to vest event CreateVestingStream( uint256 indexed id, address indexed token, uint256 amount ); /// @notice Release from vesting stream /// @param id Id of vesting stream /// @param amount Amount released from stream event ReleaseFromVestingStream(uint256 indexed id, uint256 amount); /// @notice Emitted after each successful ETH transfer to proxy /// @param amount Amount of ETH received event ReceiveETH(uint256 amount); /// ----------------------------------------------------------------------- /// structs /// ----------------------------------------------------------------------- /// @notice holds vesting stream metadata struct VestingStream { address token; uint256 vestingStart; uint256 total; uint256 released; } /// ----------------------------------------------------------------------- /// storage /// ----------------------------------------------------------------------- /// Address to receive funds after vesting /// @dev equivalent to address public immutable beneficiary; function beneficiary() public pure returns (address) { return _getArgAddress(0); } /// Period of time for funds to vest (defaults to 365 days) /// @dev equivalent to uint256 public immutable vestingPeriod; function vestingPeriod() public pure returns (uint256) { return _getArgUint256(20); } /// Number of vesting streams /// @dev Used for sequential ids uint256 public numVestingStreams; /// Mapping from Id to vesting stream mapping(uint256 => VestingStream) internal vestingStreams; /// Mapping from token to amount vesting (includes current & previous) mapping(address => uint256) public vesting; /// Mapping from token to amount released mapping(address => uint256) public released; /// ----------------------------------------------------------------------- /// constructor /// ----------------------------------------------------------------------- // solhint-disable-next-line no-empty-blocks constructor() {} /// ----------------------------------------------------------------------- /// functions /// ----------------------------------------------------------------------- /// ----------------------------------------------------------------------- /// functions - public & external /// ----------------------------------------------------------------------- /// @notice receive ETH /// @dev receive with emitted event is implemented w/i clone bytecode /* receive() external payable { */ /* emit ReceiveETH(msg.value); */ /* } */ /// @notice Creates new vesting streams /// @param tokens Addresses of ETH (0x0) & ERC20s to begin vesting /// @return ids Ids of created vesting streams for {tokens} function createVestingStreams(address[] calldata tokens) external payable returns (uint256[] memory ids) { uint256 numTokens = tokens.length; ids = new uint256[](numTokens); // use count as first new sequential id uint256 vestingStreamId = numVestingStreams; unchecked { // overflow should be impossible in for-loop index for (uint256 i = 0; i < numTokens; ++i) { address token = tokens[i]; // overflow should be impossible // shouldn't need to worry about re-entrancy from ERC20 view fn // recognizes 0x0 as ETH // user chooses tokens array, pernicious ERC20 can't cause DoS // slither-disable-next-line calls-loop uint256 pendingAmount = ( token != address(0) ? ERC20(token).balanceOf(address(this)) : address(this).balance // vesting >= released ) - (vesting[token] - released[token]); vesting[token] += pendingAmount; // overflow should be impossible vestingStreams[vestingStreamId] = VestingStream({ token: token, vestingStart: block.timestamp, // solhint-disable-line not-rely-on-time total: pendingAmount, released: 0 }); emit CreateVestingStream(vestingStreamId, token, pendingAmount); ids[i] = vestingStreamId; ++vestingStreamId; } // use last created id as new count numVestingStreams = vestingStreamId; } } /// @notice Releases vested funds to the beneficiary /// @param ids Ids of vesting streams to release funds from /// @return releasedFunds Amounts of funds released from vesting streams {ids} function releaseFromVesting(uint256[] calldata ids) external payable returns (uint256[] memory releasedFunds) { uint256 numIds = ids.length; releasedFunds = new uint256[](numIds); unchecked { // overflow should be impossible in for-loop index for (uint256 i = 0; i < numIds; ++i) { uint256 id = ids[i]; if (id >= numVestingStreams) revert InvalidVestingStreamId(id); VestingStream memory vs = vestingStreams[id]; uint256 transferAmount = _vestedAndUnreleased(vs); address token = vs.token; // overflow should be impossible vestingStreams[id].released += transferAmount; // overflow should be impossible released[token] += transferAmount; // don't need to worry about re-entrancy; funds can't be stolen from beneficiary // pernicious ERC20s would only mess their own storage, not brick the balance of any ERC20 or ETH if (token != address(0)) { ERC20(token).safeTransfer(beneficiary(), transferAmount); } else { beneficiary().safeTransferETH(transferAmount); } emit ReleaseFromVestingStream(id, transferAmount); releasedFunds[i] = transferAmount; } } } /// ----------------------------------------------------------------------- /// functions - views /// ----------------------------------------------------------------------- /// @notice View vesting stream {id} /// @param id Id of vesting stream to view /// @return vs Vesting stream function vestingStream(uint256 id) external view returns (VestingStream memory vs) { vs = vestingStreams[id]; } /// @notice View vested amount in vesting stream {id} /// @param id Id of vesting stream to get vested amount of /// @return Amount vested in vesting stream {id} function vested(uint256 id) external view returns (uint256) { VestingStream memory vs = vestingStreams[id]; return _vested(vs); } /// @notice View vested-and-unreleased amount in vesting stream {id} /// @param id Id of vesting stream to get vested-and-unreleased amount of /// @return Amount vested-and-unreleased in vesting stream {id} function vestedAndUnreleased(uint256 id) external view returns (uint256) { VestingStream memory vs = vestingStreams[id]; return _vestedAndUnreleased(vs); } /// ----------------------------------------------------------------------- /// functions - private & internal /// ----------------------------------------------------------------------- /// @notice View vested amount in vesting stream {vs} /// @param vs Vesting stream to get vested amount of /// @return Amount vested in vesting stream {vs} function _vested(VestingStream memory vs) internal view returns (uint256) { uint256 elapsedTime; unchecked { // block.timestamp >= vs.vestingStart for any existing stream // solhint-disable-next-line not-rely-on-time elapsedTime = block.timestamp - vs.vestingStart; } return elapsedTime >= vestingPeriod() ? vs.total : FullMath.mulDiv(vs.total, elapsedTime, vestingPeriod()); } /// @notice View vested-and-unreleased amount in vesting stream {vs} /// @param vs Vesting stream to get vested-and-unreleased amount of /// @return Amount vested-and-unreleased in vesting stream {vs} function _vestedAndUnreleased(VestingStream memory vs) internal view returns (uint256) { unchecked { // underflow should be impossible return _vested(vs) - vs.released; } } }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.4; /// @title Clone /// @author zefram.eth /// @notice Provides helper functions for reading immutable args from calldata contract Clone { /// @notice Reads an immutable arg with type address /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint256 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := calldataload(add(offset, argOffset)) } } /// @notice Reads a uint256 array stored in the immutable args. /// @param argOffset The offset of the arg in the packed data /// @param arrLen Number of elements in the array /// @return arr The array function _getArgUint256Array(uint256 argOffset, uint64 arrLen) internal pure returns (uint256[] memory arr) { uint256 offset = _getImmutableArgsOffset(); uint256 el; arr = new uint256[](arrLen); for (uint64 i = 0; i < arrLen; i++) { // solhint-disable-next-line no-inline-assembly assembly { el := calldataload(add(add(offset, argOffset), mul(i, 32))) } arr[i] = el; } return arr; } /// @notice Reads an immutable arg with type uint64 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint8 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /// @return offset The offset of the packed immutable args in calldata function _getImmutableArgsOffset() internal pure returns (uint256 offset) { // solhint-disable-next-line no-inline-assembly assembly { offset := sub( calldatasize(), add(shr(240, calldataload(sub(calldatasize(), 2))), 2) ) } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { event Debug(bool one, bool two, uint256 retsize); /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits /// from https://github.com/ZeframLou/vested-erc20/blob/main/src/lib/FullMath.sol library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (type(uint256).max - denominator + 1) & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { result = mulDiv(a, b, denominator); unchecked { if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } } }
{ "remappings": [ "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "ds-test/=lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solmate/=lib/solmate/src/", "splits-contracts/=lib/splits-contracts/contracts/", "src/=src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london" }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"InvalidVestingStreamId","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CreateVestingStream","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceiveETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReleaseFromVestingStream","type":"event"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"createVestingStreams","outputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"numVestingStreams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"releaseFromVesting","outputs":[{"internalType":"uint256[]","name":"releasedFunds","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"released","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"vested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"vestedAndUnreleased","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vesting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"vestingStream","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"vestingStart","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"released","type":"uint256"}],"internalType":"struct VestingModule.VestingStream","name":"vs","type":"tuple"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50610af5806100206000396000f3fe6080604052600436106100915760003560e01c8063968fb8ba11610059578063968fb8ba1461018b5780639852595c146101ab578063a8b93e96146101d8578063cba7d6a9146101ee578063e388c4231461020157600080fd5b80632d18680e1461009657806338af3eed146100fb57806363efa49c146101285780637313ee5a146101565780639522873a1461016b575b600080fd5b3480156100a257600080fd5b506100b66100b1366004610966565b61022e565b6040516100f2919081516001600160a01b0316815260208083015190820152604080830151908201526060918201519181019190915260800190565b60405180910390f35b34801561010757600080fd5b506101106102af565b6040516001600160a01b0390911681526020016100f2565b34801561013457600080fd5b50610148610143366004610966565b6102c0565b6040519081526020016100f2565b34801561016257600080fd5b50610148610313565b61017e6101793660046109cb565b61031f565b6040516100f29190610a0d565b34801561019757600080fd5b506101486101a6366004610966565b61052c565b3480156101b757600080fd5b506101486101c6366004610a51565b60036020526000908152604090205481565b3480156101e457600080fd5b5061014860005481565b61017e6101fc3660046109cb565b610578565b34801561020d57600080fd5b5061014861021c366004610a51565b60026020526000908152604090205481565b610262604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b50600090815260016020818152604092839020835160808101855281546001600160a01b031681529281015491830191909152600281015492820192909252600390910154606082015290565b60006102bb600061074a565b905090565b6000818152600160208181526040808420815160808101835281546001600160a01b03168152938101549284019290925260028201549083015260030154606082015261030c8161076f565b9392505050565b60006102bb6014610786565b6060818067ffffffffffffffff81111561033b5761033b610a7a565b604051908082528060200260200182016040528015610364578160200160208202803683370190505b50600080549193505b8281101561052157600086868381811061038957610389610a90565b905060200201602081019061039e9190610a51565b6001600160a01b0381166000818152600360209081526040808320546002909252822054939450909203906103d3574761043b565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015610417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043b9190610aa6565b6001600160a01b038481166000818152600260208181526040808420805498909703978801909655855160808101875284815242818301908152818801898152606083018681528e87526001808652968a9020935184546001600160a01b031916991698909817835590519482019490945592519183019190915592516003909101559151838152929350909186917f9e99aba6e66a741d0793c014d6c18190a51f3559baaa8f5ce5c2cf3f685ded24910160405180910390a38386848151811061050857610508610a90565b602090810291909101015250506001918201910161036d565b506000555092915050565b6000818152600160208181526040808420815160808101835281546001600160a01b03168152938101549284019290925260028201549083015260030154606082015261030c816107a8565b6060818067ffffffffffffffff81111561059457610594610a7a565b6040519080825280602002602001820160405280156105bd578160200160208202803683370190505b50915060005b818110156107425760008585838181106105df576105df610a90565b90506020020135905060005481106106125760405163a94be08960e01b8152600481018290526024015b60405180910390fd5b6000818152600160208181526040808420815160808101835281546001600160a01b0316815293810154928401929092526002820154908301526003015460608201529061065f8261076f565b8251600085815260016020908152604080832060039081018054870190556001600160a01b038516808552925290912080548401905591925090156106bf576106ba6106a96102af565b6001600160a01b03831690846107e5565b6106da565b6106da826106cb6102af565b6001600160a01b031690610863565b837fac35c653955afa008e3d71e6d91e6feeff42bcc2eb62b48e4472beafe89ad4268360405161070c91815260200190565b60405180910390a28187868151811061072757610727610a90565b602002602001018181525050505050508060010190506105c3565b505092915050565b600080610761600119368181013560f01c90030190565b929092013560601c92915050565b6000816060015161077f836107a8565b0392915050565b60008061079d600119368181013560f01c90030190565b929092013592915050565b602081015160009042036107ba610313565b8110156107dc576107d78360400151826107d2610313565b6108b9565b61030c565b50506040015190565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061085d5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610609565b50505050565b600080600080600085875af19050806108b45760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610609565b505050565b60008080600019858709858702925082811083820303915050806000036108f257600084116108e757600080fd5b50829004905061030c565b8084116108fe57600080fd5b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b60006020828403121561097857600080fd5b5035919050565b60008083601f84011261099157600080fd5b50813567ffffffffffffffff8111156109a957600080fd5b6020830191508360208260051b85010111156109c457600080fd5b9250929050565b600080602083850312156109de57600080fd5b823567ffffffffffffffff8111156109f557600080fd5b610a018582860161097f565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b81811015610a4557835183529284019291840191600101610a29565b50909695505050505050565b600060208284031215610a6357600080fd5b81356001600160a01b038116811461030c57600080fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215610ab857600080fd5b505191905056fea2646970667358221220b92ac1519118e1a2a9e7f1f1e8e58e395a04eda59f458e5ad78160c405fd333a64736f6c634300080d0033
Deployed Bytecode
0x6080604052600436106100915760003560e01c8063968fb8ba11610059578063968fb8ba1461018b5780639852595c146101ab578063a8b93e96146101d8578063cba7d6a9146101ee578063e388c4231461020157600080fd5b80632d18680e1461009657806338af3eed146100fb57806363efa49c146101285780637313ee5a146101565780639522873a1461016b575b600080fd5b3480156100a257600080fd5b506100b66100b1366004610966565b61022e565b6040516100f2919081516001600160a01b0316815260208083015190820152604080830151908201526060918201519181019190915260800190565b60405180910390f35b34801561010757600080fd5b506101106102af565b6040516001600160a01b0390911681526020016100f2565b34801561013457600080fd5b50610148610143366004610966565b6102c0565b6040519081526020016100f2565b34801561016257600080fd5b50610148610313565b61017e6101793660046109cb565b61031f565b6040516100f29190610a0d565b34801561019757600080fd5b506101486101a6366004610966565b61052c565b3480156101b757600080fd5b506101486101c6366004610a51565b60036020526000908152604090205481565b3480156101e457600080fd5b5061014860005481565b61017e6101fc3660046109cb565b610578565b34801561020d57600080fd5b5061014861021c366004610a51565b60026020526000908152604090205481565b610262604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b50600090815260016020818152604092839020835160808101855281546001600160a01b031681529281015491830191909152600281015492820192909252600390910154606082015290565b60006102bb600061074a565b905090565b6000818152600160208181526040808420815160808101835281546001600160a01b03168152938101549284019290925260028201549083015260030154606082015261030c8161076f565b9392505050565b60006102bb6014610786565b6060818067ffffffffffffffff81111561033b5761033b610a7a565b604051908082528060200260200182016040528015610364578160200160208202803683370190505b50600080549193505b8281101561052157600086868381811061038957610389610a90565b905060200201602081019061039e9190610a51565b6001600160a01b0381166000818152600360209081526040808320546002909252822054939450909203906103d3574761043b565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015610417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043b9190610aa6565b6001600160a01b038481166000818152600260208181526040808420805498909703978801909655855160808101875284815242818301908152818801898152606083018681528e87526001808652968a9020935184546001600160a01b031916991698909817835590519482019490945592519183019190915592516003909101559151838152929350909186917f9e99aba6e66a741d0793c014d6c18190a51f3559baaa8f5ce5c2cf3f685ded24910160405180910390a38386848151811061050857610508610a90565b602090810291909101015250506001918201910161036d565b506000555092915050565b6000818152600160208181526040808420815160808101835281546001600160a01b03168152938101549284019290925260028201549083015260030154606082015261030c816107a8565b6060818067ffffffffffffffff81111561059457610594610a7a565b6040519080825280602002602001820160405280156105bd578160200160208202803683370190505b50915060005b818110156107425760008585838181106105df576105df610a90565b90506020020135905060005481106106125760405163a94be08960e01b8152600481018290526024015b60405180910390fd5b6000818152600160208181526040808420815160808101835281546001600160a01b0316815293810154928401929092526002820154908301526003015460608201529061065f8261076f565b8251600085815260016020908152604080832060039081018054870190556001600160a01b038516808552925290912080548401905591925090156106bf576106ba6106a96102af565b6001600160a01b03831690846107e5565b6106da565b6106da826106cb6102af565b6001600160a01b031690610863565b837fac35c653955afa008e3d71e6d91e6feeff42bcc2eb62b48e4472beafe89ad4268360405161070c91815260200190565b60405180910390a28187868151811061072757610727610a90565b602002602001018181525050505050508060010190506105c3565b505092915050565b600080610761600119368181013560f01c90030190565b929092013560601c92915050565b6000816060015161077f836107a8565b0392915050565b60008061079d600119368181013560f01c90030190565b929092013592915050565b602081015160009042036107ba610313565b8110156107dc576107d78360400151826107d2610313565b6108b9565b61030c565b50506040015190565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061085d5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610609565b50505050565b600080600080600085875af19050806108b45760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610609565b505050565b60008080600019858709858702925082811083820303915050806000036108f257600084116108e757600080fd5b50829004905061030c565b8084116108fe57600080fd5b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b60006020828403121561097857600080fd5b5035919050565b60008083601f84011261099157600080fd5b50813567ffffffffffffffff8111156109a957600080fd5b6020830191508360208260051b85010111156109c457600080fd5b9250929050565b600080602083850312156109de57600080fd5b823567ffffffffffffffff8111156109f557600080fd5b610a018582860161097f565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b81811015610a4557835183529284019291840191600101610a29565b50909695505050505050565b600060208284031215610a6357600080fd5b81356001600160a01b038116811461030c57600080fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215610ab857600080fd5b505191905056fea2646970667358221220b92ac1519118e1a2a9e7f1f1e8e58e395a04eda59f458e5ad78160c405fd333a64736f6c634300080d0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.