Dai Payments – Accepting Dai or Any ERC20 Token as Payment

daisolidity

I have created an ERC20 token and want to make it payable with DAI.

I read some of the related questions but did not found any proper answer.

As dai is an ERC20 token so, how can I accept any token as payment instead of ether?

function () external payable {}

this accepts only ether, right?

sorry in advance for my English and little understanding of solidity

Best Answer

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).

Related Topic