Address Details
contract

0x68a2948DFbD993017c9cB6BC5116Ed843b705e12

Contract Name
SquidMulticall
Creator
0x98b292ā€“77919e at 0xae863dā€“6592d3
Balance
0 CELO ( )
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
34 Transfers
Gas Used
Fetching gas used...
Last Balance Update
17383153
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
SquidMulticall




Optimization enabled
true
Compiler version
v0.8.17+commit.8df45f5f




Optimization runs
99999
EVM Version
london




Verified at
2022-12-21T08:04:39.317223Z

contracts/SquidMulticall.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {ISquidMulticall} from "./interfaces/ISquidMulticall.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract SquidMulticall is ISquidMulticall {
    bool private isRunning;

    error TransferFailed();

    function run(Call[] calldata calls) external payable {
        // Prevents reentrancy
        if (isRunning) revert AlreadyRunning();
        isRunning = true;

        for (uint256 i = 0; i < calls.length; i++) {
            Call memory call = calls[i];

            if (call.callType == CallType.FullTokenBalance) {
                (address token, uint256 amountParameterPosition) = abi.decode(call.payload, (address, uint256));
                uint256 amount = IERC20(token).balanceOf(address(this));
                _setCallDataParameter(call.callData, amountParameterPosition, amount);
            } else if (call.callType == CallType.FullNativeBalance) {
                call.value = address(this).balance;
            } else if (call.callType == CallType.CollectTokenBalance) {
                address token = abi.decode(call.payload, (address));
                _safeTransferFrom(token, msg.sender, IERC20(token).balanceOf(msg.sender));
                continue;
            }

            (bool success, bytes memory data) = call.target.call{value: call.value}(call.callData);
            if (!success) revert CallFailed(i, data);
        }

        isRunning = false;
    }

    function _safeTransferFrom(address token, address from, uint256 amount) private {
        (bool success, bytes memory returnData) = token.call(
            abi.encodeWithSelector(IERC20.transferFrom.selector, from, address(this), amount)
        );
        bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool)));
        if (!transferred || token.code.length == 0) revert TransferFailed();
    }

    function _setCallDataParameter(bytes memory callData, uint256 parameterPosition, uint256 value) private pure {
        assembly {
            // 36 bytes shift because 32 for prefix + 4 for selector
            mstore(add(callData, add(36, mul(parameterPosition, 32))), value)
        }
    }

    // Required to enable ETH reception with .transfer or .send
    receive() external payable {}
}
        

/_openzeppelin/contracts/token/ERC20/IERC20.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.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);
}
          

/contracts/interfaces/ISquidMulticall.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface ISquidMulticall {
    enum CallType {
        Default,
        FullTokenBalance,
        FullNativeBalance,
        CollectTokenBalance
    }

    struct Call {
        CallType callType;
        address target;
        uint256 value;
        bytes callData;
        bytes payload;
    }

    error AlreadyRunning();
    error CallFailed(uint256 callPosition, bytes reason);

    function run(Call[] calldata calls) external payable;
}
          

Contract ABI

[{"type":"error","name":"AlreadyRunning","inputs":[]},{"type":"error","name":"CallFailed","inputs":[{"type":"uint256","name":"callPosition","internalType":"uint256"},{"type":"bytes","name":"reason","internalType":"bytes"}]},{"type":"error","name":"TransferFailed","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"run","inputs":[{"type":"tuple[]","name":"calls","internalType":"struct ISquidMulticall.Call[]","components":[{"type":"uint8","name":"callType","internalType":"enum ISquidMulticall.CallType"},{"type":"address","name":"target","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"callData","internalType":"bytes"},{"type":"bytes","name":"payload","internalType":"bytes"}]}]},{"type":"receive","stateMutability":"payable"}]
            

Deployed ByteCode

0x6080604081815260049081361015610022575b505050361561002057600080fd5b005b600091823560e01c63f87ef8001461003a5750610012565b602091827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103f95781359267ffffffffffffffff958685116103f557366023860112156103f557848401359687116103f5576024850194602436918960051b0101116103f557855460ff166103ce576100dd60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000541617600055565b855b87811061011757866101147fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060005416600055565b80f35b868061012c610127848c8b610459565b610622565b60018151610139816106aa565b610142816106aa565b036102ae576101f173ffffffffffffffffffffffffffffffffffffffff6101cc8861017889860151828082518301019101610717565b92908d8d519586809481937f70a082310000000000000000000000000000000000000000000000000000000083523090830191909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0392165afa9182156102a1575b8592610272575b50606084015160249160051b010152565b8086015173ffffffffffffffffffffffffffffffffffffffff16606088830151920151918783519301915af1610225610736565b901561023a5750610235906103fd565b6100df565b61026e869186519384937f5c0dee5d0000000000000000000000000000000000000000000000000000000085528401610766565b0390fd5b610293919250893d8b1161029a575b61028b8183610526565b8101906106fb565b90386101e0565b503d610281565b6102a961070a565b6101d9565b600281516102bb816106aa565b6102c4816106aa565b036102d35747878201526101f1565b905083600382516102e3816106aa565b6102ec816106aa565b146102f9575081906101f1565b61023593925061031a6103339161039d9301518780825183010191016106e3565b73ffffffffffffffffffffffffffffffffffffffff1690565b86517f70a0823100000000000000000000000000000000000000000000000000000000815233898201908152909190879083908190602001038173ffffffffffffffffffffffffffffffffffffffff85165afa9182156103c1575b8b926103a2575b5033906107ec565b6103fd565b6103ba919250873d891161029a5761028b8183610526565b9038610395565b6103c961070a565b61038e565b807fe4455ead00000000000000000000000000000000000000000000000000000000859252fd5b8580fd5b8380fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461042a5760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919081101561049e5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6181360301821215610499570190565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761051957604052565b6105216104cd565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761051957604052565b73ffffffffffffffffffffffffffffffffffffffff81160361049957565b359061059082610567565b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff81116105ce575b01160190565b6105d66104cd565b6105c8565b81601f82011215610499578035906105f282610592565b926106006040519485610526565b8284526020838301011161049957816000926020809301838601378301015290565b60a0813603126104995760405190610639826104fd565b8035600481101561049957825261065260208201610585565b60208301526040810135604083015260608101359067ffffffffffffffff918281116104995761068590369083016105db565b60608401526080810135918211610499576106a2913691016105db565b608082015290565b600411156106b457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9081602091031261049957516106f881610567565b90565b90816020910312610499575190565b506040513d6000823e3d90fd5b9190826040910312610499576020825161073081610567565b92015190565b3d15610761573d9061074782610592565b916107556040519384610526565b82523d6000602084013e565b606090565b909291928152602060408183015283519384604084015260005b8581106107c0575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006060809697860101520116010190565b818101830151848201606001528201610780565b90816020910312610499575180151581036104995790565b9160009182916040519073ffffffffffffffffffffffffffffffffffffffff60208301937f23b872dd000000000000000000000000000000000000000000000000000000008552166024830152306044830152606482015260648152610851816104fd565b519082855af161085f610736565b816108aa575b50159081156108a0575b5061087657565b60046040517f90b8ec18000000000000000000000000000000000000000000000000000000008152fd5b90503b153861086f565b80518015925082156108bf575b505038610865565b6108d292506020809183010191016107d4565b38806108b756fea264697066735822122057b447d7063c7d7d5758ad98eea66f484b9b8f4af581ada19cab550cb1194a2864736f6c63430008110033