The following repo contains the implementation of the contracts needed to bootstrap DAOSprout's toke sale.
Run npm install
to install dependencies, you may need to install nodejs
and npm
.
You will need truffle
, install via npm install -g truffle@beta
.
Run truffle test
.
Edit truffle.js
according to your needs, in the next lines we will assume you want to deploy to the rinkeby_infura
network.
Choose the options you want in migrations/2_sale_deploy.js
.
Run truffle migrate --network rinkeby_infura
and wait, that's all.
The token is a standard ERC20 token, thus it implements all the required functions, with the addition of some more.
The token is mintable by its owner via the functions mint(address _to, uint256 _amount)
and finishMinting()
.
It isn't needed to deploy the token, the sale contract will take care of doing so. And become the token's owner in order to mint tokens for the buyers.
TODO: how can we allocate tokens manually?
The sale contract inherits the Crowdsale
contract from zeppelin-solidity
, it also comes with a "cap" system and a presale period.
The presale takes place before the main sale.
Buyers can buy tokens at a specific _presaleRate
rate by calling buyPresaleTokens(bytes _inviteCode)
along with the invitation code they received.
An invitation code can be generated by using the owner's wallet console and typing: web3.eth.sign(signer, target_buyer)
where:
signer
is the account's of the signer address (the signer public key is specified at deployment time).target_buyer
is the public key of the buyer invited.
At deployment time, one has to specify the _cap
parameter in wei, if the amount of wei collected reaches the cap, the sale ends.
The main sale takes place right after the presale.
Buyers have two ways of buying tokens:
- they can simply send ether to the sale contract, they will get their tokens back.
- they can use the low level function
buyTokens(address beneficiary)
.
On each purchases (provided that the order is valid, aka if the main sale is running), the number of tokens granted is minted to the buyer's address (or beneficiary), the TokenPurchase
event is fired and funds are forwarded to _wallet
.
[ { constant: true,
inputs: [],
name: 'mintingFinished',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'name',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: false,
inputs: [ [Object], [Object] ],
name: 'approve',
outputs: [ [Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ constant: true,
inputs: [],
name: 'totalSupply',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: false,
inputs: [ [Object], [Object], [Object] ],
name: 'transferFrom',
outputs: [ [Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ constant: true,
inputs: [],
name: 'decimals',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: false,
inputs: [ [Object], [Object] ],
name: 'mint',
outputs: [ [Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ constant: false,
inputs: [ [Object], [Object] ],
name: 'decreaseApproval',
outputs: [ [Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ constant: true,
inputs: [ [Object] ],
name: 'balanceOf',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: false,
inputs: [],
name: 'finishMinting',
outputs: [ [Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ constant: true,
inputs: [],
name: 'owner',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'symbol',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: false,
inputs: [ [Object], [Object] ],
name: 'transfer',
outputs: [ [Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ constant: false,
inputs: [ [Object], [Object] ],
name: 'increaseApproval',
outputs: [ [Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ constant: true,
inputs: [ [Object], [Object] ],
name: 'allowance',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: false,
inputs: [ [Object] ],
name: 'transferOwnership',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function' },
{ anonymous: false,
inputs: [ [Object], [Object] ],
name: 'Mint',
type: 'event' },
{ anonymous: false,
inputs: [],
name: 'MintFinished',
type: 'event' },
{ anonymous: false,
inputs: [ [Object], [Object] ],
name: 'OwnershipTransferred',
type: 'event' },
{ anonymous: false,
inputs: [ [Object], [Object], [Object] ],
name: 'Approval',
type: 'event' },
{ anonymous: false,
inputs: [ [Object], [Object], [Object] ],
name: 'Transfer',
type: 'event' } ]
[ { constant: false,
inputs: [ [Object] ],
name: 'buyPresaleTokens',
outputs: [],
payable: true,
stateMutability: 'payable',
type: 'function' },
{ constant: true,
inputs: [],
name: 'presaleStarts',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'rate',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'endTime',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'cap',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'weiRaised',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'presaleRate',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'wallet',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'startTime',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: false,
inputs: [ [Object] ],
name: 'buyTokens',
outputs: [],
payable: true,
stateMutability: 'payable',
type: 'function' },
{ constant: true,
inputs: [],
name: 'hasEnded',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ constant: true,
inputs: [],
name: 'token',
outputs: [ [Object] ],
payable: false,
stateMutability: 'view',
type: 'function' },
{ inputs:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
payable: false,
stateMutability: 'nonpayable',
type: 'constructor' },
{ payable: true, stateMutability: 'payable', type: 'fallback' },
{ anonymous: false,
inputs: [ [Object], [Object], [Object], [Object] ],
name: 'Log',
type: 'event' },
{ anonymous: false,
inputs: [ [Object], [Object], [Object], [Object] ],
name: 'TokenPurchase',
type: 'event' } ]
This source code has been developed and published by Eliott TEISSONNIERE for DAOSprout, it is covered by an AGPLv3
license, please see the file LICENSE
for more informations.