Here is an example of how you can achieve this:
IERC20 public daiInstance;
uint256 public totalSupply;
mapping(address => uint256) public balances;
constructor(IERC20 _daiInstance) public {
daiInstance = _daiInstance;
}
function buyXXX(uint256 daiAmount) external {
uint256 xxxAmount = toXXX(daiAmount);
bool success = daiInstance.transferFrom(msg.sender, address(this), daiAmount);
require(success, "buy failed");
totalSupply = totalSupply.add(xxxAmount);
balances[msg.sender] = balances[msg.sender].add(xxxAmount);
}
function sellXXX(uint256 xxxAmount) external {
uint256 daiAmount = toDAI(xxxAmount);
totalSupply = totalSupply.sub(xxxAmount);
balances[msg.sender] = balances[msg.sender].sub(xxxAmount);
bool success = daiInstance.transfer(msg.sender, daiAmount);
require(success, "sell failed");
}
function toXXX(uint256 daiAmount) internal view returns (uint256) {
// do some logic here
}
function toDAI(uint256 xxxAmount) internal view returns (uint256) {
// do some logic here
}
Before calling your buyXXX
function, your users will need to call the approve
function on the DAI contract, passing to it your contract address as the custodian (i.e., the one being approved).
Of course, since you use address(this)
as the destination to transfer the user's DAI tokens to, those tokens will be transferred to your contract. And since you don't have a private key for it, you'll need to implement an internal mechanism (function) which will allow you to extract those tokens. Alternatively, instead of address(this)
, you can add to your contract a state-variable of address
type, which you will be able pre-configure somewhere in your contract (for example, in the constructor).
approve
function on the DAI contract, passing to it your contract address as the custodian (i.e., the one being approved). They should do so before they call your contract'sbuy
function, which will first call thetransferFrom
function on the DAI contract, passing to itmsg.sender
as the address to transfer DAI tokens from,address(this)
as the address to transfer DAI tokens to, and the desired amount (which you would need to calculate, I suppose based on the amount that your user wants to buy (which the user will also need to pass to yourbuy
function)). – goodvibration Jan 12 '20 at 18:42address(this)
as the address to transfer DAI tokens to, then it means that the tokens will be transferred to your contract, and since you don't have a private key for it, you'll need to implement an internal mechanism (function) which will allow you to extract those tokens. Alternatively, instead ofaddress(this)
you can you some state-variable ofaddress
type, which you can preconfigure somewhere in your contract (for example, in the constructor). – goodvibration Jan 12 '20 at 19:29