Skip to content
Snippets Groups Projects
Commit 2c9436d9 authored by Robert Martin-Legene's avatar Robert Martin-Legene
Browse files

Agregando el mapping userTypeNames

parent 8158abb0
No related branches found
No related tags found
No related merge requests found
......@@ -15,7 +15,7 @@ pragma solidity >=0.4;
contract destileria2
{
enum UserType { UserNotFound, UserOwner, UserDistributor, UserBeneficiary }
enum UserType { NotFound, Owner, Distributor, Beneficiary }
// no hace falte 'indexed' ya que solamente va a haber
// un evento de este tipo
event deployed(address creator);
......@@ -40,7 +40,8 @@ contract destileria2
// Used for reclaiming unused positions in the userIndex
uint256[] public deletedEntries;
// Last time we did replenishAll, where did we stop?
uint256 allstopmarker = 0;
uint256 public allstopmarker = 0;
mapping(UserType => string) public userTypeNames;
constructor() payable
{
......@@ -61,10 +62,14 @@ contract destileria2
userIndex.push(UserEntry({
// This entry can be returned when no matches were found
addr: address(0),
userType: UserType.UserNotFound,
userType: UserType.NotFound,
topUpLimit: 0,
deleted: true
}));
userTypeNames[UserType.NotFound] = "User Not Found";
userTypeNames[UserType.Owner] = "Owner";
userTypeNames[UserType.Distributor] = "Distributor";
userTypeNames[UserType.Beneficiary] = "Beneficiary";
}
receive() external payable {}
......@@ -77,167 +82,152 @@ contract destileria2
modifier onlyDistributorOrOwner
{
require(contains(UserType.UserDistributor, msg.sender) || msg.sender == owner);
require(contains(UserType.Distributor, msg.sender) || msg.sender == owner);
_;
}
function addBeneficiary(address addr, uint256 topuplimit) public onlyDistributorOrOwner returns(bool)
function addDistributor(address addr, uint256 topuplimit) public onlyOwner
{
if (topuplimit == 0)
return false;
// User must not exist already
if (getUserType(addr) != UserType.UserNotFound)
return false;
if (topuplimit > getTopUpLimit(UserType.UserDistributor, msg.sender))
return false;
emit added(msg.sender, addr, UserType.UserBeneficiary, topuplimit);
return !insert(UserType.UserBeneficiary, addr, topuplimit);
require(topuplimit > 0, "The topuplimit must be a positive number");
require(getUserType(addr) == UserType.NotFound, "The distributor to add must not already be a listed user of any type.");
insert(UserType.Distributor, addr, topuplimit);
emit added(msg.sender, addr, UserType.Distributor, topuplimit);
}
function addDistributor(address addr, uint256 topuplimit) public onlyOwner returns(bool)
function addBeneficiary(address addr, uint256 topuplimit) public onlyDistributorOrOwner
{
if (topuplimit == 0)
return false;
// User must not exist already
if (getUserType(addr) != UserType.UserNotFound)
return false;
emit added(msg.sender, addr, UserType.UserDistributor, topuplimit);
return !insert(UserType.UserDistributor, addr, topuplimit);
require(topuplimit > 0, "topuplimit must be a positive integer.");
require(getUserType(addr) == UserType.NotFound, "The distributor to add must not already be a listed user of any type.");
insert(UserType.Beneficiary, addr, topuplimit);
emit added(msg.sender, addr, UserType.Beneficiary, topuplimit);
}
function kick(UserType victimtype, address addr) private returns(bool)
function kick(UserType victimtype, address addr) private
{
if (!contains(victimtype, addr))
return false;
require(contains(victimtype, addr), "Address unknown.");
remove(victimtype, addr);
emit kicked(msg.sender, addr);
return remove(victimtype, addr);
}
function kickDistributor(address addr) public onlyOwner returns(bool)
function kickDistributor(address addr) public onlyOwner
{
return kick(UserType.UserDistributor, addr);
kick(UserType.Distributor, addr);
}
function kickBeneficiary(address addr) public onlyDistributorOrOwner returns(bool)
function kickBeneficiary(address addr) public onlyDistributorOrOwner
{
return kick(UserType.UserBeneficiary, addr);
kick(UserType.Beneficiary, addr);
}
function changeLimit(address addr, uint256 topuplimit) public onlyDistributorOrOwner returns(bool)
function changeLimit(address addr, uint256 topuplimit) public onlyDistributorOrOwner
{
uint256 pos = addressToUserEntryIndex[addr];
if (pos == 0)
return false;
require(pos == 0, "Address unknown.");
UserEntry memory entry = userIndex[pos];
if (entry.userType != UserType.UserDistributor && entry.userType != UserType.UserBeneficiary)
return false;
require(entry.userType == UserType.Distributor || entry.userType == UserType.Beneficiary, "Only Beneficiaries and Distributors have limits associated.");
if (msg.sender != owner)
{
// Only our owner can change limits for Distributors
if (entry.userType == UserType.UserDistributor)
return false;
require(entry.userType == UserType.Distributor, "Only the contract owner can changed limits for Distriburs.");
// Distributors must obey the limit
if (topuplimit > getTopUpLimit(UserType.UserDistributor, msg.sender))
return false;
require(topuplimit > getTopUpLimit(UserType.Distributor, msg.sender), "Distributors can not set a limit to exceed its own limit.");
}
// all is fine - now we change the limit
userIndex[pos].topUpLimit = topuplimit;
emit limitChanged(msg.sender, addr, topuplimit);
return true;
}
function replenish(address victim, uint256 amount) public payable onlyDistributorOrOwner returns(bool)
function replenish(address victim, uint256 amount) public payable onlyDistributorOrOwner
{
if (getUserType(victim) != UserType.UserBeneficiary)
return false;
uint256 topuplimit = getTopUpLimit(UserType.UserBeneficiary, victim);
require(amount > 0, "The topup amount must be a positive integer.");
require(getUserType(victim) == UserType.Beneficiary, "Address is not listed as beneficiary.");
uint256 topuplimit = getTopUpLimit(UserType.Beneficiary, victim);
// Does the destination account have less than his limit?
if (victim.balance + amount > topuplimit)
return false;
require(victim.balance + amount <= topuplimit, "Desired topup will make the destination address exceed his topup limit.");
// avoid uint256 overflow
if (victim.balance + amount < victim.balance)
return false;
require(victim.balance + amount > victim.balance, "Giving that amount, will make his balance overflow.");
// Do we have enough ether to send?
if (address(this).balance < amount)
return false;
require(address(this).balance >= amount, "The contract does not have enough balance to send that amount.");
// Do the transfer and emit an event
address payable addrpayable = address(uint160(victim));
addrpayable.transfer(amount);
emit replenished(msg.sender, victim, amount);
return true;
}
// To use this function, you should set gasLimit to at least gasEstimate + 50000
function replenishList(address[] calldata accs, uint256[] calldata amounts) public payable
function replenishList(address[] calldata accs, uint256[] calldata amounts) public payable onlyDistributorOrOwner
{
require(accs.length == amounts.length);
require(accs.length == amounts.length, "The two lists given as parameters are not of the same length.");
uint256 i = 0;
while (i < accs.length && gasleft()>49999)
while (i < accs.length && gasleft() >= 32768)
{
// we don't like overflow
if (accs[i].balance + amounts[i] < accs[i].balance)
continue;
// Don't allow amounts which will make the balance go above the top up limit.
if (accs[i].balance + amounts[i] < getTopUpLimit(UserType.UserBeneficiary, accs[i]))
if (accs[i].balance + amounts[i] < getTopUpLimit(UserType.Beneficiary, accs[i]))
replenish(accs[i], amounts[i]);
i++;
}
}
// Pay to as many as possible, until we run out of ether (or run through the list
function replenishAll() public payable onlyDistributorOrOwner returns(bool)
function replenishAll() public payable onlyDistributorOrOwner
{
if (userIndex.length == 0)
return false;
require(userIndex.length > 0, "There are no users registered.");
require(address(this).balance > 0, "We need wei, in order for us to send to others. Our balance is zero.");
// The index may have shrunk under the stopmarker
if (allstopmarker >= userIndex.length)
allstopmarker = 0;
// The distributor's topuplimit (for owner this is ignored)
uint256 distlimit = getTopUpLimit(UserType.UserDistributor, msg.sender);
uint256 distlimit = getTopUpLimit(UserType.Distributor, msg.sender);
uint256 i = allstopmarker;
while (++i != allstopmarker)
// just a round number
while (gasleft()>=32768)
{
i++;
// If we get to the end of the list, loop back to the start of it
if (i >= userIndex.length)
i = 0;
UserEntry memory entry = userIndex[i];
// make sure we skip deleted entries
if (entry.deleted)
continue;
// We only handle Beneficiaries
if (entry.userType != UserType.UserBeneficiary)
continue;
//
uint256 topuplimit;
if (msg.sender == owner || entry.topUpLimit <= distlimit)
topuplimit = entry.topUpLimit;
else
topuplimit = distlimit;
// Does the user actually need to get topped up?
if (topuplimit > entry.addr.balance)
continue;
// What's the difference?
uint256 amount = topuplimit - entry.addr.balance;
replenish(entry.addr, amount);
// Do we have enough ether to send?
if (address(this).balance < amount)
continue;
// Do the transfer and emit an event
address payable addrpayable = address(uint160(entry.addr));
addrpayable.transfer(amount);
emit replenished(msg.sender, entry.addr, amount);
if (!entry.deleted && entry.userType == UserType.Beneficiary)
{
uint256 topuplimit = distlimit;
if (msg.sender == owner || entry.topUpLimit <= distlimit)
topuplimit = entry.topUpLimit;
// Fill up if he is below 75% of his topuplimit
if (entry.addr.balance/100*75 < topuplimit)
{
// What's the difference?
uint256 amount = topuplimit - entry.addr.balance;
// Do we have enough ether to send?
if (amount > address(this).balance)
amount = address(this).balance;
// Do the transfer and emit an event
address payable addrpayable = address(uint160(entry.addr));
addrpayable.transfer(amount);
emit replenished(msg.sender, entry.addr, amount);
}
}
// Only run through the list once
if ( i == allstopmarker )
break;
if (address(this).balance == 0)
break;
}
return true;
return;
}
function getDistributorLimit(address addr) public view returns(uint256)
{
return getTopUpLimit(UserType.UserDistributor, addr);
return getTopUpLimit(UserType.Distributor, addr);
}
function getBeneficiaryLimit(address addr) public view returns(uint256)
{
return getTopUpLimit(UserType.UserBeneficiary, addr);
return getTopUpLimit(UserType.Beneficiary, addr);
}
function getBeneficiariesCount() public view returns(uint256 count)
......@@ -248,64 +238,60 @@ contract destileria2
{
if (userIndex[i].deleted)
continue;
if (userIndex[i].userType == UserType.UserBeneficiary)
if (userIndex[i].userType == UserType.Beneficiary)
count++;
}
}
function getUserIndexCount() public view returns(uint256)
{
return userIndex.length;
}
function isBeneficiary(address addr) public view returns(bool)
{
return contains(UserType.UserBeneficiary, addr);
return contains(UserType.Beneficiary, addr);
}
function isDistributor(address addr) public view returns(bool)
{
return contains(UserType.UserDistributor, addr);
return contains(UserType.Distributor, addr);
}
function insert(UserType victimtype, address addr, uint256 value) private returns(bool replaced)
function insert(UserType victimtype, address addr, uint256 value) private
{
uint256 pos = addressToUserEntryIndex[addr];
if (pos > 0)
assert( userIndex[pos].addr != addr || userIndex[pos].deleted );
if (deletedEntries.length > 0)
{
assert(userIndex[pos].addr == addr);
assert(!userIndex[pos].deleted);
replaced = true;
// recycle deleted entries, if possible
pos = deletedEntries[deletedEntries.length-1];
deletedEntries.pop();
}
else
{
replaced = false;
if (deletedEntries.length > 0)
{
// recycle deleted entries, if possible
pos = deletedEntries[deletedEntries.length-1];
deletedEntries.pop();
}
else
{
pos = userIndex.length;
userIndex.push();
}
pos = userIndex.length;
userIndex.push();
}
addressToUserEntryIndex[addr] = pos;
userIndex[pos].addr = addr;
userIndex[pos].userType = victimtype;
userIndex[pos].topUpLimit = value;
userIndex[pos].deleted = false;
if (!replaced)
addressToUserEntryIndex[addr] = pos;
}
function remove(UserType victimtype, address addr) private returns(bool success)
function remove(UserType victimtype, address addr) private
{
uint256 pos = addressToUserEntryIndex[addr];
if (pos == 0)
return false;
if(victimtype != userIndex[pos].userType)
return false;
assert(pos>0);
assert(userIndex[pos].addr == addr);
assert(userIndex[pos].userType == victimtype);
assert(!userIndex[pos].deleted);
userIndex[pos].addr = address(0);
userIndex[pos].deleted = true;
delete addressToUserEntryIndex[addr];
deletedEntries.push(pos);
userIndex[pos].deleted = true;
return true;
}
function getEntry(address addr) private view returns(UserEntry memory)
......@@ -318,7 +304,7 @@ contract destileria2
function getUserType(address addr) public view returns(UserType)
{
uint256 pos = addressToUserEntryIndex[addr];
// no match will give the 0th userIndex entry which has UserNotFound as UserType
// no match will give the 0th userIndex entry which has NotFound as UserType
return userIndex[pos].userType;
}
......@@ -337,4 +323,8 @@ contract destileria2
return true;
return false;
}
function kill() public onlyOwner {
selfdestruct(msg.sender);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment