creation_sourcecode: // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;
  pragma experimental ABIEncoderV2;
  
  
  /// @title Multicall - Aggregate results from multiple read-only function calls
  /// @author Nick Johnson <arachnid@notdot.net>
  
  contract Multicall {
      struct Call {
          address target;
          bytes callData;
      }
  
      modifier OnlyAllowed {
          require(allowed[msg.sender] == true, "user not allowed to execute multicall");
          _;
      }
  
      mapping(address => bool) public allowed;
      address owner;
  
      constructor(){
          allowed[msg.sender] = true;
          owner = msg.sender;
      }
  
      function addAllowed(address addressToAdd) public {
          require(msg.sender == owner);
          allowed[addressToAdd] = true;
      }
  
      function aggregate(Call[] memory calls) public OnlyAllowed returns (uint256 blockNumber, bytes[] memory returnData) {
          blockNumber = block.number;
          returnData = new bytes[](calls.length);
          for(uint256 i = 0; i < calls.length; i++) {
              (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
              require(success);
              returnData[i] = ret;
          }
      }
      // Helper functions
      function getEthBalance(address addr) public view returns (uint256 balance) {
          balance = addr.balance;
      }
      function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
          blockHash = blockhash(blockNumber);
      }
      function getLastBlockHash() public view returns (bytes32 blockHash) {
          blockHash = blockhash(block.number - 1);
      }
      function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
          timestamp = block.timestamp;
      }
      function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
          difficulty = block.difficulty;
      }
      function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
          gaslimit = block.gaslimit;
      }
      function getCurrentBlockCoinbase() public view returns (address coinbase) {
          coinbase = block.coinbase;
      }
  }