Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- PaymentSplitter
- Optimization enabled
- true
- Compiler version
- v0.6.12+commit.27d51765
- Optimization runs
- 200
- EVM Version
- istanbul
- Verified at
- 2026-04-24T14:09:41.914396Z
PaymentSplitter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
import './Context.sol';
import './SafeMath.sol';
/**
* @title PaymentSplitter
* @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
* that the Ether will be split in this way, since it is handled transparently by the contract.
*
* The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
* account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
* an amount proportional to the percentage of total shares they were assigned.
*
* `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
* accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
* function.
*/
contract PaymentSplitter is Context {
using SafeMath for uint256;
event PayeeAdded(address account, uint256 shares);
event PaymentReleased(address to, uint256 amount);
event PaymentReceived(address from, uint256 amount);
uint256 private _totalShares;
uint256 private _totalReleased;
mapping(address => uint256) private _shares;
mapping(address => uint256) private _released;
address[] private _payees;
/**
* @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
* the matching position in the `shares` array.
*
* All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
* duplicates in `payees`.
*/
constructor () public {
// 1000 shares total. 10 shares = 1%
_addPayee(0xA81eac3009bD6E6cCE36602d6851fDA789dDC3BB, 400);
_addPayee(0xF76Df69C8bf3bcFdBc46F69773749f2E308Fc2D1, 150);
_addPayee(0xFaDED72464D6e76e37300B467673b36ECc4d2ccF, 130);
_addPayee(0xEa9F106172697E3E363f9f4B292f73b1217b2a88, 100);
_addPayee(0x7e7e2bf7EdC52322ee1D251432c248693eCd9E0f, 55);
_addPayee(0x3DCa07E16B2Becd3eb76a9F9CE240B525451f887, 30);
_addPayee(0x20404Bd50e8640424a7D3BF41B3417C9AE765507, 30);
_addPayee(0x82eE15e7C0c923e512eB0C554a50E08254EbD660, 25);
_addPayee(0xFB015608e84b32f44361429B92B6d62B937e2015, 20);
_addPayee(0xFCd6AD49134A0755923c096382e5fc3b80Cb21b5, 10);
_addPayee(0xfD2D983aF16dA2965F5654a0166b8e33Cc3Cf5F1, 10);
_addPayee(0x6e43d04A2c8b8Dc3a6FA9DD35711559B493543d1, 10);
_addPayee(0x37fc5190c725F448fa9D88DE87843884164a684b, 10);
_addPayee(0x4425eD8684f3A6C1093E27FD44020B3917f29227, 10);
_addPayee(0x3b1356CA97A31b3a2DAd0e901b9F73380e00B66D, 10);
}
/**
* @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
* reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
* reliability of the events, and not the actual splitting of Ether.
*
* To learn more about this see the Solidity documentation for
* https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
* functions].
*/
receive () external payable virtual {
emit PaymentReceived(_msgSender(), msg.value);
}
/**
* @dev Getter for the total shares held by payees.
*/
function totalShares() public view returns (uint256) {
return _totalShares;
}
/**
* @dev Getter for the total amount of Ether already released.
*/
function totalReleased() public view returns (uint256) {
return _totalReleased;
}
/**
* @dev Getter for the amount of shares held by an account.
*/
function shares(address account) public view returns (uint256) {
return _shares[account];
}
/**
* @dev Getter for the amount of Ether already released to a payee.
*/
function released(address account) public view returns (uint256) {
return _released[account];
}
/**
* @dev Getter for the address of the payee number `index`.
*/
function payee(uint256 index) public view returns (address) {
return _payees[index];
}
/**
* @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
* total shares and their previous withdrawals.
*/
function release(address payable account) public virtual {
require(_shares[account] > 0, "PaymentSplitter: account has no shares");
uint256 totalReceived = address(this).balance.add(_totalReleased);
uint256 payment = totalReceived.mul(_shares[account]).div(_totalShares).sub(_released[account]);
require(payment != 0, "PaymentSplitter: account is not due payment");
_released[account] = _released[account].add(payment);
_totalReleased = _totalReleased.add(payment);
account.transfer(payment);
emit PaymentReleased(account, payment);
}
function releaseAll() external virtual {
for (uint256 i = 0; i < _payees.length; i++) {
release(address(uint160(_payees[i])));
}
}
/**
* @dev Add a new payee to the contract.
* @param account The address of the payee to add.
* @param shares_ The number of shares owned by the payee.
*/
function _addPayee(address account, uint256 shares_) private {
require(account != address(0), "PaymentSplitter: account is the zero address");
require(shares_ > 0, "PaymentSplitter: shares are 0");
require(_shares[account] == 0, "PaymentSplitter: account already has shares");
_payees.push(account);
_shares[account] = shares_;
_totalShares = _totalShares.add(shares_);
emit PayeeAdded(account, shares_);
}
}
/
pragma solidity ^0.6.12;
// File: @openzeppelin/contracts/math/SafeMath.sol
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/
pragma solidity ^0.6.12;
// File: @openzeppelin/contracts/GSN/Context.sol
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
Compiler Settings
{"remappings":[],"optimizer":{"runs":200,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"istanbul","compilationTarget":{"PaymentSplitter.sol":"PaymentSplitter"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"PayeeAdded","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false},{"type":"uint256","name":"shares","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"PaymentReceived","inputs":[{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"PaymentReleased","inputs":[{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"payee","inputs":[{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"release","inputs":[{"type":"address","name":"account","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"releaseAll","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"released","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"shares","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalReleased","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalShares","inputs":[]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x60806040523480156200001157600080fd5b506200003473a81eac3009bd6e6cce36602d6851fda789ddc3bb61019062000208565b6200005573f76df69c8bf3bcfdbc46f69773749f2e308fc2d1609662000208565b6200007673faded72464d6e76e37300b467673b36ecc4d2ccf608262000208565b6200009773ea9f106172697e3e363f9f4b292f73b1217b2a88606462000208565b620000b8737e7e2bf7edc52322ee1d251432c248693ecd9e0f603762000208565b620000d9733dca07e16b2becd3eb76a9f9ce240b525451f887601e62000208565b620000fa7320404bd50e8640424a7d3bf41b3417c9ae765507601e62000208565b6200011b7382ee15e7c0c923e512eb0c554a50e08254ebd660601962000208565b6200013c73fb015608e84b32f44361429b92b6d62b937e2015601462000208565b6200015d73fcd6ad49134a0755923c096382e5fc3b80cb21b5600a62000208565b6200017e73fd2d983af16da2965f5654a0166b8e33cc3cf5f1600a62000208565b6200019f736e43d04a2c8b8dc3a6fa9dd35711559b493543d1600a62000208565b620001c07337fc5190c725f448fa9d88de87843884164a684b600a62000208565b620001e1734425ed8684f3a6c1093e27fd44020b3917f29227600a62000208565b62000202733b1356ca97a31b3a2dad0e901b9f73380e00b66d600a62000208565b6200041d565b6001600160a01b0382166200024f5760405162461bcd60e51b815260040180806020018281038252602c81526020018062000b7f602c913960400191505060405180910390fd5b60008111620002a5576040805162461bcd60e51b815260206004820152601d60248201527f5061796d656e7453706c69747465723a20736861726573206172652030000000604482015290519081900360640190fd5b6001600160a01b03821660009081526002602052604090205415620002fc5760405162461bcd60e51b815260040180806020018281038252602b81526020018062000bab602b913960400191505060405180910390fd5b60048054600181019091557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b03841690811790915560009081526002602090815260408220839055905462000370918390620003bb811b6200046e17901c565b600055604080516001600160a01b03841681526020810183905281517f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac929181900390910190a15050565b60008282018381101562000416576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b610752806200042d6000396000f3fe6080604052600436106100745760003560e01c80638b83209b1161004e5780638b83209b1461013a5780639852595c14610180578063ce7c2ac2146101b3578063e33b7de3146101e6576100c4565b806319165587146100c95780633a98ef39146100fe5780635be7fde814610125576100c4565b366100c4577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7706100a26101fb565b604080516001600160a01b0390921682523460208301528051918290030190a1005b600080fd5b3480156100d557600080fd5b506100fc600480360360208110156100ec57600080fd5b50356001600160a01b03166101ff565b005b34801561010a57600080fd5b506101136103c0565b60408051918252519081900360200190f35b34801561013157600080fd5b506100fc6103c6565b34801561014657600080fd5b506101646004803603602081101561015d57600080fd5b5035610408565b604080516001600160a01b039092168252519081900360200190f35b34801561018c57600080fd5b50610113600480360360208110156101a357600080fd5b50356001600160a01b0316610432565b3480156101bf57600080fd5b50610113600480360360208110156101d657600080fd5b50356001600160a01b031661044d565b3480156101f257600080fd5b50610113610468565b3390565b6001600160a01b0381166000908152600260205260409020546102535760405162461bcd60e51b81526004018080602001828103825260268152602001806106ab6026913960400191505060405180910390fd5b600061026a6001544761046e90919063ffffffff16565b6001600160a01b038316600090815260036020908152604080832054835460029093529083205493945091926102b692916102b0916102aa9087906104d1565b9061052a565b9061056c565b9050806102f45760405162461bcd60e51b815260040180806020018281038252602b8152602001806106d1602b913960400191505060405180910390fd5b6001600160a01b038316600090815260036020526040902054610317908261046e565b6001600160a01b03841660009081526003602052604090205560015461033d908261046e565b6001556040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015610376573d6000803e3d6000fd5b50604080516001600160a01b03851681526020810183905281517fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b056929181900390910190a1505050565b60005490565b60005b600454811015610405576103fd600482815481106103e357fe5b6000918252602090912001546001600160a01b03166101ff565b6001016103c9565b50565b60006004828154811061041757fe5b6000918252602090912001546001600160a01b031692915050565b6001600160a01b031660009081526003602052604090205490565b6001600160a01b031660009081526002602052604090205490565b60015490565b6000828201838110156104c8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6000826104e0575060006104cb565b828202828482816104ed57fe5b04146104c85760405162461bcd60e51b81526004018080602001828103825260218152602001806106fc6021913960400191505060405180910390fd5b60006104c883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506105ae565b60006104c883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610650565b6000818361063a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156105ff5781810151838201526020016105e7565b50505050905090810190601f16801561062c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161064657fe5b0495945050505050565b600081848411156106a25760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156105ff5781810151838201526020016105e7565b50505090039056fe5061796d656e7453706c69747465723a206163636f756e7420686173206e6f207368617265735061796d656e7453706c69747465723a206163636f756e74206973206e6f7420647565207061796d656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220ead52962b65f5ecdc89a2ed0dbd125752e84eda9a4544901bfff801db5d6533064736f6c634300060c00335061796d656e7453706c69747465723a206163636f756e7420697320746865207a65726f20616464726573735061796d656e7453706c69747465723a206163636f756e7420616c72656164792068617320736861726573
Deployed ByteCode
0x6080604052600436106100745760003560e01c80638b83209b1161004e5780638b83209b1461013a5780639852595c14610180578063ce7c2ac2146101b3578063e33b7de3146101e6576100c4565b806319165587146100c95780633a98ef39146100fe5780635be7fde814610125576100c4565b366100c4577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be7706100a26101fb565b604080516001600160a01b0390921682523460208301528051918290030190a1005b600080fd5b3480156100d557600080fd5b506100fc600480360360208110156100ec57600080fd5b50356001600160a01b03166101ff565b005b34801561010a57600080fd5b506101136103c0565b60408051918252519081900360200190f35b34801561013157600080fd5b506100fc6103c6565b34801561014657600080fd5b506101646004803603602081101561015d57600080fd5b5035610408565b604080516001600160a01b039092168252519081900360200190f35b34801561018c57600080fd5b50610113600480360360208110156101a357600080fd5b50356001600160a01b0316610432565b3480156101bf57600080fd5b50610113600480360360208110156101d657600080fd5b50356001600160a01b031661044d565b3480156101f257600080fd5b50610113610468565b3390565b6001600160a01b0381166000908152600260205260409020546102535760405162461bcd60e51b81526004018080602001828103825260268152602001806106ab6026913960400191505060405180910390fd5b600061026a6001544761046e90919063ffffffff16565b6001600160a01b038316600090815260036020908152604080832054835460029093529083205493945091926102b692916102b0916102aa9087906104d1565b9061052a565b9061056c565b9050806102f45760405162461bcd60e51b815260040180806020018281038252602b8152602001806106d1602b913960400191505060405180910390fd5b6001600160a01b038316600090815260036020526040902054610317908261046e565b6001600160a01b03841660009081526003602052604090205560015461033d908261046e565b6001556040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015610376573d6000803e3d6000fd5b50604080516001600160a01b03851681526020810183905281517fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b056929181900390910190a1505050565b60005490565b60005b600454811015610405576103fd600482815481106103e357fe5b6000918252602090912001546001600160a01b03166101ff565b6001016103c9565b50565b60006004828154811061041757fe5b6000918252602090912001546001600160a01b031692915050565b6001600160a01b031660009081526003602052604090205490565b6001600160a01b031660009081526002602052604090205490565b60015490565b6000828201838110156104c8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6000826104e0575060006104cb565b828202828482816104ed57fe5b04146104c85760405162461bcd60e51b81526004018080602001828103825260218152602001806106fc6021913960400191505060405180910390fd5b60006104c883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506105ae565b60006104c883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610650565b6000818361063a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156105ff5781810151838201526020016105e7565b50505050905090810190601f16801561062c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161064657fe5b0495945050505050565b600081848411156106a25760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156105ff5781810151838201526020016105e7565b50505090039056fe5061796d656e7453706c69747465723a206163636f756e7420686173206e6f207368617265735061796d656e7453706c69747465723a206163636f756e74206973206e6f7420647565207061796d656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220ead52962b65f5ecdc89a2ed0dbd125752e84eda9a4544901bfff801db5d6533064736f6c634300060c0033