ETH Price: $2,460.99 (+1.36%)

Transaction Decoder

Block:
15925780 at Nov-08-2022 02:01:47 PM +UTC
Transaction Fee:
0.005277310510252212 ETH $12.99
Gas Used:
233,886 Gas / 22.563601542 Gwei

Emitted Events:

131 MinimalProxyFactory.VestingCreated( _address=TokenVesting, _salt=528DE7F96B05E0A63A96A6D7516BF21C78D7C28FB2E1979261F8BC89C6C1C882 )

Account State Difference:

  Address   Before After State Difference Code
0x2a686603...4179b2bfe
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 497590261154554171967156586787122471106440107807153512328890344666462105717985034783424382868411422026324979
(beaverbuild)
3.131838456746360789 Eth3.132189285746360789 Eth0.000350829
0xBef99f5f...e1386a9b0
0.800297864612942844 Eth
Nonce: 66
0.795020554102690632 Eth
Nonce: 67
0.005277310510252212
0xE3572735...53FD3f6d0

Execution Trace

BatchVestings.createVestings( _factory=0xE357273545C152f07afE2c38257B7b653FD3f6d0, _implementation=0x42F32e19365D8045661A006408Cc6d1064039FbF, _salt=88A065F11EB7A9D5EF074D5452A8487C34C91EAD089BB2ADA374D6933731C632, _datas=[hBvuDQAAAAAAAAAAAAAAAIkhTIyppJ5go7+o4AVE84TJNxmxAAAAAAAAAAAAAAAAPGcwIn9Xhbo36NRGTb+aHYfk8KwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY2lxlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ40AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADtTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAGsXVHTokJTETamLlU7t6sSVJx0P] )
  • MinimalProxyFactory.createVesting( _implementation=0x42F32e19365D8045661A006408Cc6d1064039FbF, _salt=528DE7F96B05E0A63A96A6D7516BF21C78D7C28FB2E1979261F8BC89C6C1C882, _data=0x841BEE0D00000000000000000000000089214C8CA9A49E60A3BFA8E00544F384C93719B10000000000000000000000003C6730227F5785BA37E8D4464DBF9A1D87E4F0AC00000000000000000000000000000000000000000000000000000000636971940000000000000000000000000000000000000000000000000000000000278D000000000000000000000000000000000000000000000000000000000000ED4E0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006B175474E89094C44DA98B954EEDEAC495271D0F ) => ( addr=0x2a6866032afbCB3cee58BEE4a1EeD054179b2bfe )
    • TokenVesting.3d602d80( )
    • TokenVesting.initialize( _owner=0x89214c8Ca9A49E60a3bfa8e00544F384C93719b1, _beneficiary=0x3C6730227F5785bA37e8d4464DBF9A1D87e4f0AC, _start=1667854740, _cliff=2592000, _duration=15552000, _revocable=True, _token=0x6B175474E89094C44Da98b954EedeAC495271d0F )
      • TokenVesting.initialize( _owner=0x89214c8Ca9A49E60a3bfa8e00544F384C93719b1, _beneficiary=0x3C6730227F5785bA37e8d4464DBF9A1D87e4f0AC, _start=1667854740, _cliff=2592000, _duration=15552000, _revocable=True, _token=0x6B175474E89094C44Da98b954EedeAC495271d0F )
        File 1 of 4: BatchVestings
        // SPDX-License-Identifier: MIT
        
        pragma solidity ^0.8.0;
        
        interface IVestingFactory {
        	function createVesting(
        		address _implementation,
        		bytes32 _salt,
        		bytes calldata _data
        	) external returns (address addr);
        }
        
        contract BatchVestings {
        	function createVestings(
        		IVestingFactory _factory,
        		address _implementation,
        		bytes32 _salt,
        		bytes[] calldata _datas
        	) external {
        		for (uint256 i = 0; i < _datas.length; i++) {
        			_factory.createVesting(_implementation, keccak256(abi.encode(_salt, i)), _datas[i]);
        		}
        	}
        }

        File 2 of 4: MinimalProxyFactory
        // SPDX-License-Identifier: MIT
        
        pragma solidity ^0.6.2;
        
        /**
         * @dev Collection of functions related to the address type
         */
        library Address {
            /**
             * @dev Returns true if `account` is a contract.
             *
             * [IMPORTANT]
             * ====
             * It is unsafe to assume that an address for which this function returns
             * false is an externally-owned account (EOA) and not a contract.
             *
             * Among others, `isContract` will return false for the following
             * types of addresses:
             *
             *  - an externally-owned account
             *  - a contract in construction
             *  - an address where a contract will be created
             *  - an address where a contract lived, but was destroyed
             * ====
             */
            function isContract(address account) internal view returns (bool) {
                // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
                // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
                // for accounts without code, i.e. `keccak256('')`
                bytes32 codehash;
                bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
                // solhint-disable-next-line no-inline-assembly
                assembly { codehash := extcodehash(account) }
                return (codehash != accountHash && codehash != 0x0);
            }
        
            /**
             * @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");
        
                // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                (bool success, ) = recipient.call{ value: amount }("");
                require(success, "Address: unable to send value, recipient may have reverted");
            }
        
            /**
             * @dev Performs a Solidity function call using a low level `call`. A
             * plain`call` is an unsafe replacement for a function call: use this
             * function instead.
             *
             * If `target` reverts with a revert reason, it is bubbled up by this
             * function (like regular Solidity function calls).
             *
             * Returns the raw returned data. To convert to the expected return value,
             * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
             *
             * Requirements:
             *
             * - `target` must be a contract.
             * - calling `target` with `data` must not revert.
             *
             * _Available since v3.1._
             */
            function functionCall(address target, bytes memory data) internal returns (bytes memory) {
              return functionCall(target, data, "Address: low-level call failed");
            }
        
            /**
             * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
             * `errorMessage` as a fallback revert reason when `target` reverts.
             *
             * _Available since v3.1._
             */
            function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                return _functionCallWithValue(target, data, 0, errorMessage);
            }
        
            /**
             * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
             * but also transferring `value` wei to `target`.
             *
             * Requirements:
             *
             * - the calling contract must have an ETH balance of at least `value`.
             * - the called Solidity function must be `payable`.
             *
             * _Available since v3.1._
             */
            function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
            }
        
            /**
             * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
             * with `errorMessage` as a fallback revert reason when `target` reverts.
             *
             * _Available since v3.1._
             */
            function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                require(address(this).balance >= value, "Address: insufficient balance for call");
                return _functionCallWithValue(target, data, value, errorMessage);
            }
        
            function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
                require(isContract(target), "Address: call to non-contract");
        
                // solhint-disable-next-line avoid-low-level-calls
                (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
                if (success) {
                    return returndata;
                } else {
                    // Look for revert reason and bubble it up if present
                    if (returndata.length > 0) {
                        // The easiest way to bubble the revert reason is using memory via assembly
        
                        // solhint-disable-next-line no-inline-assembly
                        assembly {
                            let returndata_size := mload(returndata)
                            revert(add(32, returndata), returndata_size)
                        }
                    } else {
                        revert(errorMessage);
                    }
                }
            }
        }
        
        
        
        contract MinimalProxyFactory {
            using Address for address;
        
            event VestingCreated(address indexed _address, bytes32 _salt);
        
            constructor() public {
            }
        
            function createVesting(address _implementation, bytes32 _salt, bytes memory _data) public virtual returns (address addr) {
                bytes32 salt = keccak256(abi.encodePacked(_salt, msg.sender));
        
                // solium-disable-next-line security/no-inline-assembly
                bytes memory slotcode = abi.encodePacked(
                    hex"3d602d80600a3d3981f3363d3d373d3d3d363d73",
                    _implementation,
                    hex"5af43d82803e903d91602b57fd5bf3"
                );
        
                assembly {
                    addr := create2(0, add(slotcode, 0x20), mload(slotcode), salt)
                }
                require(addr != address(0), "MinimalProxyFactory#createVesting: CREATION_FAILED");
        
                emit VestingCreated(addr, _salt);
        
                if (_data.length > 0) {
                    (bool success,) = addr.call(_data);
                    require(success, "MinimalProxyFactory#createVesting: CALL_FAILED");
                }
            }
        }

        File 3 of 4: TokenVesting
        pragma solidity ^0.4.13;
        
        library Math {
          function max64(uint64 a, uint64 b) internal constant returns (uint64) {
            return a >= b ? a : b;
          }
        
          function min64(uint64 a, uint64 b) internal constant returns (uint64) {
            return a < b ? a : b;
          }
        
          function max256(uint256 a, uint256 b) internal constant returns (uint256) {
            return a >= b ? a : b;
          }
        
          function min256(uint256 a, uint256 b) internal constant returns (uint256) {
            return a < b ? a : b;
          }
        }
        
        library SafeMath {
          function mul(uint256 a, uint256 b) internal constant returns (uint256) {
            uint256 c = a * b;
            assert(a == 0 || c / a == b);
            return c;
          }
        
          function div(uint256 a, uint256 b) internal constant returns (uint256) {
            // assert(b > 0); // Solidity automatically throws when dividing by 0
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return c;
          }
        
          function sub(uint256 a, uint256 b) internal constant returns (uint256) {
            assert(b <= a);
            return a - b;
          }
        
          function add(uint256 a, uint256 b) internal constant returns (uint256) {
            uint256 c = a + b;
            assert(c >= a);
            return c;
          }
        }
        
        contract Ownable {
          address public owner;
        
        
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        
        
          /**
           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
           * account.
           */
          function Ownable() {
            owner = msg.sender;
          }
        
        
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
            require(msg.sender == owner);
            _;
          }
        
        
          /**
           * @dev Allows the current owner to transfer control of the contract to a newOwner.
           * @param newOwner The address to transfer ownership to.
           */
          function transferOwnership(address newOwner) onlyOwner public {
            require(newOwner != address(0));
            OwnershipTransferred(owner, newOwner);
            owner = newOwner;
          }
        
        }
        
        contract ERC20Basic {
          uint256 public totalSupply;
          function balanceOf(address who) public constant returns (uint256);
          function transfer(address to, uint256 value) public returns (bool);
          event Transfer(address indexed from, address indexed to, uint256 value);
        }
        
        contract ERC20 is ERC20Basic {
          function allowance(address owner, address spender) public constant returns (uint256);
          function transferFrom(address from, address to, uint256 value) public returns (bool);
          function approve(address spender, uint256 value) public returns (bool);
          event Approval(address indexed owner, address indexed spender, uint256 value);
        }
        
        library SafeERC20 {
          function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
            assert(token.transfer(to, value));
          }
        
          function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
            assert(token.transferFrom(from, to, value));
          }
        
          function safeApprove(ERC20 token, address spender, uint256 value) internal {
            assert(token.approve(spender, value));
          }
        }
        
        contract TokenVesting is Ownable {
          using SafeMath for uint256;
          using SafeERC20 for ERC20;
        
          event Released(uint256 amount);
          event Revoked();
        
          // beneficiary of tokens after they are released
          address public beneficiary;
        
          uint256 public cliff;
          uint256 public start;
          uint256 public duration;
        
          bool public revocable;
          bool public revoked;
          bool public initialized;
        
          uint256 public released;
        
          ERC20 public token;
        
          /**
           * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
           * _beneficiary, gradually in a linear fashion until _start + _duration. By then all
           * of the balance will have vested.
           * @param _beneficiary address of the beneficiary to whom vested tokens are transferred
           * @param _cliff duration in seconds of the cliff in which tokens will begin to vest
           * @param _duration duration in seconds of the period in which the tokens will vest
           * @param _revocable whether the vesting is revocable or not
           * @param _token address of the ERC20 token contract
           */
          function initialize(
            address _owner,
            address _beneficiary,
            uint256 _start,
            uint256 _cliff,
            uint256 _duration,
            bool    _revocable,
            address _token
          ) public {
            require(!initialized);
            require(_beneficiary != 0x0);
            require(_cliff <= _duration);
        
            initialized = true;
            owner       = _owner;
            beneficiary = _beneficiary;
            start       = _start;
            cliff       = _start.add(_cliff);
            duration    = _duration;
            revocable   = _revocable;
            token       = ERC20(_token);
          }
        
          /**
           * @notice Only allow calls from the beneficiary of the vesting contract
           */
          modifier onlyBeneficiary() {
            require(msg.sender == beneficiary);
            _;
          }
        
          /**
           * @notice Allow the beneficiary to change its address
           * @param target the address to transfer the right to
           */
          function changeBeneficiary(address target) onlyBeneficiary public {
            require(target != 0);
            beneficiary = target;
          }
        
          /**
           * @notice Transfers vested tokens to beneficiary.
           */
          function release() onlyBeneficiary public {
            require(now >= cliff);
            _releaseTo(beneficiary);
          }
        
          /**
           * @notice Transfers vested tokens to a target address.
           * @param target the address to send the tokens to
           */
          function releaseTo(address target) onlyBeneficiary public {
            require(now >= cliff);
            _releaseTo(target);
          }
        
          /**
           * @notice Transfers vested tokens to beneficiary.
           */
          function _releaseTo(address target) internal {
            uint256 unreleased = releasableAmount();
        
            released = released.add(unreleased);
        
            token.safeTransfer(target, unreleased);
        
            Released(released);
          }
        
          /**
           * @notice Allows the owner to revoke the vesting. Tokens already vested are sent to the beneficiary.
           */
          function revoke() onlyOwner public {
            require(revocable);
            require(!revoked);
        
            // Release all vested tokens
            _releaseTo(beneficiary);
        
            // Send the remainder to the owner
            token.safeTransfer(owner, token.balanceOf(this));
        
            revoked = true;
        
            Revoked();
          }
        
        
          /**
           * @dev Calculates the amount that has already vested but hasn't been released yet.
           */
          function releasableAmount() public constant returns (uint256) {
            return vestedAmount().sub(released);
          }
        
          /**
           * @dev Calculates the amount that has already vested.
           */
          function vestedAmount() public constant returns (uint256) {
            uint256 currentBalance = token.balanceOf(this);
            uint256 totalBalance = currentBalance.add(released);
        
            if (now < cliff) {
              return 0;
            } else if (now >= start.add(duration) || revoked) {
              return totalBalance;
            } else {
              return totalBalance.mul(now.sub(start)).div(duration);
            }
          }
        
          /**
           * @notice Allow withdrawing any token other than the relevant one
           */
          function releaseForeignToken(ERC20 _token, uint256 amount) onlyOwner {
            require(_token != token);
            _token.transfer(owner, amount);
          }
        }

        File 4 of 4: TokenVesting
        pragma solidity ^0.4.13;
        
        library Math {
          function max64(uint64 a, uint64 b) internal constant returns (uint64) {
            return a >= b ? a : b;
          }
        
          function min64(uint64 a, uint64 b) internal constant returns (uint64) {
            return a < b ? a : b;
          }
        
          function max256(uint256 a, uint256 b) internal constant returns (uint256) {
            return a >= b ? a : b;
          }
        
          function min256(uint256 a, uint256 b) internal constant returns (uint256) {
            return a < b ? a : b;
          }
        }
        
        library SafeMath {
          function mul(uint256 a, uint256 b) internal constant returns (uint256) {
            uint256 c = a * b;
            assert(a == 0 || c / a == b);
            return c;
          }
        
          function div(uint256 a, uint256 b) internal constant returns (uint256) {
            // assert(b > 0); // Solidity automatically throws when dividing by 0
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return c;
          }
        
          function sub(uint256 a, uint256 b) internal constant returns (uint256) {
            assert(b <= a);
            return a - b;
          }
        
          function add(uint256 a, uint256 b) internal constant returns (uint256) {
            uint256 c = a + b;
            assert(c >= a);
            return c;
          }
        }
        
        contract Ownable {
          address public owner;
        
        
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        
        
          /**
           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
           * account.
           */
          function Ownable() {
            owner = msg.sender;
          }
        
        
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
            require(msg.sender == owner);
            _;
          }
        
        
          /**
           * @dev Allows the current owner to transfer control of the contract to a newOwner.
           * @param newOwner The address to transfer ownership to.
           */
          function transferOwnership(address newOwner) onlyOwner public {
            require(newOwner != address(0));
            OwnershipTransferred(owner, newOwner);
            owner = newOwner;
          }
        
        }
        
        contract ERC20Basic {
          uint256 public totalSupply;
          function balanceOf(address who) public constant returns (uint256);
          function transfer(address to, uint256 value) public returns (bool);
          event Transfer(address indexed from, address indexed to, uint256 value);
        }
        
        contract ERC20 is ERC20Basic {
          function allowance(address owner, address spender) public constant returns (uint256);
          function transferFrom(address from, address to, uint256 value) public returns (bool);
          function approve(address spender, uint256 value) public returns (bool);
          event Approval(address indexed owner, address indexed spender, uint256 value);
        }
        
        library SafeERC20 {
          function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
            assert(token.transfer(to, value));
          }
        
          function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
            assert(token.transferFrom(from, to, value));
          }
        
          function safeApprove(ERC20 token, address spender, uint256 value) internal {
            assert(token.approve(spender, value));
          }
        }
        
        contract TokenVesting is Ownable {
          using SafeMath for uint256;
          using SafeERC20 for ERC20;
        
          event Released(uint256 amount);
          event Revoked();
        
          // beneficiary of tokens after they are released
          address public beneficiary;
        
          uint256 public cliff;
          uint256 public start;
          uint256 public duration;
        
          bool public revocable;
          bool public revoked;
          bool public initialized;
        
          uint256 public released;
        
          ERC20 public token;
        
          /**
           * @dev Creates a vesting contract that vests its balance of any ERC20 token to the
           * _beneficiary, gradually in a linear fashion until _start + _duration. By then all
           * of the balance will have vested.
           * @param _beneficiary address of the beneficiary to whom vested tokens are transferred
           * @param _cliff duration in seconds of the cliff in which tokens will begin to vest
           * @param _duration duration in seconds of the period in which the tokens will vest
           * @param _revocable whether the vesting is revocable or not
           * @param _token address of the ERC20 token contract
           */
          function initialize(
            address _owner,
            address _beneficiary,
            uint256 _start,
            uint256 _cliff,
            uint256 _duration,
            bool    _revocable,
            address _token
          ) public {
            require(!initialized);
            require(_beneficiary != 0x0);
            require(_cliff <= _duration);
        
            initialized = true;
            owner       = _owner;
            beneficiary = _beneficiary;
            start       = _start;
            cliff       = _start.add(_cliff);
            duration    = _duration;
            revocable   = _revocable;
            token       = ERC20(_token);
          }
        
          /**
           * @notice Only allow calls from the beneficiary of the vesting contract
           */
          modifier onlyBeneficiary() {
            require(msg.sender == beneficiary);
            _;
          }
        
          /**
           * @notice Allow the beneficiary to change its address
           * @param target the address to transfer the right to
           */
          function changeBeneficiary(address target) onlyBeneficiary public {
            require(target != 0);
            beneficiary = target;
          }
        
          /**
           * @notice Transfers vested tokens to beneficiary.
           */
          function release() onlyBeneficiary public {
            require(now >= cliff);
            _releaseTo(beneficiary);
          }
        
          /**
           * @notice Transfers vested tokens to a target address.
           * @param target the address to send the tokens to
           */
          function releaseTo(address target) onlyBeneficiary public {
            require(now >= cliff);
            _releaseTo(target);
          }
        
          /**
           * @notice Transfers vested tokens to beneficiary.
           */
          function _releaseTo(address target) internal {
            uint256 unreleased = releasableAmount();
        
            released = released.add(unreleased);
        
            token.safeTransfer(target, unreleased);
        
            Released(released);
          }
        
          /**
           * @notice Allows the owner to revoke the vesting. Tokens already vested are sent to the beneficiary.
           */
          function revoke() onlyOwner public {
            require(revocable);
            require(!revoked);
        
            // Release all vested tokens
            _releaseTo(beneficiary);
        
            // Send the remainder to the owner
            token.safeTransfer(owner, token.balanceOf(this));
        
            revoked = true;
        
            Revoked();
          }
        
        
          /**
           * @dev Calculates the amount that has already vested but hasn't been released yet.
           */
          function releasableAmount() public constant returns (uint256) {
            return vestedAmount().sub(released);
          }
        
          /**
           * @dev Calculates the amount that has already vested.
           */
          function vestedAmount() public constant returns (uint256) {
            uint256 currentBalance = token.balanceOf(this);
            uint256 totalBalance = currentBalance.add(released);
        
            if (now < cliff) {
              return 0;
            } else if (now >= start.add(duration) || revoked) {
              return totalBalance;
            } else {
              return totalBalance.mul(now.sub(start)).div(duration);
            }
          }
        
          /**
           * @notice Allow withdrawing any token other than the relevant one
           */
          function releaseForeignToken(ERC20 _token, uint256 amount) onlyOwner {
            require(_token != token);
            _token.transfer(owner, amount);
          }
        }