2


I have a smart contract called "PlayerContract" and a smart contract which implements ERC20 called "MyToken".

in PlayerContract I have a method that accepts an uint256 (represent an amount of MyToken) from users and when we reach a known condition one user win the sum of tokens.

example :

function play (uint256 tokens) public {

   // store values for each participant.

  if (condition) {
   //transfer token to winers from loosers
  }
}

My question is how can "PlayerContract" transfer token from one to onther and what is the best way to do that?

2 Answers 2

2

You need to interface playerContract with MyToken.

contract MyToken{

    ...

}

contract playerContract{


    function play (uint256 tokens) public {
        // store values for each participant.
        if (condition) {
            MyToekn instance = MyToken('address of Mytoken');
            instance.transfer('winner address', ntokens); 
        }
    }


}

The idea is that the players are sending tokens to playerContract Address. For the contract to be able to transfer these tokens to the winner it needs to use the function transfer in MyToken, so you define an instance to the contact and now playerContract can use the transfer function.

Hope this helps

EDIT: using a single transaction.

This can be achieved with approveAndCall. The ERC20 contract must have implemented it and something like this is in the standard:

contract ApproveAndCallFallBack {
    function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}

In you contract the function receive approval must be implemented. You will be getting the information of who is sending the tokens, how much, from which token contract and to whom, you also get a variable data in case you need them to pass data, but this is not the case.

contract MyToken{

...

}

contract playerContract{


function play (uint256 tokens, address from) internal {
    // store values for each participant.
    if (condition) {
        MyToekn instance = MyToken('address of Mytoken');
        instance.transfer('winner address', ntokens); 
    }
}


function receiveApproval(address from, uint256 tokens, address token, bytes data) public{
     require(token=='your token address');
     delete data;
     MyToekn instance = MyToken(token);
     instance.transferFrom(from,address(this), tokens)
     play(tokens, from); 
}

}

The require(token=='your token address'); is there because people may try to pay you with a token different than yours.

Hope this helps.

Note: do not forget that if you have some profit in tokens these will be linked to the contract and you will need to implement a function to move then like in the play function.

6
  • this it can works, but the user here has to make two transactions: the first one is to send token to contract address, and the second to send the uint256 number to the playerContract. I need a solution with a single transaction
    – maroodb
    Jun 19, 2018 at 8:53
  • Using the standard ERC20 you only have one option, using approveAndCall. In this way the subjects call the ERC20 contract and approve you the number of tokens, then the ERC20 calls your contract function and you can move the tokens to your contract at the same time you get to store the number of tokens of each subject. This implies that you included approveAndCall in your token design. Let me know if this solves your problem.
    – Jaime
    Jun 19, 2018 at 9:44
  • Sure. I edited the answer to include the solution with approveAndCall. Let me know how it goes.
    – Jaime
    Jun 19, 2018 at 10:17
  • thanks ! it is very helpful! just one more question :p in ""receiveApproval(address from, uint256 tokens, address token, bytes data)"" the data has to be bytes or I can pass any type of data (for example uint) ?
    – maroodb
    Jun 19, 2018 at 10:27
  • receiveApproval is defined like that in the ERC20 standard, you can change this in your token but then if someone else tries to use your token for other applications it won't work. Also if you need to pass an uint variable you can convert the uint to bytes and then in your contract you can convert it back to uint. Look at this answer for the conversion
    – Jaime
    Jun 19, 2018 at 12:16
2
import MyToken from './MyToken.sol'

In your function

MyToken(_tokenAddress).transfer(_to, _amount)

So either you have to pass in _tokenAddress as an argument to play(), or set it in a constructor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.