ETH Price: $1,891.42 (-1.31%)

Transaction Decoder

Block:
19614571 at Apr-09-2024 12:39:23 AM +UTC
Transaction Fee:
0.001270719726544607 ETH $2.40
Gas Used:
61,147 Gas / 20.781391181 Gwei

Emitted Events:

55 BigTimeToken.Transfer( from=[Receiver] Vault, to=0xa908E533632FDD10623aCd2671f5db0DD199f8e5, value=4644545000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
(Lido: Execution Layer Rewards Vault)
113.958964951147227911 Eth113.959056671647227911 Eth0.0000917205
0x64Bc2cA1...824c8a194
0xdDB3cC4D...C40aA023A
9.65100725931326526 Eth
Nonce: 221390
9.649736539586720653 Eth
Nonce: 221391
0.001270719726544607

Execution Trace

Vault.sendERC20( _token=0x64Bc2cA1Be492bE7185FAA2c8835d9b824c8a194, _to=0xa908E533632FDD10623aCd2671f5db0DD199f8e5, _amount=4644545000000000000000 )
  • BigTimeToken.transfer( to=0xa908E533632FDD10623aCd2671f5db0DD199f8e5, amount=4644545000000000000000 ) => ( True )
    File 1 of 2: Vault
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/VaultERC20.sol";
    import "src/VaultERC721.sol";
    import "src/VaultETH.sol";
    import "src/VaultExecute.sol";
    import "src/VaultNewReceivers.sol";
    import "src/VaultIssueERC721.sol";
    contract Vault is
      VaultERC20,
      VaultERC721,
      VaultETH,
      VaultExecute,
      VaultNewReceivers,
      VaultIssueERC721
    {
      constructor()
        VaultERC20(1, 2, 11)
        VaultERC721(3)
        VaultETH(4, 5)
        VaultExecute(6, 7)
        VaultNewReceivers(8)
        VaultIssueERC721(9)
        Pausable(10)
      {}
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/commons/Ownable.sol";
    contract Limits is Ownable {
      error ExceededLimit(uint256 _amount, uint256 _limit);
      uint256 public ERC20Limit;
      event UpdateERC20Limit(uint256 _limit);
      modifier underLimit(uint256 _amount) {
        if (!isUnderLimit(_amount)) {
          revert ExceededLimit(_amount, ERC20Limit);
        }
        _;
      }
      function isUnderLimit(uint256 _amount) public view returns (bool) {
        return _amount <= ERC20Limit;
      }
      function updateERC20Limit(uint256 _limit) external virtual onlyOwner {
        _updateERC20Limit(_limit);
      }
      function _updateERC20Limit(uint256 _limit) internal {
        ERC20Limit = _limit;
        emit UpdateERC20Limit(_limit);
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/interfaces/IERC173.sol";
    contract Ownable is IERC173 {
      error NotOwner(address _sender, address _owner);
      error InvalidNewOwner();
      address public owner;
      constructor() {
        owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
      }
      modifier onlyOwner() {
        if (!isOwner(msg.sender)) revert NotOwner(msg.sender, owner);
        _;
      }
      function isOwner(address _owner) public view returns (bool) {
        return _owner == owner && _owner != address(0);
      }
      function transferOwnership(address _newOwner) external onlyOwner {
        if (_newOwner == address(0)) revert InvalidNewOwner();
        owner = _newOwner;
        emit OwnershipTransferred(msg.sender, _newOwner);
      }
      function rennounceOwnership() external onlyOwner {
        owner = address(0);
        emit OwnershipTransferred(msg.sender, address(0));
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/commons/Ownable.sol";
    import "src/commons/Permissions.sol";
    contract Pausable is Ownable, Permissions {
      error ContractPaused();
      event Unpaused(address _sender);
      event Paused(address _sender);
      enum State { Invalid, Unpaused, Paused }
      State internal _state = State.Unpaused;
      uint8 public immutable PERMISSION_PAUSE;
      constructor(uint8 _permissionPause) {
        PERMISSION_PAUSE = _permissionPause;
      }
      modifier notPaused() {
        if (_state == State.Paused) {
          revert ContractPaused();
        }
        _;
      }
      function isPaused() public view returns (bool) {
        return _state == State.Paused;
      }
      function pause() external onlyPermissioned(PERMISSION_PAUSE) {
        _state = State.Paused;
        emit Paused(msg.sender);
      }
      function unpause() external onlyOwner {
        _state = State.Unpaused;
        emit Unpaused(msg.sender);
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/commons/Ownable.sol";
    contract Permissions is Ownable {
      error PermissionDenied(address _sender, uint8 _permission);
      error DuplicatedPermission(uint8 _permission);
      mapping (address => bytes32) public permissions;
      mapping (uint8 => bool) public permissionExists;
      event AddPermission(address indexed _addr, uint8 _permission);
      event DelPermission(address indexed _addr, uint8 _permission);
      event ClearPermissions(address indexed _addr);
      modifier onlyPermissioned(uint8 _permission) {
        if (!hasPermission(msg.sender, _permission) && !isOwner(msg.sender)) {
          revert PermissionDenied(msg.sender, _permission);
        }
        _;
      }
      function _registerPermission(uint8 _permission) internal {
        if (permissionExists[_permission]) {
          revert DuplicatedPermission(_permission);
        }
        permissionExists[_permission] = true;
      }
      function hasPermission(address _addr, uint8 _permission) public view returns (bool) {
        return (permissions[_addr] & _maskForPermission(_permission)) != 0;
      }
      function addPermission(address _addr, uint8 _permission) external virtual onlyOwner {
        _addPermission(_addr, _permission);
      }
      function addPermissions(address _addr, uint8[] calldata _permissions) external virtual onlyOwner {
        _addPermissions(_addr, _permissions);
      }
      function delPermission(address _addr, uint8 _permission) external virtual onlyOwner {
        _delPermission(_addr, _permission);
      }
      function clearPermissions(address _addr) external virtual onlyOwner {
        _clearPermissions(_addr);
      }
      function _maskForPermission(uint8 _permission) internal pure returns (bytes32) {
        return bytes32(1 << _permission);
      }
      function _addPermission(address _addr, uint8 _permission) internal {
        permissions[_addr] |= _maskForPermission(_permission);
        emit AddPermission(_addr, _permission);
      }
      function _addPermissions(address _addr, uint8[] calldata _permissions) internal {
        unchecked {
          for (uint256 i = 0; i < _permissions.length; ++i) {
            _addPermission(_addr, _permissions[i]);
          }
        }
      }
      function _delPermission(address _addr, uint8 _permission) internal {
        permissions[_addr] &= ~_maskForPermission(_permission);
        emit DelPermission(_addr, _permission);
      }
      function _clearPermissions(address _addr) internal {
        delete permissions[_addr];
        emit ClearPermissions(_addr);
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/interfaces/IERC721Receiver.sol";
    contract Receiver is IERC721Receiver {
      error NotAuthorized(address _sender);
      address immutable private owner;
      constructor () {
        owner = msg.sender;
      }
      function execute(address payable _to, uint256 _value, bytes calldata _data) external returns (bool, bytes memory) {
        if (msg.sender != owner) revert NotAuthorized(msg.sender);
        return _to.call{ value: _value }(_data);
      }
      function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
        // return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))
        return 0x150b7a02;
      }
      receive() external payable { }
      fallback() external payable { }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/libs/CREATE2.sol";
    import "src/utils/Proxy.sol";
    import "src/commons/receiver/Receiver.sol";
    contract ReceiverHub {
      error ReceiverCallError(address _receiver, address _to, uint256 _value, bytes _data, bytes _result);
      
      address immutable public receiverTemplate;
      bytes32 immutable private receiverTemplateCreationCodeHash;
      constructor () {
        receiverTemplate = address(new Receiver());
        receiverTemplateCreationCodeHash = keccak256(Proxy.creationCode(address(receiverTemplate)));
      }
      function receiverFor(uint256 _id) public view returns (Receiver) {
        return Receiver(CREATE2.addressOf(address(this), _id, receiverTemplateCreationCodeHash));
      }
      function createReceiver(uint256 _id) internal returns (Receiver) {
        return Receiver(CREATE2.deploy(_id, Proxy.creationCode(receiverTemplate)));
      }
      function createIfNeeded(Receiver receiver, uint256 _id) internal returns (Receiver) {
        uint256 receiverCodeSize; assembly { receiverCodeSize := extcodesize(receiver) }
        if (receiverCodeSize != 0) {
          return receiver;
        }
        return createReceiver(_id);
      }
      function useReceiver(uint256 _id) internal returns (Receiver) {
        return createIfNeeded(receiverFor(_id), _id);
      }
      function executeOnReceiver(uint256 _id, address _to, uint256 _value, bytes memory _data) internal returns (bytes memory) {
        return executeOnReceiver(useReceiver(_id), _to, _value, _data);
      }
      function executeOnReceiver(Receiver _receiver, address _to, uint256 _value, bytes memory _data) internal returns (bytes memory) {
        (bool succeed, bytes memory result) = _receiver.execute(payable(_to), _value, _data);
        if (!succeed) revert ReceiverCallError(address(_receiver), _to, _value, _data, result);
        return result;
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    interface IERC173 {
      event OwnershipTransferred(address indexed _previousOwner, address indexed _newOwner);
      function owner() view external returns(address);
      function transferOwnership(address _newOwner) external;\t
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    interface IERC20 {
      event Transfer(address indexed _from, address indexed _to, uint256 _value);
      event Approval(address indexed _owner, address indexed _spender, uint256 _value);
      function totalSupply() external view returns (uint256);
      function balanceOf(address _account) external view returns (uint256);
      function transfer(address _to, uint256 _amount) external returns (bool);
      function allowance(address _owner, address _spender) external view returns (uint256);
      function approve(address _spender, uint256 _amount) external returns (bool);
      function transferFrom(address _from, address _to, uint256 _amount) external returns (bool);
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    interface IERC721 {
      event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
      event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
      event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
      function balanceOf(address _owner) external view returns (uint256);
      function ownerOf(uint256 _tokenId) external view returns (address);
      function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
      function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
      function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
      function approve(address _approved, uint256 _tokenId) external payable;
      function setApprovalForAll(address _operator, bool _approved) external;
      function getApproved(uint256 _tokenId) external view returns (address);
      function isApprovedForAll(address _owner, address _operator) external view returns (bool);
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    interface IERC721Deterministic {
      function issueToken(address _beneficiary, uint256 _optionId, uint256 _issuedId) external;
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    interface IERC721Receiver {
      function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns(bytes4);
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    library CREATE2 {
      error ContractNotCreated();
      function addressOf(address _creator, uint256 _salt, bytes32 _creationCodeHash) internal pure returns (address payable) {
        return payable(
            address(
            uint160(
              uint256(
                keccak256(
                  abi.encodePacked(
                    bytes1(0xff),
                    _creator,
                    _salt,
                    _creationCodeHash
                  )
                )
              )
            )
          )
        );
      }
      function deploy(uint256 _salt, bytes memory _creationCode) internal returns (address payable _contract) {
        assembly {
          _contract := create2(callvalue(), add(_creationCode, 32), mload(_creationCode), _salt)
        }
        if (_contract == address(0)) {
          revert ContractNotCreated();
        }
      }
    }
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.16;
    /*
    The MIT License (MIT)
    Copyright (c) 2018 Murray Software, LLC.
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:
    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    */
    //solhint-disable max-line-length
    //solhint-disable no-inline-assembly
    library Proxy {
      function creationCode(address _target) internal pure returns (bytes memory result) {
        return abi.encodePacked(
          hex'3d602d80600a3d3981f3363d3d373d3d3d363d73',
          _target,
          hex'5af43d82803e903d91602b57fd5bf3'
        );
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/interfaces/IERC20.sol";
    library SafeERC20 {
      error ErrorSendingERC20(address _token, address _to, uint256 _amount, bytes _result);
      function safeTransfer(IERC20 _token, address _to, uint256 _amount) internal {
        (bool success, bytes memory result) = address(_token).call(abi.encodeWithSelector(
          IERC20.transfer.selector,
          _to,
          _amount
        ));
        if (!success || !optionalReturnsTrue(result)) {
          revert ErrorSendingERC20(address(_token), _to, _amount, result);
        }
      }
      function optionalReturnsTrue(bytes memory _return) internal pure returns (bool) {
        return _return.length == 0 || abi.decode(_return, (bool));
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/interfaces/IERC20.sol";
    import "src/commons/receiver/ReceiverHub.sol";
    import "src/commons/Limits.sol";
    import "src/commons/Permissions.sol";
    import "src/commons/Pausable.sol";
    import "src/utils/SafeERC20.sol";
    abstract contract VaultERC20 is ReceiverHub, Limits, Permissions, Pausable {
      using SafeERC20 for IERC20;
      error ErrorSweepingERC20(address _token, address _receiver, uint256 _amount, bytes _result);
      error ArrayLengthMismatchERC20(uint256 _array1, uint256 _array2);
      uint8 public immutable PERMISSION_SWEEP_ERC20;
      uint8 public immutable PERMISSION_SEND_ERC20;
      uint8 public immutable PERMISSION_SEND_ERC20_LIMIT;
      constructor (uint8 _sweepErc20Permission, uint8 _sendErc20Permission, uint8 _sendErc20LimitPermission) {
        PERMISSION_SWEEP_ERC20 = _sweepErc20Permission;
        PERMISSION_SEND_ERC20 = _sendErc20Permission;
        PERMISSION_SEND_ERC20_LIMIT = _sendErc20LimitPermission;
        _registerPermission(PERMISSION_SWEEP_ERC20);
        _registerPermission(PERMISSION_SEND_ERC20);
        _registerPermission(PERMISSION_SEND_ERC20_LIMIT);
      }
      function sweepERC20(
        IERC20 _token,
        uint256 _id
      ) external notPaused onlyPermissioned(PERMISSION_SWEEP_ERC20) {
        _sweepERC20(_token, _id);
      }
      function sweepBatchERC20(
        IERC20 _token,
        uint256[] calldata _ids
      ) external notPaused onlyPermissioned(PERMISSION_SWEEP_ERC20) {
        unchecked {
          uint256 idsLength = _ids.length;
          for (uint256 i = 0; i < idsLength; ++i) {
            _sweepERC20(_token, _ids[i]);
          }
        }
      }
      function _sweepERC20(
        IERC20 _token,
        uint256 _id
      ) internal {
        Receiver receiver = receiverFor(_id);
        uint256 balance = _token.balanceOf(address(receiver));
        if (balance != 0) {
          createIfNeeded(receiver, _id);
          bytes memory res = executeOnReceiver(receiver, address(_token), 0, abi.encodeWithSelector(
            IERC20.transfer.selector,
            address(this),
            balance
          ));
          if (!SafeERC20.optionalReturnsTrue(res)) {
            revert ErrorSweepingERC20(address(_token), address(receiver), balance, res);
          }
        }
      }
      function sendERC20(
        IERC20 _token,
        address _to,
        uint256 _amount
      ) external notPaused onlyPermissioned(PERMISSION_SEND_ERC20) {
        _token.safeTransfer(_to, _amount);
      }
      function sendBatchERC20(
        IERC20 _token,
        address[] calldata _to,
        uint256[] calldata _amounts
      ) external notPaused onlyPermissioned(PERMISSION_SEND_ERC20) {
        uint256 toLength = _to.length;
        if (toLength != _amounts.length) {
          revert ArrayLengthMismatchERC20(toLength, _amounts.length);
        }
        unchecked {
          for (uint256 i = 0; i < toLength; ++i) {
            _token.safeTransfer(_to[i], _amounts[i]);
          }
        }
      }
      function sendERC20WithLimit(
        IERC20 _token,
        address _to,
        uint256 _amount
      ) external notPaused onlyPermissioned(PERMISSION_SEND_ERC20_LIMIT) underLimit(_amount) {
        _token.safeTransfer(_to, _amount);
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/interfaces/IERC721.sol";
    import "src/commons/receiver/ReceiverHub.sol";
    import "src/commons/Permissions.sol";
    import "src/commons/Pausable.sol";
    abstract contract VaultERC721 is ReceiverHub, Permissions, Pausable {
      uint8 public immutable PERMISSION_SEND_ERC721;
      error ArrayLengthMismatchERC721(uint256 _array1, uint256 _array2, uint256 _array3);
      constructor (uint8 _sendErc721Permission) {
        PERMISSION_SEND_ERC721 = _sendErc721Permission;
        _registerPermission(PERMISSION_SEND_ERC721);
      }
      function sendERC721(
        IERC721 _token,
        uint256 _from,
        address _to,
        uint256 _id
      ) external notPaused onlyPermissioned(PERMISSION_SEND_ERC721) {
        Receiver receiver = useReceiver(_from);
        executeOnReceiver(receiver, address(_token), 0, abi.encodeWithSelector(
            _token.transferFrom.selector,
            address(receiver),
            _to,
            _id
          )
        );
      }
      function sendBatchERC721(
        IERC721 _token,
        uint256[] calldata _ids,
        address[] calldata _tos,
        uint256[] calldata _tokenIds
      ) external notPaused onlyPermissioned(PERMISSION_SEND_ERC721) {
        unchecked {
          uint256 idsLength = _ids.length;
          if (idsLength != _tos.length || idsLength != _tokenIds.length) {
            revert ArrayLengthMismatchERC721(idsLength, _tos.length, _tokenIds.length);
          }
          for (uint256 i = 0; i < idsLength; ++i) {
            Receiver receiver = useReceiver(_ids[i]);
            executeOnReceiver(receiver, address(_token), 0, abi.encodeWithSelector(
                _token.transferFrom.selector,
                address(receiver),
                _tos[i],
                _tokenIds[i]
              )
            );
          }
        }
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/commons/receiver/ReceiverHub.sol";
    import "src/commons/Permissions.sol";
    import "src/commons/Pausable.sol";
    abstract contract VaultETH is ReceiverHub, Permissions, Pausable {
      error ErrorSendingETH(address _to, uint256 _amount, bytes _result);
      error ArrayLengthMismatchETH(uint256 _array1, uint256 _array2);
      uint8 public immutable PERMISSION_SWEEP_ETH;
      uint8 public immutable PERMISSION_SEND_ETH;
      constructor (uint8 _sweepETHPermission, uint8 _sendETHPermission) {
        PERMISSION_SWEEP_ETH = _sweepETHPermission;
        PERMISSION_SEND_ETH = _sendETHPermission;
        _registerPermission(PERMISSION_SWEEP_ETH);
        _registerPermission(PERMISSION_SEND_ETH);
      }
      function sweepETH(
        uint256 _id
      ) external notPaused onlyPermissioned(PERMISSION_SWEEP_ETH) {
        _sweepETH(_id);
      }
      function sweepBatchETH(
        uint256[] calldata _ids
      ) external notPaused onlyPermissioned(PERMISSION_SWEEP_ETH) {
        unchecked {
          uint256 idsLength = _ids.length;
          for (uint256 i = 0; i < idsLength; ++i) {
            _sweepETH(_ids[i]);
          }
        }
      }
      function _sweepETH(uint256 _id) internal {
        Receiver receiver = receiverFor(_id);
        uint256 balance = address(receiver).balance;
        if (balance != 0) {
          createIfNeeded(receiver, _id);
          executeOnReceiver(receiver, address(this), balance, bytes(""));
        }
      }
      function sendETH(
        address payable _to,
        uint256 _amount
      ) external notPaused onlyPermissioned(PERMISSION_SEND_ETH) {
        (bool succeed, bytes memory result) = _to.call{ value: _amount }("");
        if (!succeed) { revert ErrorSendingETH(_to, _amount, result); }
      }
      function sendBatchETH(
        address payable[] calldata  _tos,
        uint256[] calldata _amounts
      ) external notPaused onlyPermissioned(PERMISSION_SEND_ETH) {
        uint256 toLength = _tos.length;
        if (toLength != _amounts.length) {
          revert ArrayLengthMismatchETH(toLength, _amounts.length);
        }
        unchecked {
          for (uint256 i = 0; i < toLength; ++i) {
            (bool succeed, bytes memory result) = _tos[i].call{ value: _amounts[i] }("");
            if (!succeed) { revert ErrorSendingETH(_tos[i], _amounts[i], result); }
          }
        }
      }
      receive() external payable {}
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/commons/receiver/ReceiverHub.sol";
    import "src/commons/Permissions.sol";
    import "src/commons/Pausable.sol";
    abstract contract VaultExecute is ReceiverHub, Permissions, Pausable {
      uint8 public immutable PERMISSION_EXECUTE_ON_RECEIVER;
      uint8 public immutable PERMISSION_EXECUTE;
      error CallError(address _to, uint256 _value, bytes _data, bytes _result);
      constructor(
        uint8 _executeOnReceiverPermission,
        uint8 _executePermission
      ) {
        PERMISSION_EXECUTE_ON_RECEIVER = _executeOnReceiverPermission;
        PERMISSION_EXECUTE = _executePermission;
        _registerPermission(PERMISSION_EXECUTE_ON_RECEIVER);
        _registerPermission(PERMISSION_EXECUTE);
      }
      function executeOnReceiver(
        uint256 _id,
        address payable _to,
        uint256 _value,
        bytes calldata _data
      ) external notPaused onlyPermissioned(PERMISSION_EXECUTE_ON_RECEIVER) returns (bytes memory) {
        return executeOnReceiver(_id, _to, _value, _data);
      }
      function execute(
        address payable _to,
        uint256 _value,
        bytes calldata _data
      ) external notPaused onlyPermissioned(PERMISSION_EXECUTE) returns (bytes memory) {
        (bool res, bytes memory result) = _to.call{ value: _value }(_data);
        if (!res) revert CallError(_to, _value, _data, result);
        return result;
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/commons/Permissions.sol";
    import "src/commons/Pausable.sol";
    import "src/interfaces/IERC721Deterministic.sol";
    abstract contract VaultIssueERC721 is Permissions, Pausable {
      uint8 public immutable PERMISSION_ISSUE_ERC721;
      error ArrayLengthMismatchIssueERC721(uint256 _array1, uint256 _array2, uint256 _array3);
      constructor (uint8 _issueERC721Permission) {
        PERMISSION_ISSUE_ERC721 = _issueERC721Permission;
        _registerPermission(PERMISSION_ISSUE_ERC721);
      }
      function issueERC721(
        address _beneficiary,
        IERC721Deterministic _contract,
        uint256 _optionId,
        uint256 _issuedId
      ) external notPaused onlyPermissioned(PERMISSION_ISSUE_ERC721) {
        _contract.issueToken(_beneficiary, _optionId, _issuedId);
      }
      function issueBatchERC721(
        address _beneficiary,
        IERC721Deterministic[] calldata _contracts,
        uint256[] calldata _optionIds,
        uint256[] calldata _issuedIds
      ) external notPaused onlyPermissioned(PERMISSION_ISSUE_ERC721) {
        unchecked {
          uint256 contractsLength = _contracts.length;
          if (contractsLength != _optionIds.length || contractsLength != _issuedIds.length) {
            revert ArrayLengthMismatchIssueERC721(contractsLength, _optionIds.length, _issuedIds.length);
          }
          for (uint256 i = 0; i < contractsLength; ++i) {
            _contracts[i].issueToken(_beneficiary, _optionIds[i], _issuedIds[i]);
          }
        }
      }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.16;
    import "src/commons/receiver/ReceiverHub.sol";
    import "src/commons/Permissions.sol";
    import "src/commons/Pausable.sol";
    abstract contract VaultNewReceivers is ReceiverHub, Permissions, Pausable {
      uint8 public immutable PERMISSION_DEPLOY_RECEIVER;
      constructor (uint8 _deployReceiverPermission) {
        PERMISSION_DEPLOY_RECEIVER = _deployReceiverPermission;
        _registerPermission(PERMISSION_DEPLOY_RECEIVER);
      }
      function deployReceivers(
        uint256[] calldata _receivers
      ) external notPaused onlyPermissioned(PERMISSION_DEPLOY_RECEIVER) {
        unchecked {
          uint256 receiversLength = _receivers.length;
          for (uint256 i = 0; i < receiversLength; ++i) {
            useReceiver(_receivers[i]);
          }
        }
      }
      function deployReceiversRange(
        uint256 _from,
        uint256 _to
      ) external notPaused onlyPermissioned(PERMISSION_DEPLOY_RECEIVER) {
        unchecked {
          for (uint256 i = _from; i < _to; ++i) {
            useReceiver(i);
          }
        }
      }
    }
    

    File 2 of 2: BigTimeToken
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
    pragma solidity ^0.8.0;
    import "./IERC20.sol";
    import "./extensions/IERC20Metadata.sol";
    import "../../utils/Context.sol";
    /**
     * @dev Implementation of the {IERC20} interface.
     *
     * This implementation is agnostic to the way tokens are created. This means
     * that a supply mechanism has to be added in a derived contract using {_mint}.
     * For a generic mechanism see {ERC20PresetMinterPauser}.
     *
     * TIP: For a detailed writeup see our guide
     * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
     * to implement supply mechanisms].
     *
     * The default value of {decimals} is 18. To change this, you should override
     * this function so it returns a different value.
     *
     * We have followed general OpenZeppelin Contracts guidelines: functions revert
     * instead returning `false` on failure. This behavior is nonetheless
     * conventional and does not conflict with the expectations of ERC20
     * applications.
     *
     * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
     * This allows applications to reconstruct the allowance for all accounts just
     * by listening to said events. Other implementations of the EIP may not emit
     * these events, as it isn't required by the specification.
     *
     * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
     * functions have been added to mitigate the well-known issues around setting
     * allowances. See {IERC20-approve}.
     */
    contract ERC20 is Context, IERC20, IERC20Metadata {
        mapping(address => uint256) private _balances;
        mapping(address => mapping(address => uint256)) private _allowances;
        uint256 private _totalSupply;
        string private _name;
        string private _symbol;
        /**
         * @dev Sets the values for {name} and {symbol}.
         *
         * All two of these values are immutable: they can only be set once during
         * construction.
         */
        constructor(string memory name_, string memory symbol_) {
            _name = name_;
            _symbol = symbol_;
        }
        /**
         * @dev Returns the name of the token.
         */
        function name() public view virtual override returns (string memory) {
            return _name;
        }
        /**
         * @dev Returns the symbol of the token, usually a shorter version of the
         * name.
         */
        function symbol() public view virtual override returns (string memory) {
            return _symbol;
        }
        /**
         * @dev Returns the number of decimals used to get its user representation.
         * For example, if `decimals` equals `2`, a balance of `505` tokens should
         * be displayed to a user as `5.05` (`505 / 10 ** 2`).
         *
         * Tokens usually opt for a value of 18, imitating the relationship between
         * Ether and Wei. This is the default value returned by this function, unless
         * it's overridden.
         *
         * NOTE: This information is only used for _display_ purposes: it in
         * no way affects any of the arithmetic of the contract, including
         * {IERC20-balanceOf} and {IERC20-transfer}.
         */
        function decimals() public view virtual override returns (uint8) {
            return 18;
        }
        /**
         * @dev See {IERC20-totalSupply}.
         */
        function totalSupply() public view virtual override returns (uint256) {
            return _totalSupply;
        }
        /**
         * @dev See {IERC20-balanceOf}.
         */
        function balanceOf(address account) public view virtual override returns (uint256) {
            return _balances[account];
        }
        /**
         * @dev See {IERC20-transfer}.
         *
         * Requirements:
         *
         * - `to` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address to, uint256 amount) public virtual override returns (bool) {
            address owner = _msgSender();
            _transfer(owner, to, amount);
            return true;
        }
        /**
         * @dev See {IERC20-allowance}.
         */
        function allowance(address owner, address spender) public view virtual override returns (uint256) {
            return _allowances[owner][spender];
        }
        /**
         * @dev See {IERC20-approve}.
         *
         * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
         * `transferFrom`. This is semantically equivalent to an infinite approval.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 amount) public virtual override returns (bool) {
            address owner = _msgSender();
            _approve(owner, spender, amount);
            return true;
        }
        /**
         * @dev See {IERC20-transferFrom}.
         *
         * Emits an {Approval} event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of {ERC20}.
         *
         * NOTE: Does not update the allowance if the current allowance
         * is the maximum `uint256`.
         *
         * Requirements:
         *
         * - `from` and `to` cannot be the zero address.
         * - `from` must have a balance of at least `amount`.
         * - the caller must have allowance for ``from``'s tokens of at least
         * `amount`.
         */
        function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
            address spender = _msgSender();
            _spendAllowance(from, spender, amount);
            _transfer(from, to, amount);
            return true;
        }
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
            address owner = _msgSender();
            _approve(owner, spender, allowance(owner, spender) + addedValue);
            return true;
        }
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
            address owner = _msgSender();
            uint256 currentAllowance = allowance(owner, spender);
            require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
            unchecked {
                _approve(owner, spender, currentAllowance - subtractedValue);
            }
            return true;
        }
        /**
         * @dev Moves `amount` of tokens from `from` to `to`.
         *
         * This internal function is equivalent to {transfer}, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a {Transfer} event.
         *
         * Requirements:
         *
         * - `from` cannot be the zero address.
         * - `to` cannot be the zero address.
         * - `from` must have a balance of at least `amount`.
         */
        function _transfer(address from, address to, uint256 amount) internal virtual {
            require(from != address(0), "ERC20: transfer from the zero address");
            require(to != address(0), "ERC20: transfer to the zero address");
            _beforeTokenTransfer(from, to, amount);
            uint256 fromBalance = _balances[from];
            require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
            unchecked {
                _balances[from] = fromBalance - amount;
                // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
                // decrementing then incrementing.
                _balances[to] += amount;
            }
            emit Transfer(from, to, amount);
            _afterTokenTransfer(from, to, amount);
        }
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a {Transfer} event with `from` set to the zero address.
         *
         * Requirements:
         *
         * - `account` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: mint to the zero address");
            _beforeTokenTransfer(address(0), account, amount);
            _totalSupply += amount;
            unchecked {
                // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
                _balances[account] += amount;
            }
            emit Transfer(address(0), account, amount);
            _afterTokenTransfer(address(0), account, amount);
        }
        /**
         * @dev Destroys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a {Transfer} event with `to` set to the zero address.
         *
         * Requirements:
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: burn from the zero address");
            _beforeTokenTransfer(account, address(0), amount);
            uint256 accountBalance = _balances[account];
            require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
            unchecked {
                _balances[account] = accountBalance - amount;
                // Overflow not possible: amount <= accountBalance <= totalSupply.
                _totalSupply -= amount;
            }
            emit Transfer(account, address(0), amount);
            _afterTokenTransfer(account, address(0), amount);
        }
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
         *
         * This internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an {Approval} event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 amount) internal virtual {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
        /**
         * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
         *
         * Does not update the allowance amount in case of infinite allowance.
         * Revert if not enough allowance is available.
         *
         * Might emit an {Approval} event.
         */
        function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
            uint256 currentAllowance = allowance(owner, spender);
            if (currentAllowance != type(uint256).max) {
                require(currentAllowance >= amount, "ERC20: insufficient allowance");
                unchecked {
                    _approve(owner, spender, currentAllowance - amount);
                }
            }
        }
        /**
         * @dev Hook that is called before any transfer of tokens. This includes
         * minting and burning.
         *
         * Calling conditions:
         *
         * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
         * will be transferred to `to`.
         * - when `from` is zero, `amount` tokens will be minted for `to`.
         * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
         * - `from` and `to` are never both zero.
         *
         * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
         */
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
        /**
         * @dev Hook that is called after any transfer of tokens. This includes
         * minting and burning.
         *
         * Calling conditions:
         *
         * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
         * has been transferred to `to`.
         * - when `from` is zero, `amount` tokens have been minted for `to`.
         * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
         * - `from` and `to` are never both zero.
         *
         * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
         */
        function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
    pragma solidity ^0.8.0;
    import "../IERC20.sol";
    /**
     * @dev Interface for the optional metadata functions from the ERC20 standard.
     *
     * _Available since v4.1._
     */
    interface IERC20Metadata is IERC20 {
        /**
         * @dev Returns the name of the token.
         */
        function name() external view returns (string memory);
        /**
         * @dev Returns the symbol of the token.
         */
        function symbol() external view returns (string memory);
        /**
         * @dev Returns the decimals places of the token.
         */
        function decimals() external view returns (uint8);
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
    pragma solidity ^0.8.0;
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP.
     */
    interface IERC20 {
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
        /**
         * @dev Moves `amount` tokens from the caller's account to `to`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address to, uint256 amount) external returns (bool);
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
        /**
         * @dev Moves `amount` tokens from `from` to `to` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(address from, address to, uint256 amount) external returns (bool);
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
    pragma solidity ^0.8.0;
    /**
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }
    //SPDX-License-Identifier: Unlicense
    pragma solidity 0.8.4;
    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
    contract BigTimeToken is ERC20 {
        constructor(
            string memory _name,
            string memory _symbol,
            uint _totalSupply,
            address _owner
        ) ERC20(_name, _symbol) {
            _mint(_owner, _totalSupply * 10 ** decimals());
        }
    }