ETH Price: $2,990.22 (+2.42%)
Gas: 6 Gwei

Contract

0x48EC5560bFD59b95859965cCE48cC244CFDF6b0c
 

Overview

ETH Balance

8,831.315050623326547234 ETH

Eth Value

$26,407,548.92 (@ $2,990.22/ETH)

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
0x5af6dd32329b79f84d33e517807c9b091b0f91453ef6dd7a190442705b678648Send Multi Sig(pending)2024-05-03 7:23:242 mins ago1714721004IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0xdfd26d4104e863ba4cf27cd8ca01c5ea12c365c822a9d4c7e9d47695c3162976Send Multi Sig T...(pending)2024-05-03 7:22:502 mins ago1714720970IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x46ebfdf4899a981ea166c40ec67e0e120c49d4bbe56aee1dc96531024c068bf2Send Multi Sig T...(pending)2024-05-03 7:22:402 mins ago1714720960IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x23bf62e9ac11d77f237f0229b8d163a15469b244d2532814794db555d850cda6Send Multi Sig(pending)2024-05-03 7:20:584 mins ago1714720858IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x31ec2c9c1d545016dc60e81357db7500aa5e2809fab6703dac9123e0b8bc236cSend Multi Sig T...(pending)2024-05-03 7:20:294 mins ago1714720829IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x1d2d1b00415ccbe2170134686a894d826f1371502fb4e0c0c623bbe4d7d95ab1Send Multi Sig(pending)2024-05-03 7:18:586 mins ago1714720738IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x0f3a1304db29826d4e50073bde3f09fdb1bc34b998b37f58233e8280cfa26152Send Multi Sig(pending)2024-05-03 7:12:5712 mins ago1714720377IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x56f7353aee577b6371d381178e01679eec5e8ab90ded339e1729ebaf68203a0dSend Multi Sig T...(pending)2024-05-03 7:12:5212 mins ago1714720372IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x5362c1b6cd9101b8b22cb80e9c0f9b00d766d9cd4e30d83fdebdf29109208a93Send Multi Sig T...(pending)2024-05-03 7:10:4114 mins ago1714720241IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x7d614caf8e1baf69969973de95451a90e3cada6031535999997a91f3e117ffdaSend Multi Sig T...(pending)2024-05-03 7:10:2815 mins ago1714720228IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x5e61bca2a2c65f738623a5a589066c304c4f213b0c0e9e25430362a16023be09Send Multi Sig(pending)2024-05-03 7:02:0623 mins ago1714719726IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x08a6fec018275e9ba121da4e7b7412a462e54a377a60c37d84ff20aae29df9cbSend Multi Sig T...(pending)2024-05-03 6:56:4028 mins ago1714719400IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x2c77162865f3b86da1a306e5eca3a1ebfd1890fbd5139fba17765edd87e30da4Send Multi Sig(pending)2024-05-03 6:53:0532 mins ago1714719185IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x6e46b3362343dcd0ce232a9151323a4e1dc4cfa9247ca7a154c8dac5598d99e5Send Multi Sig T...(pending)2024-05-03 6:52:4332 mins ago1714719163IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x0caea40cb8ab5e52544b3493152951cf568beeba74a12941aaca389a960ce347Send Multi Sig(pending)2024-05-03 6:49:2036 mins ago1714718960IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0xa7235aaa82d5fd02611e80d71e892dc8298e12bde7bf799cbf08878beb875a49Send Multi Sig(pending)2024-05-03 6:47:4137 mins ago1714718861IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0xf20726a5d387e143fb3a26d94a7ef32928cbe9b3f95626cac7b0ee0112e56a12Send Multi Sig T...(pending)2024-05-03 6:42:4042 mins ago1714718560IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x9ff36edbed352c3f7aceaa53198e3e027de5414b99008309bc086148889f145aSend Multi Sig T...(pending)2024-05-03 6:37:3947 mins ago1714718259IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x94ac392a02131893679ddb4db85ba8cbb23d0345a5e5c1ab28b2bbf61d2967baSend Multi Sig(pending)2024-05-03 6:36:0749 mins ago1714718167IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x9f839afb959c5a67e884529c3d1c59edf9c971ffb9699cd5e1cdfaca7fbca005Send Multi Sig T...(pending)2024-05-03 6:32:5352 mins ago1714717973IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x273828c20d91cc867a50d775bad6bfb076c3b39c54b33d950a1efdcab2fd8633Send Multi Sig(pending)2024-05-03 6:30:5954 mins ago1714717859IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x241940bb92b78135075a812d78128b3cfe293b838d1a1ad2e56075dab47ec7abSend Multi Sig T...(pending)2024-05-03 6:30:2255 mins ago1714717822IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
0x03964ecf6cc0bce4ad268cb1c40ffde354a8b3a15a5ebeb0771b39d80d750150Send Multi Sig T...(pending)2024-05-03 6:28:1057 mins ago1714717690IN
Bitstamp: Wallet
0 ETH(Pending)(Pending)
Send Multi Sig197880732024-05-03 7:23:232 mins ago1714721003IN
Bitstamp: Wallet
0 ETH0.000873648.46436218
Send Multi Sig T...197880702024-05-03 7:22:472 mins ago1714720967IN
Bitstamp: Wallet
0 ETH0.000608016.49474614
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
197880732024-05-03 7:23:232 mins ago1714721003
Bitstamp: Wallet
0.01393285 ETH
197880612024-05-03 7:20:594 mins ago1714720859
Bitstamp: Wallet
0.7086002 ETH
197880512024-05-03 7:18:596 mins ago1714720739
Bitstamp: Wallet
1.494 ETH
197880212024-05-03 7:12:5912 mins ago1714720379
Bitstamp: Wallet
0.1931 ETH
197879672024-05-03 7:02:1123 mins ago1714719731
Bitstamp: Wallet
0.0307 ETH
197879252024-05-03 6:53:4731 mins ago1714719227
Bitstamp: Wallet
0.64312641 ETH
197879042024-05-03 6:49:3535 mins ago1714718975
Bitstamp: Wallet
1.46002821 ETH
197878952024-05-03 6:47:4737 mins ago1714718867
Bitstamp: Wallet
0.08 ETH
197878372024-05-03 6:36:1149 mins ago1714718171
Bitstamp: Wallet
0.0226 ETH
197878112024-05-03 6:30:5954 mins ago1714717859
Bitstamp: Wallet
14 ETH
197877722024-05-03 6:23:111 hr ago1714717391
Bitstamp: Wallet
0.030417 ETH
197877212024-05-03 6:12:591 hr ago1714716779
Bitstamp: Wallet
0.1609 ETH
197876672024-05-03 6:02:111 hr ago1714716131
Bitstamp: Wallet
5.75038929 ETH
197876662024-05-03 6:01:591 hr ago1714716119
Bitstamp: Wallet
0.0225 ETH
197876382024-05-03 5:56:231 hr ago1714715783
Bitstamp: Wallet
0.0797 ETH
197876042024-05-03 5:49:111 hr ago1714715351
Bitstamp: Wallet
0.1538 ETH
197876022024-05-03 5:48:471 hr ago1714715327
Bitstamp: Wallet
22.20710721 ETH
197875262024-05-03 5:33:351 hr ago1714714415
Bitstamp: Wallet
0.6208 ETH
197875162024-05-03 5:31:351 hr ago1714714295
Bitstamp: Wallet
0.0921 ETH
197875152024-05-03 5:31:231 hr ago1714714283
Bitstamp: Wallet
20 ETH
197874752024-05-03 5:23:232 hrs ago1714713803
Bitstamp: Wallet
0.0129 ETH
197874682024-05-03 5:21:592 hrs ago1714713719
Bitstamp: Wallet
0.0305 ETH
197874672024-05-03 5:21:472 hrs ago1714713707
Bitstamp: Wallet
0.0219 ETH
197874372024-05-03 5:15:472 hrs ago1714713347
Bitstamp: Wallet
0.005 ETH
197874302024-05-03 5:14:232 hrs ago1714713263
Bitstamp: Wallet
0.0091 ETH
View All Internal Transactions
Loading...
Loading

