This contract is useful when you want to save gas to send ETH to multiple recipient. There are 2 ways to execute, one is send based on right in ETH value, another way is send from contract's ETH balance.
Few things worth to take note:
<?Php
$abi = '[{"constant":true,"inputs":[],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addresses","type":"address[]"},{"name":"amount","type":"uint256"}],"name":"multiSendFixedAmountFromContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addresses","type":"address[]"},{"name":"amounts","type":"uint256[]"}],"name":"multiSendArrayAmount","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addresses","type":"address[]"},{"name":"amount","type":"uint256"}],"name":"multiSendFixedAmount","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"}]';
$bytecode = "608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506106f7806100606000396000f300608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806312065fe014610097578063171347d2146100c25780633ccfd60b14610132578063893d20e8146101495780638da5cb5b146101a05780638dd931a5146101f7578063e294418c14610293575b60008036905014151561009557600080fd5b005b3480156100a357600080fd5b506100ac6102f6565b6040518082815260200191505060405180910390f35b3480156100ce57600080fd5b506101306004803603810190808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190929190505050610315565b005b34801561013e57600080fd5b50610147610414565b005b34801561015557600080fd5b5061015e6104cf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101ac57600080fd5b506101b56104f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610291600480360381019080803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929050505061051d565b005b6102f46004803603810190808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190929190505050610616565b005b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b6000806000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561037357600080fd5b6000845111151561038357600080fd5b60008311151561039257600080fd5b83519150600090505b8181101561040e5783818151811015156103b157fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610400573d6000803e3d6000fd5b50808060010191505061039b565b50505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561046f57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501580156104cc573d6000803e3d6000fd5b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000806000865111151561053357600080fd5b8451865114151561054357600080fd5b8551935060009250600091505b8382101561060057848281518110151561056657fe5b90602001906020020151905060008111151561058157600080fd5b808301925034831115151561059557600080fd5b85828151811015156105a357fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156105f2573d6000803e3d6000fd5b508180600101925050610550565b348314151561060e57600080fd5b505050505050565b6000806000845111151561062957600080fd5b60008311151561063857600080fd5b348385510214151561064957600080fd5b83519150600090505b818110156106c557838181518110151561066857fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f193505050501580156106b7573d6000803e3d6000fd5b508080600101915050610652565b505050505600a165627a7a723058203a876db5068e91f2eb23127519a93d1e23092311dea7f3675c3263132eaba8d90029";
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<meta name="keywords" content="<?php echo $_HTML['meta']['keywords']?>">
<title><?php echo $_HTML['title']?></title>
<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js@1.0.0-beta.34/dist/web3.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ethjs@0.3.4/dist/ethjs.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ethjs-contract@0.2.3/dist/ethjs-contract.min.js"></script>
<!-- Bootstrap core CSS -->
<link href="../media/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="../media/vendor/enlighter/css/enlighterjs.min.css?<?php echo time()?>" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="../media/css/simple-sidebar.css?<?php echo time()?>" rel="stylesheet">
<!-- Bootstrap core JavaScript -->
<script src="../media/vendor/jquery/jquery.min.js"></script>
</head>
<body>
<div class="d-flex" id="wrapper">
<!-- Page Content -->
<div id="page-content-wrapper" >
<p>
<h6 class="mt-3">Experiment</h6>
<ul>
<li>Contract deployment <a target="_blank" href="https://ropsten.etherscan.io/address/0x04365d35ccbf70cfee1efd9464acf2fd4f926d20"><img style='width:12px;height:12px;' src='../media/images/external_link.png'/></a>
, gas consumed 459,627.
</li>
<li>
✔ Call multiSendFixedAmount with input of 2 <b>addresses with ETH balance</b> <a target="_blank" href="https://ropsten.etherscan.io/tx/0x79a69fe9d16fe4d436500be2ff2831634ec76a5e858e6f9c28b66cf9286208da"><img style='width:12px;height:12px;' src='../media/images/external_link.png'/></a>. Gas consumed 38,160, with 19,080 gas per ETH transfer.
</li>
<li>
✖ Call multiSendFixedAmount with input of 2 <b>zero ETH balance address</b> <a target="_blank" href="https://ropsten.etherscan.io/tx/0x259d97ee503dd1d7da421a48ac5bdc2712958da975c073abdb43e624b2a39ed7"><img style='width:12px;height:12px;' src='../media/images/external_link.png'/></a>. Gas consumed 88,160, with 44,080 gas per ETH transfer.
</li>
</ul>
</p>
<p>
<h6 class="mt-3">ABI</h6>
<textarea class="form-control" rows="5" id="comment" readonly><?php echo $abi;?></textarea>
</p>
<p>
<h6 class="mt-3">Bytecode</h6>
<textarea class="form-control" rows="5" id="comment" readonly><?php echo $bytecode;?></textarea>
</p>
<p>
<button id="deploy-contract" class="btn btn-primary">Deploy Contract</button> Via Meta Mask <b> OR </b> <a href="eth_sc_deploy_contract.php?data=<?php echo $bytecode?>&disable_fields=data,to" target="_parent">Use Manual Way</a>
</p>
<script>
try {
// the abi
const contractABI = JSON.parse('<?php echo $abi?>');
// bytecode
const contractBytecode = '<?php echo $bytecode?>';
var button = document.querySelector('button#deploy-contract');
button.addEventListener('click', async (e) => {
e.srcElement.innerHTML = "Check Connection ...";
// Modern dapp browsers...
if (window.ethereum) {
window.web3 = new Web3(ethereum);
try {
// Request account access if needed
await ethereum.enable();
e.srcElement.innerHTML = "Deploy Contract";
// Modern dapp browsers...
// Acccounts now exposed
startApp(window.web3);
} catch (error) {
e.srcElement.innerHTML = "Deploy Contract";
// User denied account access...
}
}
// Legacy dapp browsers...
else if (window.web3) {
window.web3 = new Web3(web3.currentProvider);
// Acccounts always exposed
e.srcElement.innerHTML = "Deploy Contract";
startApp(window.web3);
}
// Non-dapp browsers...
else {
e.srcElement.innerHTML = "Deploy Contract";
alert('Non-Ethereum browser detected. You should consider trying MetaMask!');
}
});
function startApp(web3) {
const eth = new Eth(web3.currentProvider);
const contract = new EthContract(eth);
eth.accounts().then((accounts) => {
const contractFactory = eth.contract(contractABI, contractBytecode, {
from: accounts[0],
gas: 470000,
});
// create a new contract
contractFactory.new((error, result) => {
// result null '0x928sdfk...' (i.e. the transaction hash)
});
});
}
} catch (e) {
alert("Caught! " + e.message);
}
</script>
</div>
<!-- /#page-content-wrapper -->
</div>
<!-- /#wrapper -->
</body>
<script src="../media/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="../media/vendor/enlighter/js/enlighterjs.min.js"></script>
<!-- Menu Toggle Script -->
<script type="text/javascript">
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
});
// - highlight all pre + code tags (CSS3 selectors)
// - use javascript as default language
// - use theme "enlighter" as default theme
// - replace tabs with 2 spaces
EnlighterJS.init('pre', 'code', {
language : 'php',
theme: 'enlighter',
indent : 4
});
$(document).ready(function(){
$('[data-toggle="tooltip"]').tooltip();
});
</script>
<script type="text/javascript" src="../media/vendor/iframeresizer/js/iframeResizer.contentWindow.min.js"></script>
</html>
pragma solidity ^0.4.17;
contract MultiSendEth {
address public owner;
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
constructor() public{
owner = msg.sender;
}
//accept eth deposit
function() external payable {
require(msg.data.length == 0); //to prevent invalid calls.
}
//getowner
function getOwner() public view returns (address) {
return owner;
}
//getbalance
function getBalance() public view returns (uint256) {
return address(this).balance;
}
//withdraw whole balance
function withdraw() public onlyOwner{
msg.sender.transfer(address(this).balance);
}
function multiSendArrayAmount(address[] addresses, uint256[] amounts) public payable {
require(addresses.length > 0);
require(addresses.length == amounts.length);
uint256 length = addresses.length;
uint256 currentSum = 0;
for (uint256 i = 0; i < length; i++) {
uint256 amount = amounts[i];
require(amount > 0);
currentSum += amount;
require(currentSum <= msg.value);
addresses[i].transfer(amount);
}
require(currentSum == msg.value);
}
function multiSendFixedAmount(address[] addresses, uint256 amount) public payable {
require(addresses.length > 0);
require(amount > 0);
require(addresses.length * amount == msg.value);
uint256 length = addresses.length;
for(uint256 i=0;i<length;i++) {
addresses[i].transfer(amount);
}
}
function multiSendFixedAmountFromContract(address[] addresses, uint256 amount) public onlyOwner {
require(addresses.length > 0);
require(amount > 0);
uint256 length = addresses.length;
for(uint256 i=0;i<length;i++) {
addresses[i].transfer(amount);
}
}
}