how to read token sale smart contracts

how to read token sale smart contracts

@crypto_eli5

code is the law in ethereum network. not everyone can code, but reading the code is not as scary as it seems. there are a few things you can learn by reading a smart contract. i'll walk you through request.network token sale contract code.

first, obtain the code from etherscan.io, open the contract source tab and grab the contract source code.

skip the standard library parts as they are always the same old crutches implementing standard token interface or even math. yup, ethereum can't do math properly and you need additional checks for overflows.

the function you are looking for has no name, it's simply function (), which is invoked when someone sends ether to this address without calling a specific function. it is often called the default or fallback function.

// fallback function can be used to buy tokens
function () 
    payable 
{
    buyTokens();
}

okay, nothing to see here. let's find function buyTokens()

// low level token purchase function
// Request Modification : change to not mint but transfer from this contract
function buyTokens() 
    public 
    payable 
{
    require(validPurchase());
​
    uint256 weiAmount = msg.value;
​
    // calculate token amount to be created
    uint256 tokens = weiAmount.mul(rate);
​
    // update state
    weiRaised = weiRaised.add(weiAmount);
​
    require(token.transfer(msg.sender, tokens)); // Request Modification : changed here - tranfer instead of mintable
    TokenPurchase(msg.sender, weiAmount, tokens);
​
    forwardFunds();
}

require will cancel the transaction and burn all provided gas if the inner clause is false, let's find function validPurchase()

function validPurchase() 
    internal 
    returns(bool)
{
    require(tx.gasprice <= GAS_LIMIT_IN_WEI);
    uint ethCapPerAddress = getCurrentEthCapPerAddress();
    participated[msg.sender] = participated[msg.sender].add(msg.value);
    return super.validPurchase() && participated[msg.sender] <= ethCapPerAddress;
}

here we can see another requirement which limits the maximum gas price. constant GAS_LIMIT_IN_WEI value can be looked up here:

uint public constant GAS_LIMIT_IN_WEI = 50000000000 wei; // limit gas price -50 Gwei wales stopper

this basically tells us that no transaction with the gas price exceeding 50 gwei can pass. not sure if the project has anything against wales though.

the function also calls super.validPurchase(), a namesake function in the parent contract.

function validPurchase() 
    internal 
    returns(bool) 
{
    bool withinPeriod = now >= startTime && now <= endTime;
    bool nonZeroPurchase = msg.value != 0;
    return withinPeriod && nonZeroPurchase;
}

this function ensures that we are within the sale time window and that at least some ether was sent along with transaction. if you try to look up startTime, you'll end up with nothing as it's not a constant, but a variable that is set when the contract is deployed. note that the function where it's set called exactly as the contract (RequestTokenSale). such function is called a constructor function.

you can look up the contract state on etherscan on read smart contract tab.

startTime 1507878000
endTime   1508223600

if you see a number ~1.5 billion it's almost certainly a date-time written as unix time (sometimes called epoch time, a number of seconds passed from midnight january 1st, 1970). unix time is always in utc, so don't forget to convert to your local timezone.

startTime 2017-10-13 07:00:00 UTC
endTime   2017-10-17 07:00:00 UTC

sometimes a sale is limited by block numbers and not by time. here's an example from another crowdsale.

presaleStartBlock          4241483
presaleUnlimitedStartBlock 4245055
crowdsaleStartBlock        4248627
crowdsaleEndedBlock        4348635

this way you can check for exact requirements even if the details are not provided publicly in full. for example tezos crowdsale was limited by block number and due to unpredictable nature of block times started 45 minutes early.

so, to wrap up:

  • unwind the function () to see the buying flow and participation requirements
  • look for constants in ALL_CAPS and find where they are used. you can get a deeper understanding of token distribution mechanics, vesting periods and the exact exchange rates.
  • look for contract state in read smart contract tab on etherscan

subscribe to @crypto_eli5