Minimal Proxy Contract for 0xe8e847cf573fc8ed75621660a36affd18c543d7e

Contract Name:
WalletSimple

Compiler Version
v0.7.5+commit.eb77ed08

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, Apache-2.0 license

Contract Source Code (Solidity Multiple files format)

File 4 of 4: WalletSimple.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.7.5;
import './TransferHelper.sol';
import './Forwarder.sol';
import './ERC20Interface.sol';

/**
 *
 * WalletSimple
 * ============
 *
 * Basic multi-signer wallet designed for use in a co-signing environment where 2 signatures are required to move funds.
 * Typically used in a 2-of-3 signing configuration. Uses ecrecover to allow for 2 signatures in a single transaction.
 *
 * The first signature is created on the operation hash (see Data Formats) and passed to sendMultiSig/sendMultiSigToken
 * The signer is determined by verifyMultiSig().
 *
 * The second signature is created by the submitter of the transaction and determined by msg.signer.
 *
 * Data Formats
 * ============
 *
 * The signature is created with ethereumjs-util.ecsign(operationHash).
 * Like the eth_sign RPC call, it packs the values as a 65-byte array of [r, s, v].
 * Unlike eth_sign, the message is not prefixed.
 *
 * The operationHash the result of keccak256(prefix, toAddress, value, data, expireTime).
 * For ether transactions, `prefix` is "ETHER".
 * For token transaction, `prefix` is "ERC20" and `data` is the tokenContractAddress.
 *
 *
 */
