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 { ...@@ -5,7 +5,7 @@ contract Distillery {
address owner; address owner;
struct Allowances { struct Allowances {
address beneficiary; address beneficiary;
uint256 value; uint topuplimit;
} }
Allowances[] thelist; Allowances[] thelist;
// We use distpos to remember where we were stopped processing last time // We use distpos to remember where we were stopped processing last time
...@@ -16,7 +16,11 @@ contract Distillery { ...@@ -16,7 +16,11 @@ contract Distillery {
// that some would have first priority in getting ether at every invocation // 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 // So we continue checking the list from the same place where we left off
// at the previous invocation of distribute() // 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 { constructor() public payable {
owner = msg.sender; owner = msg.sender;
...@@ -26,83 +30,107 @@ contract Distillery { ...@@ -26,83 +30,107 @@ contract Distillery {
_; _;
} }
// Using this function, you can find out how long thelist is. // 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; return thelist.length;
} }
// Using this function, you get the address and "value" at a given position in thelist. // Using this function, you get the address and topuplimit at a given position in thelist.
function atPosition( uint256 idx ) public view returns (address,uint256) { function atPosition( uint idx ) public view returns ( address, uint ) {
require( idx <= thelist.length, "There are not that many addresses in the list." ); 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. // Returns a position +1 of where an address can be found in thelist.
// Or returns -1 if the address is not found in thelist. // Or returns 0 if the address is not found in thelist.
function _beneficiaryPosition( address beneficiary ) internal view returns (int256) { // 0 : not found
uint256 pos = thelist.length & 0x7fffffffffffffffffffffffffffffff; // 1 : first position
function _beneficiaryPosition( address beneficiary ) internal view returns ( uint ) {
uint pos = thelist.length;
while ( pos-- > 0 ) while ( pos-- > 0 )
if ( beneficiary == thelist[pos].beneficiary ) if ( beneficiary == thelist[pos].beneficiary )
return int256( pos & 0x7fffffffffffffffffffffffffffffff ); return pos+1;
return -1; return 0;
} }
// This function returns the "allowance" that a given address is set to. // This function returns the "allowance" that a given address is set to.
// Using this function, you don't have to cycle through atPosition() until // Using this function, you don't have to cycle through atPosition() until
// you find the address you want to know about. // you find the address you want to know about.
function getEtherAllowance( address beneficiary ) public view returns (uint256) { function getEtherAllowance( address beneficiary ) public view returns (uint256) {
int256 pos = _beneficiaryPosition( beneficiary ); uint pos = _beneficiaryPosition( beneficiary );
if ( pos == -1 ) if ( pos == 0 )
return 0; return 0;
return thelist[uint256(pos)].value; return thelist[pos-1].topuplimit;
} }
// This admin (ownerOnly) function allows the creator of the contract to // This admin (ownerOnly) function allows the creator of the contract to
// add/change/delete "allowances" per address. // add/change/delete "allowances" per address.
function setEtherAllowance( address beneficiary, uint256 value ) public onlyOwner { function setEtherAllowance( address beneficiary, uint256 topuplimit ) public onlyOwner {
int256 pos = _beneficiaryPosition( beneficiary ); uint pos = _beneficiaryPosition( beneficiary );
if ( value > 0 ) { // Not found and trying to delete beneficiary? Just return immediately.
if ( pos == -1 ) if ( pos == 0 && topuplimit == 0 )
// Add the address to thelist if it was not already there return;
thelist.push( Allowances(beneficiary, value) ); emit setAllowance( beneficiary, topuplimit );
else // not found
// Simple update the value of this address if ( pos == 0 )
thelist[uint256(pos)].value = value; {
if ( topuplimit > 0 )
// Add the address to thelist because it was not already there
thelist.push( Allowances(beneficiary,topuplimit) );
return; 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 { function selfDestruct() public onlyOwner {
selfdestruct( owner ); selfdestruct( owner );
} }
function mayDistribute() public view returns ( bool )
{
return msg.sender == owner;
}
function distribute() external { 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 // Is there anything to do at all
uint listlength = thelist.length;
if ( listlength == 0 ) if ( listlength == 0 )
return; return;
// Has the list gotten shorter since we we were last time? // 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. // This shouldn't happen, but it's better to be safe than to be sorry.
if ( distpos >= listlength ) if ( distpos >= listlength )
distpos = 0; distpos = 0;
uint256 wheretostop = distpos; uint wheretostop = distpos;
while ( gasleft() > 54321 ) { while ( gasleft() > 54321 ) {
// Did we get to the end of the list, then start over // Did we get to the end of the list, then start over
if ( ++distpos >= listlength ) if ( ++distpos >= listlength )
distpos = 0; distpos = 0;
uint256 balance = thelist[distpos].beneficiary.balance; uint blockchainbalance = thelist[distpos].beneficiary.balance;
uint256 value = thelist[distpos].value; uint topuplimit = thelist[distpos].topuplimit;
if ( balance < value && (value+diff) > 0 ) 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 // we use send() instead of transfer(), because
// transfer() can throw(), and we don't want // transfer() can throw(), and we don't want
// to stop processing because of a single error. // 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; thelist[distpos].beneficiary.send( diff ) || true;
} }
if ( wheretostop == distpos ) 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