Found the best way is to make the receiver pay for the transaction. Followed Steve Marx in this article to arrive the following code. The flow of the code will be like below.
- Users update their preferred wallet address on the app
- Users ensure they have ETH for gas and the wallet address loaded in metamask
- On the server side, calculating how many tokens they are supposed to receive, and then signs the transaction
node server code
const recipient = receipientaddress;
const amount = web3.toWei(tokensToSend);
const nonce = req.body.nonce; //calucated nonce of the wallet address (of metamask)
const tmpContractAddress = "0x...";//contract address that will send the token (address of the deployed contract below)
var hash = "0x" + ethereumjs.soliditySHA3(
["address", "uint256", "uint256", "address"],
[recipient,amount, nonce, tmpContractAddress]
).toString("hex");
var signed = web3.personal.sign(hash, senderAddr, senderAddrPass);
smart contract code
pragma solidity ^0.4.20;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred (address indexed _from, address indexed _to);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public{
owner = msg.sender;
emit OwnershipTransferred(address(0), owner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
owner = newOwner;
emit OwnershipTransferred(owner,newOwner);
}
}
/**
* @title Token
* @dev API interface for interacting with the Token contract
*/
interface Token {
function transfer(address _to, uint256 _value) external returns (bool);
function balanceOf(address _owner) constant external returns (uint256 balance);
}
contract RetnWithdraw10 is Ownable{
address owner;
Token token;
mapping(address => mapping(uint256 => bool)) usedNonces;
event Redeemed(address indexed beneficiary, uint256 value);
function RetnWithdraw10() public {
address _tokenAddr = 0x815CfC2701C1d072F2fb7E8bDBe692dEEefFfe41;//0x2ADd07C4d319a1211Ed6362D8D0fBE5EF56b65F6;
// test token 0x815CfC2701C1d072F2fb7E8bDBe692dEEefFfe41;
token = Token(_tokenAddr);
owner = msg.sender;
}
function claimPayment(uint256 amount, uint256 nonce, bytes sig) public {
require (token.balanceOf(this) >= amount);
require (!usedNonces[msg.sender][nonce]);
// This recreates the message that was signed on the client.
bytes32 message = prefixed(keccak256(msg.sender, amount, nonce, this));
require (recoverSigner(message, sig) == owner);
usedNonces[msg.sender][nonce] = true;
//msg.sender.transfer(amount);
if(token.transfer(msg.sender,amount)){
emit Redeemed(msg.sender,amount);
}
else
usedNonces[msg.sender][nonce] = false;
}
// Destroy contract and reclaim leftover funds.
function kill() public onlyOwner{
uint256 remaining = token.balanceOf(this);
if(remaining>0)
token.transfer(owner,remaining);
selfdestruct(msg.sender);
}
// Signature methods
function splitSignature(bytes sig)
internal
pure
returns (uint8, bytes32, bytes32)
{
require(sig.length == 65);
bytes32 r;
bytes32 s;
uint8 v;
assembly {
// first 32 bytes, after the length prefix
r := mload(add(sig, 32))
// second 32 bytes
s := mload(add(sig, 64))
// final byte (first byte of the next 32 bytes)
v := byte(0, mload(add(sig, 96)))
}
return (v, r, s);
}
function recoverSigner(bytes32 message, bytes sig)
internal
pure
returns (address)
{
uint8 v;
bytes32 r;
bytes32 s;
(v, r, s) = splitSignature(sig);
return ecrecover(message, v, r, s);
}
// Builds a prefixed hash to mimic the behavior of eth_sign.
function prefixed(bytes32 hash) internal pure returns (bytes32) {
return keccak256("\x19Ethereum Signed Message:\n32", hash);
}
}
and finall at html (front-end) side
tokensToRedeem = 2; //should be same as what is passed to the server
var abi = [ { "constant": false, "inputs": [ { "name": "amount", "type": "uint256" }, { "name": "nonce", "type": "uint256" }, { "name": "sig", "type": "bytes" } ], "name": "claimPayment", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" } ];
var MyContract = web3.eth.contract(abi);
var contrctAddress = "0x...";//deployed contract address
var myContractInstance = MyContract.at(contrctAddress);
web3.eth.getAccounts(function(error, result) {
if(!error)
{
if(result.length == 0)
{
toastr.error('Please ensure you logged in metamask.');
return false;
}
myContractInstance.claimPayment(web3.toWei(tokensToRedeem),2,hash,{ from:result[0],
to:contrctAddress,
value: 0,
}, function(err, transactionHash) {
if (!err)
{
$('#btnMetaMask').css('display','none');
$('#notesMeta').html("Transaction Submitted. Track <a target='_blank' href='<?php echo $etherscanurl;?>/tx/"+transactionHash +"'>here</a>");
console.log(transactionHash);
}
else
{
console.log('Error While Redeem');
console.log(error);
};
})
}
else
{ console.log('error');
console.log(err);
}
});
Best Answer
Once you have distributed tokens out through an ICO, you would then write code in your application that requires said tokens. What the tokens are traded for is entirely up to you and dependent on the parameters of the application you are building.
The contract code for the token you create will include a sendCoin() function of some kind that sends tokens between Ethereum addresses. So in the code you would specify an address for collecting tokens in the game and users would then send tokens to that address in a transaction on the Ethereum chain. Sending the tokens will require an up to date Ethereum node (to access the token contract code and send a transaction), so users in your game would have to have a local updated node on their system, or maybe you could just have a remote node up and running that they connect to centrally (if you don't care about have decentralization in your game).
Here's probably the real catch that there's no easy solution already figured out--until that transaction including the sent tokens is processed there is no way to tell that they have sent you tokens (at least by scanning the blockchain). Each new block takes about 13 seconds to mine, so thats the bare minimum time the user will have to wait to collect whatever they are buying. You could just log their purchases and check their balances (no wait time) and then give them the item before the transaction is mined. There's a lot of ways to about doing this, and they can't all be covered in one question.
I will say lastly that make sure the game you are building is decentralized in some way, otherwise there is no point in using tokens built on Ethereum.
EDIT: Forgot to mention, sending tokens to another Ethereum address will require some amount of ether in the sending account (however much the gas cost of the sendCoin() function is). So if they are running a local Ethereum node they would need some ether in their account.