ERC20TokenMultiSender

0xb69b5581d79a242b27c0fd7ebc3ec15c43e69b67

Verification
Verified
v0.8.24+commit.e11b9ed9
Type
Contract
991 bytes
ABI entries
6
2 read · 2 write
License
none

Contract information

Address
0xb69b5581d79a242b27c0fd7ebc3ec15c43e69b67
Chain
Robinhood Chain (4663)
Compiler
v0.8.24+commit.e11b9ed9
Optimization
Enabled
Creation tx
0x726b8593c9…05a69a2edc

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (2)

payments()address
serviceId()bytes32

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_payments",
        "type": "address"
      },
      {
        "internalType": "string",
        "name": "_serviceId",
        "type": "string"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "_projectId",
        "type": "bytes32"
      },
      {
        "internalType": "address",
        "name": "_token",
        "type": "address"
      },
      {
        "internalType": "address[]",
        "name": "_addresses",
        "type": "address[]"
      },
      {
        "internalType": "uint256[]",
        "name": "_amounts",
        "type": "uint256[]"
      },
      {
        "internalType": "uint256",
        "name": "_totalAmount",
        "type": "uint256"
      }
    ],
    "name": "airdropTokens",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "_projectId",
        "type": "bytes32"
      },
      {
        "internalType": "address",
        "name": "_token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "qty",
        "type": "uint256"
      }
    ],
    "name": "payService",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "payments",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "serviceId",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]

Source code

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

/*

                                                                                                    
                    &&&&&& &&&&&                                        &%                          
                     &&&&&&&&&&&&&&&                               && &&&&&&&&&&%                   
                     &&&&&&&      &&&&&                          #&&&&&&&&&&&&&                     
                     &&&&&  &&&&&&&   &&                      &&&&    &%  &&&&&&&                   
                        &&. &&&&&&&&&&                        &  %&&&&&&&  &&&&                     
                        &&&&  *&&&&&&&&&                       &&&&&&&&&  &&&&                      
                           .&&&   &&&&&&&&                   &&&&&&&&   &&&                         
                                    .&&&&&&&               &&&&&&&   &&&%                           
                                       &&&&&&             &&&&&&                                    
                                         &&&&&          /&&&&.                                      
                                           &&&&  %&&&  #&&&,                                        
                                   &&&&(     &&&&&&&&&&&&&                                          
                               &&&&&&&&&&&&&&&&&&&&&&&&&&&&   &&&&&&&&&&                            
                             &&&%        &&&&&&&&&&&&&&&&&&&&&&&&&     &&&                          
                            &&&    &&&*    &&&&&&&&&&&&&&&&&&&&&         &&*                        
                           &&&   .&&&&&&   &&&&&&&&&&&&&&&&&&&&   &&&&&   &&                        
                           &&&   #&&&&&&   &&&&&&&&&&&&&&&&&&&&&  &&&&&   &&                        
                            &&&    &&&&    &&&&&&&&&&&&&&&&&&&&&&  #&&   &&&                        
                             &&&         &&&&&&&&&&&&&&&&&&&&&&&&,     *&&&                         
                              (&&&&&&&&&&&&&&&&&&&&          &&&&&&&&&&&%                           
                                  &&&&&&&&&&&&&&&&&          &&&&&                                  
                                    &&&&&&&&&&&&&&&&&&    %&&&&&&&                                  
                                    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#                                 
                                      &&&&&&&&&&&&&&&&&&&&&&&&&&&&                                  
                                           &&&&&&&&&&&&&&&&&&&&                                     

*/
/**
 * Token Multi Sender contract
 * This contract is used to send multiple tokens ERC20 to multiple addresses
 *
 */
/// @title TokenMultiSender
/// @author Smithii
/// @notice This contract is used to send multiple tokens ERC20 to multiple addresses

import {Payable} from "./utils/Payable.sol";

contract ERC20TokenMultiSender is Payable {
    constructor(
        address _payments,
        string memory _serviceId
    ) Payable(_payments, _serviceId) {}

    /// AirDrop tokens and pay the service fee
    /// @param _projectId the project id
    /// @param _token the token address
    /// @param _addresses the addresses to send the tokens
    /// @param _amounts the amounts to send to each address
    /// @param _totalAmount the total amount to send
    function airdropTokens(
        bytes32 _projectId,
        address _token,
        address[] calldata _addresses,
        uint256[] calldata _amounts,
        uint256 _totalAmount
    ) external payable {
        /// @notice pay the service fee
        payService(_projectId, _token, _addresses.length);
        /// @notice airdrop the tokens
        _airdropTokens(_token, _addresses, _amounts, _totalAmount);
    }

    /// Ultra light weight gas airdrop function by GasliteDrop 0x09350F89e2D7B6e96bA730783c2d76137B045FEF
    /** 
    /// @author Harrison (@PopPunkOnChain)
    /// @author Gaslite (@GasliteGG)
    /// @author Pop Punk LLC (@PopPunkLLC)
    */
    /// @param _token the token address
    /// @param _addresses the addresses to send the tokens
    /// @param _amounts the amounts to send to each address
    /// @param _totalAmount the total amount to send
    function _airdropTokens(
        address _token,
        address[] calldata _addresses,
        uint256[] calldata _amounts,
        uint256 _totalAmount
    ) internal {
        assembly {
            // Check that the number of addresses matches the number of amounts
            if iszero(eq(_amounts.length, _addresses.length)) {
                revert(0, 0)
            }

            // transferFrom(address from, address to, uint256 amount)
            mstore(0x00, hex"23b872dd")
            // from address
            mstore(0x04, caller())
            // to address (this contract)
            mstore(0x24, address())
            // total amount
            mstore(0x44, _totalAmount)

            // transfer total amount to this contract
            if iszero(call(gas(), _token, 0, 0x00, 0x64, 0, 0)) {
                revert(0, 0)
            }

            // transfer(address to, uint256 value)
            mstore(0x00, hex"a9059cbb")

            // end of array
            let end := add(_addresses.offset, shl(5, _addresses.length))
            // diff = _addresses.offset - _amounts.offset
            let diff := sub(_addresses.offset, _amounts.offset)

            // Loop through the addresses
            for {
                let addressOffset := _addresses.offset
            } 1 {

            } {
                // to address
                mstore(0x04, calldataload(addressOffset))
                // amount
                mstore(0x24, calldataload(sub(addressOffset, diff)))
                // transfer the tokens
                if iszero(call(gas(), _token, 0, 0x00, 0x64, 0, 0)) {
                    revert(0, 0)
                }
                // increment the address offset
                addressOffset := add(addressOffset, 0x20)
                // if addressOffset >= end, break
                if iszero(lt(addressOffset, end)) {
                    break
                }
            }
        }
    }
}
Chain explorer3178msChain node97ms