Blockchain / Global / Address
Contract
0x0CDab740d1aA2f8ED0055C69769Ee2ac48554140
- Balance
- 0 SOMI
- Transactions sent
- 1
- Type
- Contract · 5,400 bytes of code
MultiCallUtils Verified
- Compiler
- solc 0.8.30+commit.73712a01
- Language
- Solidity
- Optimization
- No
- EVM version
- prague
- License
- —
- Verified
- 2026-10-12
src/MultiCallUtils.sol
and 1 more files
Solidity
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.22;
import "./interfaces/IModuleCalls.sol";
contract MultiCallUtils {
// Errors
error DelegateCallNotAllowed(uint256 _index);
error CallReverted(uint256 _index, bytes _result);
function multiCall(
IModuleCalls.Transaction[] memory _txs
)
public
payable
returns (bool[] memory _successes, bytes[] memory _results)
{
_successes = new bool[](_txs.length);
_results = new bytes[](_txs.length);
for (uint256 i = 0; i < _txs.length; i++) {
IModuleCalls.Transaction memory transaction = _txs[i];
if (transaction.delegateCall) revert DelegateCallNotAllowed(i);
if (gasleft() < transaction.gasLimit)
revert IModuleCalls.NotEnoughGas(
i,
transaction.gasLimit,
gasleft()
);
// solhint-disable
(_successes[i], _results[i]) = transaction.target.call{
value: transaction.value,
gas: transaction.gasLimit == 0
? gasleft()
: transaction.gasLimit
}(transaction.data);
// solhint-enable
if (!_successes[i] && _txs[i].revertOnError)
revert CallReverted(i, _results[i]);
}
}
function getBalances(
address user,
address[] calldata tokens
)
external
view
returns (bool[] memory _successes, uint256[] memory _balances)
{
_successes = new bool[](tokens.length + 1);
_balances = new uint256[](tokens.length + 1);
for (uint i = 0; i < tokens.length; i++) {
(_successes[i], _balances[i]) = _getBalance(user, tokens[i]);
}
// last element is the native balance
(_successes[tokens.length], _balances[tokens.length]) = (
true,
address(user).balance
);
}
// ///
// Globals
// ///
function callBlockhash(uint256 _i) external view returns (bytes32) {
return blockhash(_i);
}
function callCoinbase() external view returns (address) {
return block.coinbase;
}
function callDifficulty() external view returns (uint256) {
return block.prevrandao; // old block.difficulty
}
function callPrevrandao() external view returns (uint256) {
return block.prevrandao;
}
function callGasLimit() external view returns (uint256) {
return block.gaslimit;
}
function callBlockNumber() external view returns (uint256) {
return block.number;
}
function callTimestamp() external view returns (uint256) {
return block.timestamp;
}
function callGasLeft() external view returns (uint256) {
return gasleft();
}
function callGasPrice() external view returns (uint256) {
return tx.gasprice;
}
function callOrigin() external view returns (address) {
return tx.origin;
}
function callBalanceOf(address _addr) external view returns (uint256) {
return _addr.balance;
}
function callCodeSize(address _addr) external view returns (uint256 size) {
assembly {
size := extcodesize(_addr)
}
}
function callCode(address _addr) external view returns (bytes memory code) {
assembly {
let size := extcodesize(_addr)
code := mload(0x40)
mstore(0x40, add(code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
mstore(code, size)
extcodecopy(_addr, add(code, 0x20), 0, size)
}
}
function callCodeHash(
address _addr
) external view returns (bytes32 codeHash) {
assembly {
codeHash := extcodehash(_addr)
}
}
function callChainId() external view returns (uint256 id) {
assembly {
id := chainid()
}
}
// internal
function _getBalance(
address user,
address token
) internal view returns (bool txSuccess, uint256 balance) {
uint256 size;
assembly {
size := extcodesize(token)
}
if (size == 0) {
return (txSuccess, balance);
}
(bool success, bytes memory data) = token.staticcall(
abi.encodeWithSelector(0x70a08231, user)
);
if (success) {
balance = abi.decode(data, (uint256));
txSuccess = true;
}
}
}
Other files
src/interfaces/IModuleCalls.sol
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.22; interface IModuleCalls { // Events event TxFailed(bytes32 indexed _tx, uint256 _index, bytes _reason); event TxExecuted(bytes32 indexed _tx, uint256 _index); // Errors error NotEnoughGas(uint256 _index, uint256 _requested, uint256 _available); error InvalidSignature(bytes32 _hash, bytes _signature); // Transaction structure struct Transaction { bool delegateCall; // Performs delegatecall bool revertOnError; // Reverts transaction bundle if tx fails uint256 gasLimit; // Maximum gas to be forwarded address target; // Address of the contract to call uint256 value; // Amount of ETH to pass with the call bytes data; // calldata to pass } /** * @notice Allow wallet owner to execute an action * @param _txs Transactions to process * @param _nonce Signature nonce (may contain an encoded space) * @param _signature Encoded signature */ function execute( Transaction[] calldata _txs, uint256 _nonce, bytes calldata _signature ) external; /** * @notice Allow wallet to execute an action * without signing the message * @param _txs Transactions to execute */ function selfExecute(Transaction[] calldata _txs) external; }
ABI · 20 entries
json
[
{
"name": "CallReverted",
"type": "error",
"inputs": [
{
"name": "_index",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "_result",
"type": "bytes",
"internalType": "bytes"
}
]
},
{
"name": "DelegateCallNotAllowed",
"type": "error",
"inputs": [
{
"name": "_index",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "NotEnoughGas",
"type": "error",
"inputs": [
{
"name": "_index",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "_requested",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "_available",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "callBalanceOf",
"type": "function",
"inputs": [
{
"name": "_addr",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callBlockNumber",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callBlockhash",
"type": "function",
"inputs": [
{
"name": "_i",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "callChainId",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "id",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callCode",
"type": "function",
"inputs": [
{
"name": "_addr",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "code",
"type": "bytes",
"internalType": "bytes"
}
],
"stateMutability": "view"
},
{
"name": "callCodeHash",
"type": "function",
"inputs": [
{
"name": "_addr",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "codeHash",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "callCodeSize",
"type": "function",
"inputs": [
{
"name": "_addr",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "size",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callCoinbase",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "callDifficulty",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callGasLeft",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callGasLimit",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callGasPrice",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callOrigin",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "callPrevrandao",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "callTimestamp",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "getBalances",
"type": "function",
"inputs": [
{
"name": "user",
"type": "address",
"internalType": "address"
},
{
"name": "tokens",
"type": "address[]",
"internalType": "address[]"
}
],
"outputs": [
{
"name": "_successes",
"type": "bool[]",
"internalType": "bool[]"
},
{
"name": "_balances",
"type": "uint256[]",
"internalType": "uint256[]"
}
],
"stateMutability": "view"
},
{
"name": "multiCall",
"type": "function",
"inputs": [
{
"name": "_txs",
"type": "tuple[]",
"components": [
{
"name": "delegateCall",
"type": "bool",
"internalType": "bool"
},
{
"name": "revertOnError",
"type": "bool",
"internalType": "bool"
},
{
"name": "gasLimit",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "target",
"type": "address",
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "data",
"type": "bytes",
"internalType": "bytes"
}
],
"internalType": "struct IModuleCalls.Transaction[]"
}
],
"outputs": [
{
"name": "_successes",
"type": "bool[]",
"internalType": "bool[]"
},
{
"name": "_results",
"type": "bytes[]",
"internalType": "bytes[]"
}
],
"stateMutability": "payable"
}
]