contract WalletSimple {
  // Events
  event Deposited(address from, uint256 value, bytes data);
  event SafeModeActivated(address msgSender);
  event Transacted(
    address msgSender, // Address of the sender of the message initiating the transaction
    address otherSigner, // Address of the signer (second signature) used to initiate the transaction
    bytes32 operation, // Operation hash (see Data Formats)
    address toAddress, // The address the transaction was sent to
    uint256 value, // Amount of Wei sent to the address
    bytes data // Data sent when invoking the transaction
  );

  event BatchTransfer(address sender, address recipient, uint256 value);
  // this event shows the other signer and the operation hash that they signed
  // specific batch transfer events are emitted in Batcher
  event BatchTransacted(
    address msgSender, // Address of the sender of the message initiating the transaction
    address otherSigner, // Address of the signer (second signature) used to initiate the transaction
    bytes32 operation // Operation hash (see Data Formats)
  );

  // Public fields
  mapping(address => bool) public signers; // The addresses that can co-sign transactions on the wallet
  bool public safeMode = false; // When active, wallet may only send to signer addresses
  bool public initialized = false; // True if the contract has been initialized

  // Internal fields
  uint256 private constant MAX_SEQUENCE_ID_INCREASE = 10000;
  uint256 constant SEQUENCE_ID_WINDOW_SIZE = 10;
  uint256[SEQUENCE_ID_WINDOW_SIZE] recentSequenceIds;

  /**
   * Set up a simple multi-sig wallet by specifying the signers allowed to be used on this wallet.
   * 2 signers will be required to send a transaction from this wallet.
   * Note: The sender is NOT automatically added to the list of signers.
   * Signers CANNOT be changed once they are set
   *
   * @param allowedSigners An array of signers on the wallet
   */
  function init(address[] calldata allowedSigners) external onlyUninitialized {
    require(allowedSigners.length == 3, 'Invalid number of signers');

    for (uint8 i = 0; i < allowedSigners.length; i++) {
      require(allowedSigners[i] != address(0), 'Invalid signer');
      signers[allowedSigners[i]] = true;
    }
    initialized = true;
  }

  /**
   * Get the network identifier that signers must sign over
   * This provides protection signatures being replayed on other chains
   * This must be a virtual function because chain-specific contracts will need
   *    to override with their own network ids. It also can't be a field
   *    to allow this contract to be used by proxy with delegatecall, which will
   *    not pick up on state variables
   */
  function getNetworkId() internal virtual pure returns (string memory) {
    return 'ETHER';
  }

  /**
   * Get the network identifier that signers must sign over for token transfers
   * This provides protection signatures being replayed on other chains
   * This must be a virtual function because chain-specific contracts will need
   *    to override with their own network ids. It also can't be a field
   *    to allow this contract to be used by proxy with delegatecall, which will
   *    not pick up on state variables
   */
  function getTokenNetworkId() internal virtual pure returns (string memory) {
    return 'ERC20';
  }

  /**
   * Get the network identifier that signers must sign over for batch transfers
   * This provides protection signatures being replayed on other chains
   * This must be a virtual function because chain-specific contracts will need
   *    to override with their own network ids. It also can't be a field
   *    to allow this contract to be used by proxy with delegatecall, which will
   *    not pick up on state variables
   */
  function getBatchNetworkId() internal virtual pure returns (string memory) {
    return 'ETHER-Batch';
  }

  /**
   * Determine if an address is a signer on this wallet
   * @param signer address to check
   * returns boolean indicating whether address is signer or not
   */
  function isSigner(address signer) public view returns (bool) {
    return signers[signer];
  }

  /**
   * Modifier that will execute internal code block only if the sender is an authorized signer on this wallet
   */
  modifier onlySigner {
    require(isSigner(msg.sender), 'Non-signer in onlySigner method');
    _;
  }

  /**
   * Modifier that will execute internal code block only if the contract has not been initialized yet
   */
  modifier onlyUninitialized {
    require(!initialized, 'Contract already initialized');
    _;
  }

  /**
   * Gets called when a transaction is received with data that does not match any other method
   */
  fallback() external payable {
    if (msg.value > 0) {
      // Fire deposited event if we are receiving funds
      Deposited(msg.sender, msg.value, msg.data);
    }
  }

  /**
   * Gets called when a transaction is received with ether and no data
   */
  receive() external payable {
    if (msg.value > 0) {
      // Fire deposited event if we are receiving funds
      Deposited(msg.sender, msg.value, msg.data);
    }
  }

  /**
   * Execute a multi-signature transaction from this wallet using 2 signers: one from msg.sender and the other from ecrecover.
   * Sequence IDs are numbers starting from 1. They are used to prevent replay attacks and may not be repeated.
   *
   * @param toAddress the destination address to send an outgoing transaction
   * @param value the amount in Wei to be sent
   * @param data the data to send to the toAddress when invoking the transaction
   * @param expireTime the number of seconds since 1970 for which this transaction is valid
   * @param sequenceId the unique sequence id obtainable from getNextSequenceId
   * @param signature see Data Formats
   */
  function sendMultiSig(
    address toAddress,
    uint256 value,
    bytes calldata data,
    uint256 expireTime,
    uint256 sequenceId,
    bytes calldata signature
  ) external onlySigner {
    // Verify the other signer
    bytes32 operationHash = keccak256(
      abi.encodePacked(
        getNetworkId(),
        toAddress,
        value,
        data,
        expireTime,
        sequenceId
      )
    );

    address otherSigner = verifyMultiSig(
      toAddress,
      operationHash,
      signature,
      expireTime,
      sequenceId
    );

    // Success, send the transaction
    (bool success, ) = toAddress.call{ value: value }(data);
    require(success, 'Call execution failed');

    emit Transacted(
      msg.sender,
      otherSigner,
      operationHash,
      toAddress,
      value,
      data
    );
  }

  /**
   * Execute a batched multi-signature transaction from this wallet using 2 signers: one from msg.sender and the other from ecrecover.
   * Sequence IDs are numbers starting from 1. They are used to prevent replay attacks and may not be repeated.
   * The recipients and values to send are encoded in two arrays, where for index i, recipients[i] will be sent values[i].
   *
   * @param recipients The list of recipients to send to
   * @param values The list of values to send to
   * @param expireTime the number of seconds since 1970 for which this transaction is valid
   * @param sequenceId the unique sequence id obtainable from getNextSequenceId
   * @param signature see Data Formats
   */
  function sendMultiSigBatch(
    address[] calldata recipients,
    uint256[] calldata values,
    uint256 expireTime,
    uint256 sequenceId,
    bytes calldata signature
  ) external onlySigner {
    require(recipients.length != 0, 'Not enough recipients');
    require(
      recipients.length == values.length,
      'Unequal recipients and values'
    );
    require(recipients.length < 256, 'Too many recipients, max 255');

    // Verify the other signer
    bytes32 operationHash = keccak256(
      abi.encodePacked(
        getBatchNetworkId(),
        recipients,
        values,
        expireTime,
        sequenceId
      )
    );

    // the first parameter (toAddress) is used to ensure transactions in safe mode only go to a signer
    // if in safe mode, we should use normal sendMultiSig to recover, so this check will always fail if in safe mode
    require(!safeMode, 'Batch in safe mode');
    address otherSigner = verifyMultiSig(
      address(0x0),
      operationHash,
      signature,
      expireTime,
      sequenceId
    );

    batchTransfer(recipients, values);
    emit BatchTransacted(msg.sender, otherSigner, operationHash);
  }

  /**
   * Transfer funds in a batch to each of recipients
   * @param recipients The list of recipients to send to
   * @param values The list of values to send to recipients.
   *  The recipient with index i in recipients array will be sent values[i].
   *  Thus, recipients and values must be the same length
   */
  function batchTransfer(
    address[] calldata recipients,
    uint256[] calldata values
  ) internal {
    for (uint256 i = 0; i < recipients.length; i++) {
      require(address(this).balance >= values[i], 'Insufficient funds');

      (bool success, ) = recipients[i].call{ value: values[i] }('');
      require(success, 'Call failed');

      emit BatchTransfer(msg.sender, recipients[i], values[i]);
    }
  }

  /**
   * Execute a multi-signature token transfer from this wallet using 2 signers: one from msg.sender and the other from ecrecover.
   * Sequence IDs are numbers starting from 1. They are used to prevent replay attacks and may not be repeated.
   *
   * @param toAddress the destination address to send an outgoing transaction
   * @param value the amount in tokens to be sent
   * @param tokenContractAddress the address of the erc20 token contract
   * @param expireTime the number of seconds since 1970 for which this transaction is valid
   * @param sequenceId the unique sequence id obtainable from getNextSequenceId
   * @param signature see Data Formats
   */
  function sendMultiSigToken(
    address toAddress,
    uint256 value,
    address tokenContractAddress,
    uint256 expireTime,
    uint256 sequenceId,
    bytes calldata signature
  ) external onlySigner {
    // Verify the other signer
    bytes32 operationHash = keccak256(
      abi.encodePacked(
        getTokenNetworkId(),
        toAddress,
        value,
        tokenContractAddress,
        expireTime,
        sequenceId
      )
    );

    verifyMultiSig(toAddress, operationHash, signature, expireTime, sequenceId);

    TransferHelper.safeTransfer(tokenContractAddress, toAddress, value);
  }

  /**
   * Execute a token flush from one of the forwarder addresses. This transfer needs only a single signature and can be done by any signer
   *
   * @param forwarderAddress the address of the forwarder address to flush the tokens from
   * @param tokenContractAddress the address of the erc20 token contract
   */
  function flushForwarderTokens(
    address payable forwarderAddress,
    address tokenContractAddress
  ) external onlySigner {
    Forwarder forwarder = Forwarder(forwarderAddress);
    forwarder.flushTokens(tokenContractAddress);
  }

  /**
   * Do common multisig verification for both eth sends and erc20token transfers
   *
   * @param toAddress the destination address to send an outgoing transaction
   * @param operationHash see Data Formats
   * @param signature see Data Formats
   * @param expireTime the number of seconds since 1970 for which this transaction is valid
   * @param sequenceId the unique sequence id obtainable from getNextSequenceId
   * returns address that has created the signature
   */
  function verifyMultiSig(
    address toAddress,
    bytes32 operationHash,
    bytes calldata signature,
    uint256 expireTime,
    uint256 sequenceId
  ) private returns (address) {
    address otherSigner = recoverAddressFromSignature(operationHash, signature);

    // Verify if we are in safe mode. In safe mode, the wallet can only send to signers
    require(!safeMode || isSigner(toAddress), 'External transfer in safe mode');

    // Verify that the transaction has not expired
    require(expireTime >= block.timestamp, 'Transaction expired');

    // Try to insert the sequence ID. Will revert if the sequence id was invalid
    tryInsertSequenceId(sequenceId);

    require(isSigner(otherSigner), 'Invalid signer');

    require(otherSigner != msg.sender, 'Signers cannot be equal');

    return otherSigner;
  }

  /**
   * Irrevocably puts contract into safe mode. When in this mode, transactions may only be sent to signing addresses.
   */
  function activateSafeMode() external onlySigner {
    safeMode = true;
    SafeModeActivated(msg.sender);
  }

  /**
   * Gets signer's address using ecrecover
   * @param operationHash see Data Formats
   * @param signature see Data Formats
   * returns address recovered from the signature
   */
  function recoverAddressFromSignature(
    bytes32 operationHash,
    bytes memory signature
  ) private pure returns (address) {
    require(signature.length == 65, 'Invalid signature - wrong length');

    // We need to unpack the signature, which is given as an array of 65 bytes (like eth.sign)
    bytes32 r;
    bytes32 s;
    uint8 v;

    // solhint-disable-next-line
    assembly {
      r := mload(add(signature, 32))
      s := mload(add(signature, 64))
      v := and(mload(add(signature, 65)), 255)
    }
    if (v < 27) {
      v += 27; // Ethereum versions are 27 or 28 as opposed to 0 or 1 which is submitted by some signing libs
    }

    // protect against signature malleability
    // S value must be in the lower half orader
    // reference: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/051d340171a93a3d401aaaea46b4b62fa81e5d7c/contracts/cryptography/ECDSA.sol#L53
    require(
      uint256(s) <=
        0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
      "ECDSA: invalid signature 's' value"
    );

    // note that this returns 0 if the signature is invalid
    // Since 0x0 can never be a signer, when the recovered signer address
    // is checked against our signer list, that 0x0 will cause an invalid signer failure
    return ecrecover(operationHash, v, r, s);
  }

  /**
   * Verify that the sequence id has not been used before and inserts it. Throws if the sequence ID was not accepted.
   * We collect a window of up to 10 recent sequence ids, and allow any sequence id that is not in the window and
   * greater than the minimum element in the window.
   * @param sequenceId to insert into array of stored ids
   */
  function tryInsertSequenceId(uint256 sequenceId) private onlySigner {
    // Keep a pointer to the lowest value element in the window
    uint256 lowestValueIndex = 0;
    // fetch recentSequenceIds into memory for function context to avoid unnecessary sloads
    uint256[SEQUENCE_ID_WINDOW_SIZE] memory _recentSequenceIds = recentSequenceIds;
    for (uint256 i = 0; i < SEQUENCE_ID_WINDOW_SIZE; i++) {
      require(_recentSequenceIds[i] != sequenceId, 'Sequence ID already used');

      if (_recentSequenceIds[i] < _recentSequenceIds[lowestValueIndex]) {
        lowestValueIndex = i;
      }
    }

    // The sequence ID being used is lower than the lowest value in the window
    // so we cannot accept it as it may have been used before
    require(
      sequenceId > _recentSequenceIds[lowestValueIndex],
      'Sequence ID below window'
    );

    // Block sequence IDs which are much higher than the lowest value
    // This prevents people blocking the contract by using very large sequence IDs quickly
    require(
      sequenceId <=
        (_recentSequenceIds[lowestValueIndex] + MAX_SEQUENCE_ID_INCREASE),
      'Sequence ID above maximum'
    );

    recentSequenceIds[lowestValueIndex] = sequenceId;
  }

  /**
   * Gets the next available sequence ID for signing when using executeAndConfirm
   * returns the sequenceId one higher than the highest currently stored
   */
  function getNextSequenceId() public view returns (uint256) {
    uint256 highestSequenceId = 0;
    for (uint256 i = 0; i < SEQUENCE_ID_WINDOW_SIZE; i++) {
      if (recentSequenceIds[i] > highestSequenceId) {
        highestSequenceId = recentSequenceIds[i];
      }
    }
    return highestSequenceId + 1;
  }
}

