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

Updated the Distillery SC to also emit events.

parent 0b4cb2b4
No related branches found
No related tags found
No related merge requests found
......@@ -5,7 +5,7 @@ contract Distillery {
address owner;
struct Allowances {
address beneficiary;
uint256 value;
uint topuplimit;
}
Allowances[] thelist;
// We use distpos to remember where we were stopped processing last time
......@@ -16,7 +16,11 @@ contract Distillery {
// that some would have first priority in getting ether at every invocation
// So we continue checking the list from the same place where we left off
// at the previous invocation of distribute()
uint256 distpos;
uint distpos;
event distributeStartedBy( address activator );
event setAllowance( address subject, uint amount );
event xfrAllowance( address subject, uint amount );
constructor() public payable {
owner = msg.sender;
......@@ -26,83 +30,107 @@ contract Distillery {
_;
}
// Using this function, you can find out how long thelist is.
function numberOfBeneficiaries() public view returns (uint256) {
function numberOfBeneficiaries() public view returns ( uint ) {
return thelist.length;
}
// Using this function, you get the address and "value" at a given position in thelist.
function atPosition( uint256 idx ) public view returns (address,uint256) {
// Using this function, you get the address and topuplimit at a given position in thelist.
function atPosition( uint idx ) public view returns ( address, uint ) {
require( idx <= thelist.length, "There are not that many addresses in the list." );
return (thelist[idx].beneficiary,thelist[idx].value);
return (thelist[idx].beneficiary,thelist[idx].topuplimit);
}
// Returns a (signed) position of where an address can be found in thelist.
// Or returns -1 if the address is not found in thelist.
function _beneficiaryPosition( address beneficiary ) internal view returns (int256) {
uint256 pos = thelist.length & 0x7fffffffffffffffffffffffffffffff;
// Returns a position +1 of where an address can be found in thelist.
// Or returns 0 if the address is not found in thelist.
// 0 : not found
// 1 : first position
function _beneficiaryPosition( address beneficiary ) internal view returns ( uint ) {
uint pos = thelist.length;
while ( pos-- > 0 )
if ( beneficiary == thelist[pos].beneficiary )
return int256( pos & 0x7fffffffffffffffffffffffffffffff );
return -1;
return pos+1;
return 0;
}
// This function returns the "allowance" that a given address is set to.
// Using this function, you don't have to cycle through atPosition() until
// you find the address you want to know about.
function getEtherAllowance( address beneficiary ) public view returns (uint256) {
int256 pos = _beneficiaryPosition( beneficiary );
if ( pos == -1 )
uint pos = _beneficiaryPosition( beneficiary );
if ( pos == 0 )
return 0;
return thelist[uint256(pos)].value;
return thelist[pos-1].topuplimit;
}
// This admin (ownerOnly) function allows the creator of the contract to
// add/change/delete "allowances" per address.
function setEtherAllowance( address beneficiary, uint256 value ) public onlyOwner {
int256 pos = _beneficiaryPosition( beneficiary );
if ( value > 0 ) {
if ( pos == -1 )
// Add the address to thelist if it was not already there
thelist.push( Allowances(beneficiary, value) );
else
// Simple update the value of this address
thelist[uint256(pos)].value = value;
function setEtherAllowance( address beneficiary, uint256 topuplimit ) public onlyOwner {
uint pos = _beneficiaryPosition( beneficiary );
// Not found and trying to delete beneficiary? Just return immediately.
if ( pos == 0 && topuplimit == 0 )
return;
emit setAllowance( beneficiary, topuplimit );
// not found
if ( pos == 0 )
{
if ( topuplimit > 0 )
// Add the address to thelist because it was not already there
thelist.push( Allowances(beneficiary,topuplimit) );
return;
} else {
// The beneficiary is set to have 0 Ether, so we
// delete the beneficiary from the list
uint i = uint256(pos) + 1;
while ( i++ < thelist.length )
thelist[i] = thelist[i+1];
// If distpos was past the position that we removed,
// then move that back one.
if ( distpos > uint256(pos) )
distpos--;
// Shorten the list
thelist.length--;
}
// Now use a properly zero-indexed pos
pos--;
//
if ( topuplimit > 0 ) {
// Simple update the topuplimit of this address
thelist[pos].topuplimit = topuplimit;
return;
}
// The beneficiary is set to have 0 Ether, so we
// delete the beneficiary from the list
uint i = pos;
while ( i++ < thelist.length )
thelist[i-1] = thelist[i];
// Shorten the list
thelist.length--;
// If distpos was past the position that we removed,
// then move that back one.
if ( distpos >= pos )
distpos--;
}
function selfDestruct() public onlyOwner {
selfdestruct( owner );
}
function mayDistribute() public view returns ( bool )
{
return msg.sender == owner;
}
function distribute() external {
uint256 listlength = thelist.length;
require( mayDistribute(), "You are not authorized to activate the distribution functionality." );
emit distributeStartedBy( msg.sender );
// Is there anything to do at all
uint listlength = thelist.length;
if ( listlength == 0 )
return;
// Has the list gotten shorter since we we were last time?
// This shouldn't happen, but it's better to be safe than to be sorry.
if ( distpos >= listlength )
distpos = 0;
uint256 wheretostop = distpos;
distpos = 0;
uint wheretostop = distpos;
while ( gasleft() > 54321 ) {
// Did we get to the end of the list, then start over
if ( ++distpos >= listlength )
distpos = 0;
uint256 balance = thelist[distpos].beneficiary.balance;
uint256 value = thelist[distpos].value;
if ( balance < value && (value+diff) > 0 )
distpos = 0;
uint blockchainbalance = thelist[distpos].beneficiary.balance;
uint topuplimit = thelist[distpos].topuplimit;
uint diff = topuplimit - blockchainbalance;
// Don't top up anyone, if they still more than 90% of their allowance.
if ( blockchainbalance > topuplimit*9/10 )
diff = 0;
if ( diff > 0 )
{
uint256 diff = value - balance;
// we use send() instead of transfer(), because
// transfer() can throw(), and we don't want
// to stop processing because of a single error.
// -
// Use || true to avoid warnings from the compiler.
emit xfrAllowance( thelist[distpos].beneficiary, diff );
thelist[distpos].beneficiary.send( diff ) || true;
}
if ( wheretostop == distpos )
......
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