How to do it...

  1. Loops can be very tricky when it comes to solidty. There are two very common mistakes that anyone can easily overlook while writing smart contracts.
  2. Create a function that uses a for loop to iterate through an array of addresses and transfer the payout:
pragma solidity ^0.4.24;

contract Payout {
// Arbitrary length array to store addresses
address[] private addresses;

// Mapping to store payout value
mapping (address => uint) public payouts;

// Function to transfer payouts
function payoutAll() public {
for(uint8 i = 0; i < addresses.length; i++) {
require(addresses[i].send(payouts[addresses[i]]));
}
}
}
  1. The contract contains two potential bugs, which will arise when the length of the array exceeds a certain limit.
  2. For example, the for loop uses a uint with size 8 to store the index. Since uint8 can only store a very short range of integers, if the array length exceeds 255, an overflow can occur. This will result start transferring payout starting from index 0.
  3. To avoid this, it is recommended to always use a data type that can accommodate the loop's needs. The function can be modified as follows to avoid this issue:
function payoutAll() public {
for(uint256 i = 0; i < addresses.length; i++) {
require(addresses[i].send(payouts[addresses[i]]));
}
}
  1. Using a different data type can solve the underflow issue, but it will still fail to satisfy the block's gas limit. It will take a lot of gas if there are more instructions to execute.
  2. Since the array length is infinite, this issue can arise when the number of addresses in the array is more. This can also result in permanent DoS for the payout functionality.
  3. It is recommended to perform a large set of instructions in batches to avoid such issues. The contract can be modified as follows:
pragma solidity^0.4.24;

contract Payout {

// Using struct over mapping
struct Recipient {
address addr;
uint256 value;
}

Recipient[] recipients;

// State variable for batch operation
uint256 nextIndex;

// Function to transfer payout
function payoutAll() public {
uint256 i = nextIndex;

while (i < recipients.length && gasleft() > 200000) {
recipients[i].addr.send(recipients[i].value);
i++;
}

nextIndex = i;
}
}
  1. It is recommended to verify all conditions before proceeding with this implementation. It depends on the use case you are planning to implement it with. 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.194