Description:
Smart contract deployed on Ethereum with Factory features.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"src/BatchTransfer.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/**
* @title BatchTransfer
* @notice Gas-efficient batch transfer contract for ERC721 tokens with access control
* @dev Allows ONLY the authorized caller to transfer multiple ERC721 tokens in a single transaction
*
* Security Model:
* 1. Contract is deployed with a single authorized caller address (immutable)
* 2. Safe approves this contract: setApprovalForAll(BatchTransfer, true)
* 3. ONLY the authorized caller can execute batchTransferFrom
* 4. Any other address attempting to call will revert with "Unauthorized"
*
* Usage:
* 1. Deploy with authorizedCaller = EOA operator address
* 2. Safe approves this contract via setApprovalForAll
* 3. EOA operator calls batchTransferFrom to transfer tokens
*
* Gas optimizations:
* - Minimal storage usage (one immutable address)
* - Unchecked iterator increments
* - No events (rely on ERC721 Transfer events)
* - Direct interface calls (no try/catch overhead)
*/
interface IERC721 {
function transferFrom(address from, address to, uint256 tokenId) external;
}
contract BatchTransfer {
/// @notice The only address authorized to call batch transfer functions
/// @dev Immutable for gas efficiency and security - cannot be changed after deployment
address public immutable authorizedCaller;
/// @notice Emitted when contract is deployed
/// @param caller The authorized caller address
event BatchTransferDeployed(address indexed caller);
/// @notice Reverts when msg.sender is not the authorized caller
error Unauthorized();
/**
* @notice Deploy the BatchTransfer contract with a specific authorized caller
* @param _authorizedCaller The address that will be allowed to call batch transfer functions
* @dev The authorized caller cannot be changed after deployment
*/
constructor(address _authorizedCaller) {
require(_authorizedCaller != address(0), "Zero address not allowed");
authorizedCaller = _authorizedCaller;
emit BatchTransferDeployed(_authorizedCaller);
}
/**
* @notice Modifier to restrict function access to authorized caller only
*/
modifier onlyAuthorized() {
if (msg.sender != authorizedCaller) revert Unauthorized();
_;
}
/**
* @notice Batch transfer ERC721 tokens from one address to another
* @param token The ERC721 token contract address
* @param from The address to transfer from (must have approved this contract)
* @param to The address to transfer to
* @param tokenIds Array of token IDs to transfer
*
* @dev Reverts if:
* - Caller is not the authorized caller (Unauthorized)
* - Any tokenId is not owned by `from`
* - This contract is not approved by `from`
* - Any individual transfer fails
*
* All transfers are atomic - if one fails, all revert.
*/
function batchTransferFrom(
address token,
address from,
address to,
uint256[] calldata tokenIds
) external onlyAuthorized {
uint256 length = tokenIds.length;
for (uint256 i; i < length;) {
IERC721(token).transferFrom(from, to, tokenIds[i]);
unchecked {
++i;
}
}
}
/**
* @notice Batch transfer multiple ERC721 collections in one transaction
* @param tokens Array of ERC721 token contract addresses
* @param from The address to transfer from (must have approved this contract for all tokens)
* @param to The address to transfer to
* @param tokenIds Array of arrays - tokenIds[i] contains IDs for tokens[i]
*
* @dev Useful for transferring tokens from multiple collections at once
* Requires tokens.length == tokenIds.length
* Reverts if caller is not the authorized caller (Unauthorized)
*/
function batchTransferFromMultiple(
address[] calldata tokens,
address from,
address to,
uint256[][] calldata tokenIds
) external onlyAuthorized {
uint256 length = tokens.length;
require(length == tokenIds.length, "Length mismatch");
for (uint256 i; i < length;) {
uint256 tokenIdsLength = tokenIds[i].length;
for (uint256 j; j < tokenIdsLength;) {
IERC721(tokens[i]).transferFrom(from, to, tokenIds[i][j]);
unchecked {
++j;
}
}
unchecked {
++i;
}
}
}
}
"
}
},
"settings": {
"remappings": [
"forge-std/=lib/forge-std/src/",
"solady/=lib/solady/src/"
],
"optimizer": {
"enabled": false,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}
}}
Submitted on: 2025-10-24 13:06:42
Comments
Log in to comment.
No comments yet.