You can either issue two tokens right off the bat, or you can do a check after the person votes to see if they have any left, and if not, issue Token B. This is some pseudocode for how you would do it the latter way (the way you wanted).
contract tokenA { function transfer(address receiver, uint amount){ } }
contract tokenB { function transfer(address receiver, uint amount){ } }
contract Crowdsale {
tokenA public tokenRewardA;
tokenB public tokenRewardB;
mapping(address => uint256) balancesA;
mapping(address => uint256) balancesB;
function Crowdsale(address _addressOfTokenA, address _addressOfTokenB) {
tokenRewardA = tokenA(_addressOfTokenA);
tokenRewardB = tokenB(_addressOfTokenB);
}
function () payable {
uint amount = msg.value;
uint tokensA = // do some calculations for amount of tokensA
tokenRewardA.transfer(msg.sender, tokensA);
balancesA[msg.sender] += tokensA;
}
function vote(uint256 _amount) {
// calculate the vote for tokens A
// and decrement their vote amount
// do that part however ylike.
// then check the balanceA amount
if (balancesA[msg.sender] == 0) {
// decide how many tokenB to give them
uint tokensB = //calculations;
tokenRewardB.transfer(msg.sender, tokensB);
balancesB[msg.sender] += tokensB;
// now set a variable somewhere to indicate
// this user has claimed their tokensB already
}
}
}
You could also add checks to the default payable function so that once they've bought some A, used them, and now have B, they are not able to buy A anymore. Keep another mapping of address => bool
to see if they've already gone through the process, and update it in vote()
.
If you want instead to do it for the total votes/tokenA, and not a single users, then just keep a running tally. Say you know there are 1,000,000 tokens. Every time tokens sell, just += uint256 tokensSold
with the amount. Every time tokens are used to vote, += uint256 tokensVotedWith
. That way you know how many tokens have been used without querying a gigantic amount of wallets.
Create a bool issuingTokenB
and set it to true when you're ready to globally issue them (ie, when tokenVotedWith
is at whatever number you decide). Check in the default function () payable
to see if (issuingTokenB && msg.value == 0)
, in which case a 0 eth transaction has been sent from someone. Then give them their tokenB.
This doesn't account for many things, like a user sending tokens to someone else, as now they have less but obviously your balances here on the Crowdfund wouldn't update, just the TokenA or TokenB contract. This is just a skeleton. You could make calls to the balances mapping and balanceOf function on the token contracts themselves instead of keeping two running totals.