Escrowing ERC20 tokens:
Your escrow contract needs to know when it received new tokens, from whom, and how many.
This is achieved by having the "seller" create two transactions:
- Approval: First transaction calls token contract
// tracker_0x_address is the address of the ERC20 contract they want to deposit tokens from ( ContractA )
// spender is your deployed escrow contract address
ERC20(tracker_0x_address).approve(address spender, uint tokens)
- Deposit: Second transaction calls a method in the escrow contract
mapping ( address => uint256 ) public balances;
deposit(uint tokens) {
// add the deposited tokens into existing balance
balances[msg.sender]+= tokens;
// transfer the tokens from the sender to this contract
ERC20(tracker_0x_address).transferFrom(msg.sender, address(this), tokens);
}
This updates the sender's balance, and then transfers the tokens from sender to escrow (contractB).
Releasing escrowed tokens:
All your smart contract has to do is call the
ERC20(tracker_0x_address).transfer(msg.sender, balances[msg.sender]);
on the token tracker address in order to transfer those tokens to an address.
If you're doing multiple tokens and multiple users in one contract you're going to have to implement a second layer mapping for the balances as well as support for a tracker variable in the deposit method.
Code Example
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
pragma solidity ^0.4.17;
contract ERC20 {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
contract contractB {
address tracker_0x_address = 0xd26114cd6EE289AccF82350c8d8487fedB8A0C07; // ContractA Address
mapping ( address => uint256 ) public balances;
function deposit(uint tokens) public {
// add the deposited tokens into existing balance
balances[msg.sender]+= tokens;
// transfer the tokens from the sender to this contract
ERC20(tracker_0x_address).transferFrom(msg.sender, address(this), tokens);
}
function returnTokens() public {
uint256 amount = balances[msg.sender];
balances[msg.sender] = 0;
ERC20(tracker_0x_address).transfer(msg.sender, amount);
}
}