File 1 of 4: ERC20Interface.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.7.5;

/**
 * Contract that exposes the needed erc20 token functions
 */

abstract contract ERC20Interface {
  // Send _value amount of tokens to address _to
  function transfer(address _to, uint256 _value)
    public
    virtual
    returns (bool success);

  // Get the account balance of another account with address _owner
  function balanceOf(address _owner)
    public
    virtual
    view
    returns (uint256 balance);
}

File 2 of 4: Forwarder.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.7.5;
import './TransferHelper.sol';
import './ERC20Interface.sol';

/**
 * Contract that will forward any incoming Ether to the creator of the contract
 *
 */
contract Forwarder {
  // Address to which any funds sent to this contract will be forwarded
  address public parentAddress;
  event ForwarderDeposited(address from, uint256 value, bytes data);

  /**
   * Initialize the contract, and sets the destination address to that of the creator
   */
  function init(address _parentAddress) external onlyUninitialized {
    parentAddress = _parentAddress;
    uint256 value = address(this).balance;

    if (value == 0) {
      return;
    }

    (bool success, ) = parentAddress.call{ value: value }('');
    require(success, 'Flush failed');
    // NOTE: since we are forwarding on initialization,
    // we don't have the context of the original sender.
    // We still emit an event about the forwarding but set
    // the sender to the forwarder itself
    emit ForwarderDeposited(address(this), value, msg.data);
  }

  /**
   * Modifier that will execute internal code block only if the sender is the parent address
   */
  modifier onlyParent {
    require(msg.sender == parentAddress, 'Only Parent');
    _;
  }

  /**
   * Modifier that will execute internal code block only if the contract has not been initialized yet
   */
  modifier onlyUninitialized {
    require(parentAddress == address(0x0), 'Already initialized');
    _;
  }

  /**
   * Default function; Gets called when data is sent but does not match any other function
   */
  fallback() external payable {
    flush();
  }

  /**
   * Default function; Gets called when Ether is deposited with no data, and forwards it to the parent address
   */
  receive() external payable {
    flush();
  }

  /**
   * Execute a token transfer of the full balance from the forwarder token to the parent address
   * @param tokenContractAddress the address of the erc20 token contract
   */
  function flushTokens(address tokenContractAddress) external onlyParent {
    ERC20Interface instance = ERC20Interface(tokenContractAddress);
    address forwarderAddress = address(this);
    uint256 forwarderBalance = instance.balanceOf(forwarderAddress);
    if (forwarderBalance == 0) {
      return;
    }

    TransferHelper.safeTransfer(
      tokenContractAddress,
      parentAddress,
      forwarderBalance
    );
  }

  /**
   * Flush the entire balance of the contract to the parent address.
   */
  function flush() public {
    uint256 value = address(this).balance;

    if (value == 0) {
      return;
    }

    (bool success, ) = parentAddress.call{ value: value }('');
    require(success, 'Flush failed');
    emit ForwarderDeposited(msg.sender, value, msg.data);
  }
}

