编译器
0.4.26+commit.4563c3fc
文件 1 的 3:IERC20.sol
pragma solidity ^0.4.23;
contract IERC20 {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
文件 2 的 3:MultiSend.sol
pragma solidity ^0.4.23;
import "./IERC20.sol";
import "./SafeERC20.sol";
contract MultiSend {
using SafeERC20 for IERC20;
bool private locked;
mapping(address => bool) public admins;
event AdminSet(address indexed newAdmin);
event AdminRemoved(address indexed oldAdmin);
event Transfer(address indexed from, address indexed to, address indexed tokenAddress, uint tokens);
constructor() public {
admins[msg.sender] = true;
emit AdminSet(msg.sender);
}
modifier onlyAdmin() {
require(admins[msg.sender], "Must be an admin");
_;
}
modifier reentrancyGuard() {
require(!locked, "Reentrancy Guard: Reentrant call detected!");
locked = true;
_;
locked = false;
}
function setAdmin(address admin) external onlyAdmin returns(bool success){
admins[admin] = true;
emit AdminSet(admin);
return admins[admin];
}
function removeAdmin(address admin) external onlyAdmin returns(bool success){
admins[admin] = false;
emit AdminRemoved(admin);
return !admins[admin];
}
function withdraw(address returnee, address tokenAddress, uint256 amount)external onlyAdmin returns(bool success){
IERC20 token = IERC20(tokenAddress);
uint256 balance = token.balanceOf(address(this));
require(balance > 0, "There are no tokens to withdraw");
require(balance >= amount, "Attempting to withdraw more tokens than available");
require(token.safeTransfer(returnee, amount) == true, "Failed to transfer tokens");
emit Transfer(address(this), returnee, tokenAddress, amount);
return true;
}
function sendEth(address[] memory recipients, uint256[] memory amounts) public payable reentrancyGuard returns (bool) {
require(recipients.length == amounts.length, "Recipients array must have same length as amounts");
uint256 sentTotal = 0;
for (uint i = 0; i < recipients.length; i++) {
sentTotal = sentTotal + amounts[i];
require(sentTotal <= msg.value, "Ran out of funds. 'value' should be at least sum of amounts");
require(recipients[i].call.value(amounts[i])(), "Failed to send");
emit Transfer(msg.sender, recipients[i], address(0), amounts[i]);
}
uint256 remainingValue = msg.value - sentTotal;
if (remainingValue > 0) {
require(msg.sender.call.value(remainingValue)(), "Failed to send remaining back to self");
emit Transfer(address(this), msg.sender, address(0), remainingValue);
}
return true;
}
function sendErc20(address tokenAddress, address[] memory recipients, uint256[] memory amounts) public returns (bool) {
require(recipients.length == amounts.length, "Recipients array must have same length as amounts");
IERC20 token = IERC20(tokenAddress);
uint256 total = 0;
for (uint i = 0; i < recipients.length; i++) {
total += amounts[i];
}
require(token.allowance(msg.sender, address(this)) >= total, "Insufficient token allowance");
for (i = 0; i < recipients.length; i++) {
require(token.safeTransferFrom(msg.sender, recipients[i], amounts[i]) == true, "Failed to transfer");
emit Transfer(msg.sender, recipients[i], tokenAddress, amounts[i]);
}
return true;
}
}
文件 3 的 3:SafeERC20.sol
pragma solidity ^0.4.23;
import "./IERC20.sol";
library SafeERC20 {
function safeTransfer(IERC20 _token, address _to, uint256 _value) internal returns (bool) {
uint256 prevBalance = _token.balanceOf(address(this));
if (prevBalance < _value) {
return false;
}
address(_token).call(
abi.encodeWithSignature("transfer(address,uint256)", _to, _value)
);
return prevBalance - _value == _token.balanceOf(address(this));
}
function safeTransferFrom(
IERC20 _token,
address _from,
address _to,
uint256 _value
) internal returns (bool)
{
uint256 prevBalance = _token.balanceOf(_from);
if (
prevBalance < _value ||
_token.allowance(_from, address(this)) < _value
) {
return false;
}
address(_token).call(
abi.encodeWithSignature("transferFrom(address,address,uint256)", _from, _to, _value)
);
return prevBalance - _value == _token.balanceOf(_from);
}
function safeApprove(IERC20 _token, address _spender, uint256 _value) internal returns (bool) {
address(_token).call(
abi.encodeWithSignature("approve(address,uint256)",_spender, _value)
);
return _token.allowance(address(this), _spender) == _value;
}
function clearApprove(IERC20 _token, address _spender) internal returns (bool) {
bool success = safeApprove(_token, _spender, 0);
if (!success) {
success = safeApprove(_token, _spender, 1);
}
return success;
}
}
{
"compilationTarget": {
"MultiSend.sol": "MultiSend"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"admin","type":"address"}],"name":"removeAdmin","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"recipients","type":"address[]"},{"name":"amounts","type":"uint256[]"}],"name":"sendEth","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"admins","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"admin","type":"address"}],"name":"setAdmin","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"recipients","type":"address[]"},{"name":"amounts","type":"uint256[]"}],"name":"sendErc20","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"returnee","type":"address"},{"name":"tokenAddress","type":"address"},{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"newAdmin","type":"address"}],"name":"AdminSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"oldAdmin","type":"address"}],"name":"AdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":true,"name":"tokenAddress","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"}],"name":"Transfer","type":"event"}]