Yes. This should be no problem to implement this, as erc-20 tokens can be owned by smart contracts as well as external accounts. In general, there's no restriction on which accounts can own a token. You can use the code below as a reference: pragma solidity 0.4.25; // Import OpenZeppelin's ERC20 interface defenition import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; // Simple ERC20 token that mints the given initialSupply to the deployer // For testing purposes contract MyToken is ERC20 { string public name = "MyToken"; string public symbol = "MYT"; uint256 public decimals = 18; constructor(uint256 _intialSupply) public { _mint(msg.sender, _intialSupply); } } // Contract that uses any ERC20 token contract UsingERC20 { IERC20 public associatedToken; // Constructor. Pass it the token you want this contract to work with constructor(IERC20 _token) public { associatedToken = _token; } function doSomethingThatRequiresERC20tokens() public { // The key here is to use ERC20's transferFrom method. // For this to work, the given address has to have enough balance, // and it has to allow this contract to transfer tokens from their account. // This can be done using ERC20's approve method/ // If transferFrom fails, the transaction reverts. So if the transaction // does not revert, we know that the transer succeeded. // Using msg.sender here, the caller of this function. // Could be any address you like, though. // This transfers 100 tokens from msg.sender to this contract. associatedToken.transferFrom(msg.sender, address(this), 100); // Ok, now the tokens are transferred successfully, let's do some cool stuff! emit YayIReceivedTokens(100, msg.sender, associatedToken.balanceOf(address(this))); } event YayIReceivedTokens(uint256 amount, address fromAccount, uint256 totalBalance); }