Contract Name:
OwnedDistributor
Contract Source Code:
<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
pragma solidity =0.6.6;
import "./libraries/SafeMath.sol";
import "./interfaces/IImx.sol";
import "./interfaces/IClaimable.sol";
abstract contract Distributor is IClaimable {
using SafeMath for uint;
address public immutable imx;
address public immutable claimable;
struct Recipient {
uint shares;
uint lastShareIndex;
uint credit;
}
mapping(address => Recipient) public recipients;
uint public totalShares;
uint public shareIndex;
event UpdateShareIndex(uint shareIndex);
event UpdateCredit(address indexed account, uint lastShareIndex, uint credit);
event Claim(address indexed account, uint amount);
event EditRecipient(address indexed account, uint shares, uint totalShares);
constructor (
address imx_,
address claimable_
) public {
imx = imx_;
claimable = claimable_;
}
function updateShareIndex() public virtual nonReentrant returns (uint _shareIndex) {
if (totalShares == 0) return shareIndex;
uint amount = IClaimable(claimable).claim();
if (amount == 0) return shareIndex;
_shareIndex = amount.mul(2**160).div(totalShares).add(shareIndex);
shareIndex = _shareIndex;
emit UpdateShareIndex(_shareIndex);
}
function updateCredit(address account) public returns (uint credit) {
uint _shareIndex = updateShareIndex();
if (_shareIndex == 0) return 0;
Recipient storage recipient = recipients[account];
credit = recipient.credit + _shareIndex.sub(recipient.lastShareIndex).mul(recipient.shares) / 2**160;
recipient.lastShareIndex = _shareIndex;
recipient.credit = credit;
emit UpdateCredit(account, _shareIndex, credit);
}
function claimInternal(address account) internal virtual returns (uint amount) {
amount = updateCredit(account);
if (amount > 0) {
recipients[account].credit = 0;
IImx(imx).transfer(account, amount);
emit Claim(account, amount);
}
}
function claim() external virtual override returns (uint amount) {
return claimInternal(msg.sender);
}
function editRecipientInternal(address account, uint shares) internal {
updateCredit(account);
Recipient storage recipient = recipients[account];
uint prevShares = recipient.shares;
uint _totalShares = shares > prevShares ?
totalShares.add(shares - prevShares) :
totalShares.sub(prevShares - shares);
totalShares = _totalShares;
recipient.shares = shares;
emit EditRecipient(account, shares, _totalShares);
}
// Prevents a contract from calling itself, directly or indirectly.
bool internal _notEntered = true;
modifier nonReentrant() {
require(_notEntered, "Distributor: REENTERED");
_notEntered = false;
_;
_notEntered = true;
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
pragma solidity =0.6.6;
import "./Distributor.sol";
contract OwnedDistributor is Distributor {
address public admin;
event SetAdmin(address newAdmin);
constructor (
address imx_,
address claimable_,
address admin_
) public Distributor(imx_, claimable_) {
admin = admin_;
}
function editRecipient(address account, uint shares) public virtual {
require(msg.sender == admin, "OwnedDistributor: UNAUTHORIZED");
editRecipientInternal(account, shares);
}
function setAdmin(address admin_) public virtual {
require(msg.sender == admin, "OwnedDistributor: UNAUTHORIZED");
admin = admin_;
emit SetAdmin(admin_);
}
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
pragma solidity =0.6.6;
interface IClaimable {
function claim() external returns (uint amount);
event Claim(address indexed account, uint amount);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
pragma solidity =0.6.6;
//IERC20?
interface IImx {
function balanceOf(address account) external view returns (uint);
function transfer(address dst, uint rawAmount) external returns (bool);
} <i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>
pragma solidity =0.6.6;
// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol
// Subject to the MIT license.
/**
* @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 addition of two unsigned integers, reverting with custom message on overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot underflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction underflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot underflow.
*/
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 multiplication of two unsigned integers, reverting on overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b, string memory errorMessage) 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, errorMessage);
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) {
// Solidity only automatically asserts when dividing by 0
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;
}
}