File 3 of 4: TransferHelper.sol
// SPDX-License-Identifier: Apache-2.0

pragma solidity >=0.7.5;

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::safeApprove: approve failed'
        );
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::safeTransfer: transfer failed'
        );
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            'TransferHelper::transferFrom: transferFrom failed'
        );
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'TransferHelper::safeTransferETH: ETH transfer failed');
    }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"msgSender","type":"address"},{"indexed":false,"internalType":"address","name":"otherSigner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"operation","type":"bytes32"}],"name":"BatchTransacted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"BatchTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"msgSender","type":"address"}],"name":"SafeModeActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"msgSender","type":"address"},{"indexed":false,"internalType":"address","name":"otherSigner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"operation","type":"bytes32"},{"indexed":false,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Transacted","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"activateSafeMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"forwarderAddress","type":"address"},{"internalType":"address","name":"tokenContractAddress","type":"address"}],"name":"flushForwarderTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getNextSequenceId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"allowedSigners","type":"address[]"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"safeMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"expireTime","type":"uint256"},{"internalType":"uint256","name":"sequenceId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"sendMultiSig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"uint256","name":"expireTime","type":"uint256"},{"internalType":"uint256","name":"sequenceId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"sendMultiSigBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"tokenContractAddress","type":"address"},{"internalType":"uint256","name":"expireTime","type":"uint256"},{"internalType":"uint256","name":"sequenceId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"sendMultiSigToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"signers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Chain Token Portfolio % Price Amount Value
ETH
Ether (ETH)
26.40%$2,990.228,831.3151$26,407,548.92
ETH26.34%$126,347,270.1127$26,347,270.11
ETH14.13%$0.042915329,414,143.2336$14,136,913.37
ETH8.51%$18,505,433.0305$8,513,938.46
ETH6.18%$0.000008793,093,309,230.969$6,186,127.81
ETH3.78%$0.0024061,570,956,295.9036$3,779,406.66
ETH1.72%$13.62126,197.8579$1,718,814.82
ETH0.84%$0.985046848,158.7269$835,475.36
ETH0.82%$0.7192391,145,804.7353$824,107.45
ETH0.71%$0.00002330,801,604,935.7609$708,744.93
ETH0.65%$0.849816761,812.916$647,400.8
ETH0.55%$2.02272,881.4403$551,220.51
ETH0.53%$0.671347794,260.452$533,224.37
ETH0.49%$59,4518.2616$491,161.38
ETH0.43%$0.3586191,202,385.8039$431,198.39
ETH0.41%$0.0633826,451,290.9949$408,895.73
ETH0.38%$0.2512141,527,191.5101$383,651.89
ETH0.33%$7.0447,440.0487$333,977.94
ETH0.33%$0.43373762,419.6958$330,684.29
ETH0.26%$2,761.1993.7746$258,929.62
ETH0.25%$1.22204,759.1711$249,806.19
ETH0.25%$2.07120,038.1352$248,478.94
ETH0.24%$0.524589464,490.9796$243,666.86
ETH0.24%$0.42267557,515.0977$235,645.03
ETH0.23%$85.082,659.198$226,239.49
ETH0.22%$7.7928,151.9635$219,303.8
ETH0.22%$1.02212,756.0405$216,372.89
ETH0.21%$0.00387154,997,129$212,898.29
ETH0.21%$0.1707381,236,736.1847$211,158.43
ETH0.21%$0.241881861,287.7563$208,329.14
ETH0.20%$0.431889473,985.0181$204,708.92
ETH0.20%$0.999765200,627.8748$200,580.73
ETH0.19%$1.07182,066.7061$194,629.31
ETH0.19%$1.06184,114.0225$194,240.29
ETH0.17%$0.404209415,768.2897$168,057.28
ETH0.17%$0.477915350,572.9292$167,544.06
ETH0.15%$7.5819,363.1141$146,772.4
ETH0.14%$0.244011590,252.4128$144,028.08
ETH0.14%$6,881.7619.7556$135,953.25
ETH0.14%$0.300887450,283.3594$135,484.41
ETH0.13%$1.26103,497.7646$130,407.18
ETH0.13%$2.6848,367.6043$129,625.18
ETH0.13%$0.00784216,041,421.7018$125,796.67
ETH0.13%$0.193933648,101.7828$125,688.1
ETH0.12%$0.0746171,625,834.7336$121,315.37
ETH0.12%$0.1083561,092,282.3905$118,355.35
ETH0.11%$14.927,558.2096$112,768.49
ETH0.11%$0.998971108,280.4$108,168.98
ETH0.11%$0.37017283,885.0347$105,085.72
ETH0.10%$2.5839,840.8161$102,789.31
ETH0.10%$0.0102249,646,060.9337$98,624.7
ETH0.09%$23.534,007.2339$94,290.21
ETH0.09%$0.116893784,436.2761$91,695.11
ETH0.08%$13.295,906.8608$78,502.18
ETH0.07%$7.3410,070.6942$73,918.9
ETH0.07%$0.98443671,533.498$70,420.19
ETH0.07%$0.019663,554,620.3626$69,884.58
ETH0.07%$57.391,197.187$68,706.56
ETH0.07%$2.2230,156.3604$66,947.12
ETH0.06%$0.219238265,987.0949$58,314.48
ETH0.05%$0.336946145,552.6273$49,043.38
ETH0.04%$1.6922,929.8142$38,751.39
ETH0.04%$0.99936838,265.5469$38,241.36
ETH0.03%$0.58412557,042.8436$33,320.15
ETH0.03%$1.4817,998.0186$26,637.07
ETH0.03%$2.5110,103.3311$25,377.56
ETH0.02%$0.64323735,350.519$22,738.77
ETH0.02%$0.644235,035.884$22,570.12
ETH0.01%$1.0114,475.4696$14,547.85
ETH0.01%$2.125,628.5544$11,932.54
ETH<0.01%$1.474,186.9433$6,154.81
ETH<0.01%<$0.00000137,178,306,667.6063$6,076.4
ETH<0.01%$0.3657468,704.6407$3,183.69
ETH<0.01%$0.2226239,823.4852$2,186.93
ETH<0.01%<$0.000001139,318,908.0351$25.17
ETH<0.01%$0.0013361,000$1.34
MATIC<0.01%$0.719390.0014$0.001007
Loading...
Loading
[ Download: CSV Export  ]
[ 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.