Skip to main content

On Alice’s continuing mission to monetise her blog through Ether donations, she realises that her previous solution could be improved by making it more generic and flexible. She decides to create a Dapp to produce an embeddable button generated from a smart contract with an administrative UI. Taking this approach, she can build a solution usable by others who share her needs.

Before starting on her new design, she reflects on the problems with her existing work.

Her last contract contained hardcoded account values and logic. If she wanted to add, remove or amend a payee she would need to build a new contract and amend any existing HTML buttons manually.

Every time Ether was sent to the contract it would split and forward funds. This means Bob the benefactor would have to pay additional gas fees to cover two additional transactions when making a donation. This may not be so expensive with just two participants, but if there were many additional payees in the contract, it would be very inefficient. She resolves instead to keep a track of how much each participant should receive and allow them to withdraw whenever they wish. This means gas fees are borne by the payee on demand and multiple transaction fees are not incurred every time someone makes a donation.

Alice's sketch of intended behavior.

Diagram of Dapp behaviour

 

We will begin by explaining some of the features of Solidity and then show the full code with comments

Struct

We create a structured object to represent a payee in our system. Solidity does not support deleting items from arrays so we add a boolean property of “status” to mark a participant active. We also create a mapping (associative array) to act as an index of payee addresses and keep count of the total number of items to help us iterate in a loop.


struct Payee {
    bool status;
    uint weight;
    uint balance;
  }

  mapping(address => Payee) public payees;
  mapping (int8 => address) public payeesIndex;
  int8 public payeesIndexSize;

Constructor

When the contract is instantiated we can pass in or set default values in much the same way as other OO languages. Property types passed to the constructor must be of fixed size. For example, if we pass an array of strings, the array length and byte size of array elements must be consistent. In our case, we only capture the account which deployed the contract (which is available implicitly).

owner = msg.sender  

Event Log

We use the event log to communicate with our Dapp. Events are fired when a transaction is first processed and are available in the transaction receipt. By setting an index we can easily watch for actions involving those addresses in our front end code. The event log offers a mechanism of storage which is cheaper than persisting other kinds or arbitrary data on the blockchain.

We define our Event log message with 

event NewDonation(address indexed donator, uint amt);

Then we can call it in a function with NewDonation(msg.sender, msg.value);

Modifiers

Modifiers allow us to restrict access to methods by adding the name of a modifier to the declaration. For example, we can check if the account calling a method is the owner of the contract, or check for a specific contract state. The code for the function being modified is inserted where the _  is placed in the modifier. The payable modifier must be used on any function which accepts or sends Ether.



  modifier isOwner() {
    if (msg.sender != owner) throw;
    _;
  }

Getters

All public variables have a getter method which is created automatically with the same name as a variable. In the code, we explicitly define some getters to make our lives easier when accessing structs inside a mapping.


  function getBalance(address _address) isPayee returns (uint) {
    return payees[_address].balance;
  }

Putting it all together in Donation.sol

Test Code

We then use Truffle suite to run our tests in the same way as tutorial part 3.

The test results should yield:
 

Test results for donation smart contract

And the test code itself:

Want to work with us?

Want to start something?

Fantastic! We'd love to hear from you, whethere it's a pitch, an idea or just saying hello!

Feel free to get in touch.

 

Drop us an email?

info@citywebconsultants.co.uk

 

Or give us a call?

+44 (0) 191 906 7746

 

Playing hard to get? We'll contact you