├── README.md └── mutilTransfer.sol /README.md: -------------------------------------------------------------------------------- 1 | ## 批量转账合约源码 2 | 3 | 本网站唯一网址 :[https://www.ducks.life/#/](https://www.ducks.life/#/) 4 | 5 | Ethereum 合约: [0xb6d6e96e1b8d5eb82959302d7e60b62d40c892c5](https://cn.etherscan.com/address/0xb6d6e96e1b8d5eb82959302d7e60b62d40c892c5) 6 | 7 | Bsc 合约: [0x6379082dA2C77D1A2f17B7947cE074416071879a](https://bscscan.com/address/0x6379082dA2C77D1A2f17B7947cE074416071879a) 8 | 9 | Bsc-test 合约: [0xDa3e46125B9a21a835b012dCa0B4a3EFEB3bE31B](https://testnet.bscscan.com/address/0xDa3e46125B9a21a835b012dCa0B4a3EFEB3bE31B) 10 | 11 | Goeril 合约: [0x95fBABc128428E7eF00599eC6E6A9d14f448D880](https://goerli.etherscan.io/address/0x95fbabc128428e7ef00599ec6e6a9d14f448d880) 12 | 13 | OKC Mainnet 合约: [0xb6d6e96e1b8d5eb82959302d7e60b62d40c892c5](https://www.oklink.com/zh-cn/okc/address/0xb6d6e96e1b8d5eb82959302d7e60b62d40c892c5) 14 | 15 | -------------------------------------------------------------------------------- /mutilTransfer.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at BscScan.com on 2022-04-15 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) 7 | 8 | pragma solidity ^0.8.0; 9 | 10 | interface IERC20 { 11 | /** 12 | * @dev Returns the amount of tokens in existence. 13 | */ 14 | function totalSupply() external view returns (uint256); 15 | 16 | /** 17 | * @dev Returns the amount of tokens owned by `account`. 18 | */ 19 | function balanceOf(address account) external view returns (uint256); 20 | 21 | /** 22 | * @dev Moves `amount` tokens from the caller's account to `to`. 23 | * 24 | * Returns a boolean value indicating whether the operation succeeded. 25 | * 26 | * Emits a {Transfer} event. 27 | */ 28 | function transfer(address to, uint256 amount) external returns (bool); 29 | 30 | /** 31 | * @dev Returns the remaining number of tokens that `spender` will be 32 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 33 | * zero by default. 34 | * 35 | * This value changes when {approve} or {transferFrom} are called. 36 | */ 37 | function allowance(address owner, address spender) external view returns (uint256); 38 | 39 | /** 40 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 41 | * 42 | * Returns a boolean value indicating whether the operation succeeded. 43 | * 44 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 45 | * that someone may use both the old and the new allowance by unfortunate 46 | * transaction ordering. One possible solution to mitigate this race 47 | * condition is to first reduce the spender's allowance to 0 and set the 48 | * desired value afterwards: 49 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 50 | * 51 | * Emits an {Approval} event. 52 | */ 53 | function approve(address spender, uint256 amount) external returns (bool); 54 | 55 | /** 56 | * @dev Moves `amount` tokens from `from` to `to` using the 57 | * allowance mechanism. `amount` is then deducted from the caller's 58 | * allowance. 59 | * 60 | * Returns a boolean value indicating whether the operation succeeded. 61 | * 62 | * Emits a {Transfer} event. 63 | */ 64 | function transferFrom( 65 | address from, 66 | address to, 67 | uint256 amount 68 | ) external returns (bool); 69 | 70 | /** 71 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 72 | * another (`to`). 73 | * 74 | * Note that `value` may be zero. 75 | */ 76 | event Transfer(address indexed from, address indexed to, uint256 value); 77 | 78 | /** 79 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 80 | * a call to {approve}. `value` is the new allowance. 81 | */ 82 | event Approval(address indexed owner, address indexed spender, uint256 value); 83 | } 84 | 85 | library Address { 86 | /** 87 | * @dev Returns true if `account` is a contract. 88 | * 89 | * [IMPORTANT] 90 | * ==== 91 | * It is unsafe to assume that an address for which this function returns 92 | * false is an externally-owned account (EOA) and not a contract. 93 | * 94 | * Among others, `isContract` will return false for the following 95 | * types of addresses: 96 | * 97 | * - an externally-owned account 98 | * - a contract in construction 99 | * - an address where a contract will be created 100 | * - an address where a contract lived, but was destroyed 101 | * ==== 102 | * 103 | * [IMPORTANT] 104 | * ==== 105 | * You shouldn't rely on `isContract` to protect against flash loan attacks! 106 | * 107 | * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets 108 | * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract 109 | * constructor. 110 | * ==== 111 | */ 112 | function isContract(address account) internal view returns (bool) { 113 | // This method relies on extcodesize/address.code.length, which returns 0 114 | // for contracts in construction, since the code is only stored at the end 115 | // of the constructor execution. 116 | 117 | return account.code.length > 0; 118 | } 119 | 120 | /** 121 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 122 | * `recipient`, forwarding all available gas and reverting on errors. 123 | * 124 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 125 | * of certain opcodes, possibly making contracts go over the 2300 gas limit 126 | * imposed by `transfer`, making them unable to receive funds via 127 | * `transfer`. {sendValue} removes this limitation. 128 | * 129 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 130 | * 131 | * IMPORTANT: because control is transferred to `recipient`, care must be 132 | * taken to not create reentrancy vulnerabilities. Consider using 133 | * {ReentrancyGuard} or the 134 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 135 | */ 136 | function sendValue(address payable recipient, uint256 amount) internal { 137 | require(address(this).balance >= amount, "Address: insufficient balance"); 138 | 139 | (bool success, ) = recipient.call{value: amount}(""); 140 | require(success, "Address: unable to send value, recipient may have reverted"); 141 | } 142 | 143 | /** 144 | * @dev Performs a Solidity function call using a low level `call`. A 145 | * plain `call` is an unsafe replacement for a function call: use this 146 | * function instead. 147 | * 148 | * If `target` reverts with a revert reason, it is bubbled up by this 149 | * function (like regular Solidity function calls). 150 | * 151 | * Returns the raw returned data. To convert to the expected return value, 152 | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 153 | * 154 | * Requirements: 155 | * 156 | * - `target` must be a contract. 157 | * - calling `target` with `data` must not revert. 158 | * 159 | * _Available since v3.1._ 160 | */ 161 | function functionCall(address target, bytes memory data) internal returns (bytes memory) { 162 | return functionCall(target, data, "Address: low-level call failed"); 163 | } 164 | 165 | /** 166 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 167 | * `errorMessage` as a fallback revert reason when `target` reverts. 168 | * 169 | * _Available since v3.1._ 170 | */ 171 | function functionCall( 172 | address target, 173 | bytes memory data, 174 | string memory errorMessage 175 | ) internal returns (bytes memory) { 176 | return functionCallWithValue(target, data, 0, errorMessage); 177 | } 178 | 179 | /** 180 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 181 | * but also transferring `value` wei to `target`. 182 | * 183 | * Requirements: 184 | * 185 | * - the calling contract must have an ETH balance of at least `value`. 186 | * - the called Solidity function must be `payable`. 187 | * 188 | * _Available since v3.1._ 189 | */ 190 | function functionCallWithValue( 191 | address target, 192 | bytes memory data, 193 | uint256 value 194 | ) internal returns (bytes memory) { 195 | return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 196 | } 197 | 198 | /** 199 | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 200 | * with `errorMessage` as a fallback revert reason when `target` reverts. 201 | * 202 | * _Available since v3.1._ 203 | */ 204 | function functionCallWithValue( 205 | address target, 206 | bytes memory data, 207 | uint256 value, 208 | string memory errorMessage 209 | ) internal returns (bytes memory) { 210 | require(address(this).balance >= value, "Address: insufficient balance for call"); 211 | require(isContract(target), "Address: call to non-contract"); 212 | 213 | (bool success, bytes memory returndata) = target.call{value: value}(data); 214 | return verifyCallResult(success, returndata, errorMessage); 215 | } 216 | 217 | /** 218 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 219 | * but performing a static call. 220 | * 221 | * _Available since v3.3._ 222 | */ 223 | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { 224 | return functionStaticCall(target, data, "Address: low-level static call failed"); 225 | } 226 | 227 | /** 228 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 229 | * but performing a static call. 230 | * 231 | * _Available since v3.3._ 232 | */ 233 | function functionStaticCall( 234 | address target, 235 | bytes memory data, 236 | string memory errorMessage 237 | ) internal view returns (bytes memory) { 238 | require(isContract(target), "Address: static call to non-contract"); 239 | 240 | (bool success, bytes memory returndata) = target.staticcall(data); 241 | return verifyCallResult(success, returndata, errorMessage); 242 | } 243 | 244 | /** 245 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 246 | * but performing a delegate call. 247 | * 248 | * _Available since v3.4._ 249 | */ 250 | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { 251 | return functionDelegateCall(target, data, "Address: low-level delegate call failed"); 252 | } 253 | 254 | /** 255 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 256 | * but performing a delegate call. 257 | * 258 | * _Available since v3.4._ 259 | */ 260 | function functionDelegateCall( 261 | address target, 262 | bytes memory data, 263 | string memory errorMessage 264 | ) internal returns (bytes memory) { 265 | require(isContract(target), "Address: delegate call to non-contract"); 266 | 267 | (bool success, bytes memory returndata) = target.delegatecall(data); 268 | return verifyCallResult(success, returndata, errorMessage); 269 | } 270 | 271 | /** 272 | * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the 273 | * revert reason using the provided one. 274 | * 275 | * _Available since v4.3._ 276 | */ 277 | function verifyCallResult( 278 | bool success, 279 | bytes memory returndata, 280 | string memory errorMessage 281 | ) internal pure returns (bytes memory) { 282 | if (success) { 283 | return returndata; 284 | } else { 285 | // Look for revert reason and bubble it up if present 286 | if (returndata.length > 0) { 287 | // The easiest way to bubble the revert reason is using memory via assembly 288 | 289 | assembly { 290 | let returndata_size := mload(returndata) 291 | revert(add(32, returndata), returndata_size) 292 | } 293 | } else { 294 | revert(errorMessage); 295 | } 296 | } 297 | } 298 | } 299 | 300 | library SafeERC20 { 301 | using Address for address; 302 | 303 | function safeTransfer( 304 | IERC20 token, 305 | address to, 306 | uint256 value 307 | ) internal { 308 | _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 309 | } 310 | 311 | function safeTransferFrom( 312 | IERC20 token, 313 | address from, 314 | address to, 315 | uint256 value 316 | ) internal { 317 | _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 318 | } 319 | 320 | /** 321 | * @dev Deprecated. This function has issues similar to the ones found in 322 | * {IERC20-approve}, and its usage is discouraged. 323 | * 324 | * Whenever possible, use {safeIncreaseAllowance} and 325 | * {safeDecreaseAllowance} instead. 326 | */ 327 | function safeApprove( 328 | IERC20 token, 329 | address spender, 330 | uint256 value 331 | ) internal { 332 | // safeApprove should only be called when setting an initial allowance, 333 | // or when resetting it to zero. To increase and decrease it, use 334 | // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 335 | require( 336 | (value == 0) || (token.allowance(address(this), spender) == 0), 337 | "SafeERC20: approve from non-zero to non-zero allowance" 338 | ); 339 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 340 | } 341 | 342 | function safeIncreaseAllowance( 343 | IERC20 token, 344 | address spender, 345 | uint256 value 346 | ) internal { 347 | uint256 newAllowance = token.allowance(address(this), spender) + value; 348 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 349 | } 350 | 351 | function safeDecreaseAllowance( 352 | IERC20 token, 353 | address spender, 354 | uint256 value 355 | ) internal { 356 | unchecked { 357 | uint256 oldAllowance = token.allowance(address(this), spender); 358 | require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); 359 | uint256 newAllowance = oldAllowance - value; 360 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 361 | } 362 | } 363 | 364 | /** 365 | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 366 | * on the return value: the return value is optional (but if data is returned, it must not be false). 367 | * @param token The token targeted by the call. 368 | * @param data The call data (encoded using abi.encode or one of its variants). 369 | */ 370 | function _callOptionalReturn(IERC20 token, bytes memory data) private { 371 | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 372 | // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 373 | // the target address contains contract code and also asserts for success in the low-level call. 374 | 375 | bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); 376 | if (returndata.length > 0) { 377 | // Return data is optional 378 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 379 | } 380 | } 381 | } 382 | 383 | abstract contract Context { 384 | function _msgSender() internal view virtual returns (address) { 385 | return msg.sender; 386 | } 387 | 388 | function _msgData() internal view virtual returns (bytes calldata) { 389 | return msg.data; 390 | } 391 | } 392 | 393 | abstract contract Ownable is Context { 394 | address private _owner; 395 | 396 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 397 | 398 | /** 399 | * @dev Initializes the contract setting the deployer as the initial owner. 400 | */ 401 | constructor() { 402 | _transferOwnership(_msgSender()); 403 | } 404 | 405 | /** 406 | * @dev Returns the address of the current owner. 407 | */ 408 | function owner() public view virtual returns (address) { 409 | return _owner; 410 | } 411 | 412 | /** 413 | * @dev Throws if called by any account other than the owner. 414 | */ 415 | modifier onlyOwner() { 416 | require(owner() == _msgSender(), "Ownable: caller is not the owner"); 417 | _; 418 | } 419 | 420 | /** 421 | * @dev Leaves the contract without owner. It will not be possible to call 422 | * `onlyOwner` functions anymore. Can only be called by the current owner. 423 | * 424 | * NOTE: Renouncing ownership will leave the contract without an owner, 425 | * thereby removing any functionality that is only available to the owner. 426 | */ 427 | function renounceOwnership() public virtual onlyOwner { 428 | _transferOwnership(address(0)); 429 | } 430 | 431 | /** 432 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 433 | * Can only be called by the current owner. 434 | */ 435 | function transferOwnership(address newOwner) public virtual onlyOwner { 436 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 437 | _transferOwnership(newOwner); 438 | } 439 | 440 | /** 441 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 442 | * Internal function without access restriction. 443 | */ 444 | function _transferOwnership(address newOwner) internal virtual { 445 | address oldOwner = _owner; 446 | _owner = newOwner; 447 | emit OwnershipTransferred(oldOwner, newOwner); 448 | } 449 | } 450 | 451 | library SafeMath { 452 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 453 | uint256 c = a + b; 454 | require(c >= a, "SafeMath: addition overflow"); 455 | 456 | return c; 457 | } 458 | 459 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 460 | return sub(a, b, "SafeMath: subtraction overflow"); 461 | } 462 | 463 | function sub( 464 | uint256 a, 465 | uint256 b, 466 | string memory errorMessage 467 | ) internal pure returns (uint256) { 468 | require(b <= a, errorMessage); 469 | uint256 c = a - b; 470 | 471 | return c; 472 | } 473 | 474 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 475 | if (a == 0) { 476 | return 0; 477 | } 478 | 479 | uint256 c = a * b; 480 | require(c / a == b, "SafeMath: multiplication overflow"); 481 | 482 | return c; 483 | } 484 | 485 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 486 | return div(a, b, "SafeMath: division by zero"); 487 | } 488 | 489 | function div( 490 | uint256 a, 491 | uint256 b, 492 | string memory errorMessage 493 | ) internal pure returns (uint256) { 494 | require(b > 0, errorMessage); 495 | uint256 c = a / b; 496 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 497 | 498 | return c; 499 | } 500 | 501 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 502 | return mod(a, b, "SafeMath: modulo by zero"); 503 | } 504 | 505 | function mod( 506 | uint256 a, 507 | uint256 b, 508 | string memory errorMessage 509 | ) internal pure returns (uint256) { 510 | require(b != 0, errorMessage); 511 | return a % b; 512 | } 513 | } 514 | 515 | contract MutilTransfer is Ownable { 516 | using SafeMath for uint256; 517 | using SafeERC20 for IERC20; 518 | uint256 public fee = 0; //手续费 519 | 520 | function transferEth(address payable[] memory to, uint256 amount) 521 | public 522 | payable 523 | { 524 | uint256 length = to.length; 525 | require( 526 | msg.value == length.mul(amount).add(fee), 527 | "Transfer amount error" 528 | ); 529 | 530 | payable(owner()).transfer(fee); 531 | for (uint256 i = 0; i < length; i++) { 532 | to[i].transfer(amount); 533 | } 534 | } 535 | 536 | function transferProEth(address payable[] memory to, uint256[] memory amount) 537 | public 538 | payable 539 | { 540 | uint256 length = to.length; 541 | require(to.length == amount.length, "Transfer length error"); 542 | uint allAmount; 543 | for (uint256 i = 0; i < length; i++) { 544 | allAmount += amount[i]; 545 | } 546 | require(msg.value == allAmount.add(fee), "Transfer amount error"); 547 | payable(owner()).transfer(fee); 548 | for (uint256 i = 0; i < length; i++) { 549 | to[i].transfer(amount[i]); 550 | } 551 | } 552 | 553 | function transferToken( 554 | address _token, 555 | address[] memory to, 556 | uint256 amount 557 | ) public payable { 558 | IERC20 token = IERC20(_token); 559 | require(fee == msg.value, "Transfer amount error"); 560 | payable(owner()).transfer(fee); 561 | uint256 length = to.length; 562 | for (uint256 i = 0; i < length; i++) { 563 | token.safeTransferFrom(msg.sender, to[i], amount); 564 | } 565 | } 566 | 567 | function transferProToken( 568 | address _token, 569 | address[] memory to, 570 | uint256[] memory amount 571 | ) public payable { 572 | IERC20 token = IERC20(_token); 573 | require(fee == msg.value, "Transfer amount error"); 574 | require(to.length == amount.length, "Transfer length error"); 575 | payable(owner()).transfer(fee); 576 | uint256 length = to.length; 577 | for (uint256 i = 0; i < length; i++) { 578 | token.safeTransferFrom(msg.sender, to[i], amount[i]); 579 | } 580 | } 581 | 582 | function setFee(uint256 _fee) public onlyOwner { 583 | fee = _fee; 584 | } 585 | } --------------------------------------------------------------------------------