The following is a simple example of withdrawing an ERC20 from a contract.
You should have Access Control so that only a privileged address could withdraw.
The following code has not been tested nor audited, so please don’t use in production.
SimpleToken.sol
// contracts/SimpleToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.2;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/**
* @title SimpleToken
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
* Note they can later distribute these tokens as they wish using `transfer` and other
* `ERC20` functions.
* Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.1/contracts/examples/SimpleToken.sol
*/
contract SimpleToken is ERC20 {
/**
* @dev Constructor that gives msg.sender all of existing tokens.
*/
constructor(
string memory name,
string memory symbol,
uint256 initialSupply
) public ERC20(name, symbol) {
_mint(msg.sender, initialSupply);
}
}
MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/GSN/Context.sol";
contract MyContract is Context, AccessControl {
using SafeERC20 for IERC20;
bytes32 public constant WITHDRAWER_ROLE = keccak256("WITHDRAWER_ROLE");
constructor() public {
_setupRole(WITHDRAWER_ROLE, _msgSender());
}
function withdraw(IERC20 token, address recipient, uint256 amount) public {
require(hasRole(WITHDRAWER_ROLE, _msgSender()), "MyContract: must have withdrawer role to withdraw");
token.safeTransfer(recipient, amount);
}
}
Interact
- Create a SimpleToken and MyContract.
- Transfer amount of SimpleTokens to MyContract
- Check balance of SimpleTokens in MyContract
- Withdraw tokens from MyContract
- Check balances
$ npx truffle develop
Truffle Develop started at http://127.0.0.1:9545/
...
truffle(develop)> token = await SimpleToken.new("Simple Token", "SIM", "100000000000000000000")
undefined
truffle(develop)> myContract = await MyContract.new()
undefined
truffle(develop)> await token.transfer(myContract.address, "100000000000000000000")
{ tx:
...
truffle(develop)> (await token.balanceOf(myContract.address)).toString()
'100000000000000000000'
truffle(develop)> await myContract.withdraw(token.address, accounts[1], "100000000000000000")
{ tx:
...
truffle(develop)> (await token.balanceOf(accounts[1])).toString()
As an aside, to use an ERC20 in a contract, please see: Example on how to use ERC20 token in another contract