Smart Contract Design: Escrow/Controller-Vertrag

Wie würde ich vorgehen, um Folgendes zu erstellen:
Escrow/Controller-Vertrag A, der in der Lage ist, ERC20-Token von Vertrag B und ETH von Partei C zu akzeptieren und einen Tausch durchzuführen, wenn bestimmte Bedingungen erfüllt sind.

Derselbe Vertrag A sollte auch in der Lage sein, ERC20-Token von Vertrag D und ETH von Vertrag E zu erhalten und einen Swap durchzuführen, wenn bestimmte Bedingungen erfüllt sind.

Der Haken/die Relevanz der Frage ist , wie man Vertrag A gestaltet, um ERC20token-Eingaben verschiedener Art verarbeiten zu können, z. B. Walton(WTC) & FUSION(FSN) ERC20-Token?

Antworten (1)

Hier kommen Schnittstellen ins Spiel. Das ist großartig, denn ERC-20 ist eigentlich eine Schnittstelle! Ich gebe Ihnen unten ein Beispiel. Wie Sie sehen können, müssen die TokenSwappernicht einmal etwas über TokenAund wissen TokenB, sondern nur, dass sie die ERC20Schnittstelle implementieren.

Ach ja, und bevor Sie mit der Entwicklung beginnen, sollten Sie sich zunächst mit den Grundlagen der ERC20-Oberfläche vertraut machen. Lesen Sie dieses Wiki

pragma solidity ^0.4.23;

/* Declaring the ERC20 interface. This tells
   other contracts how to handle ERC-20 tokens */
interface ERC20 {
    function allowance(address owner, address spender)
    external view returns (uint256);

    function transferFrom(address from, address to, uint256 value)
    external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);

    function totalSupply() external view returns (uint256);
    function balanceOf(address who) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
}


/* a simple base ERC token contract for testing */
/* DO NOT USE FOR PRODUCTION AS IT IS NOT SAFE */
contract ERC20Token is ERC20 {
    uint256 totalSupply_;

    mapping (address => mapping (address => uint256)) internal allowed;
    mapping(address => uint256) balances;

    function totalSupply() public view returns (uint256) {
        return totalSupply_;
    }

    function transfer(address _to, uint256 _value) external returns (bool) {
        require(_to != address(0));
        require(_value <= balances[msg.sender]);


        balances[msg.sender] -= _value;
        balances[_to] += _value;

        return true;
    }

    function balanceOf(address _owner) public view returns (uint256) {
        return balances[_owner];
    }

      function transferFrom(
        address _from,
        address _to,
        uint256 _value
    )
        public
        returns (bool)
    {
        require(_to != address(0));
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);

        balances[_from] -= _value;
        balances[_to] += _value;
        allowed[_from][msg.sender] -= _value;

        return true;
    }

    function approve(address _spender, uint256 _value) public returns (bool) {
        allowed[msg.sender][_spender] = _value;
        return true;
    }

    function allowance(
        address _owner,
        address _spender
    )
    public
    view
    returns (uint256)
    {
        return allowed[_owner][_spender];
    }
}

/* The tokens inherit their functionality from ERC20Token */
contract TokenA is ERC20Token {
}

contract TokenB is ERC20Token {
}

contract TokenC is ERC20Token {
}
contract TokenD is ERC20Token {
}

/* DO NOT USE IN PRODUCTION AS IT DOESN'T CHECK FOR UNDERFLOW/OVERFLOW */
contract TokenSwapper {
    // Keeps track of the tokens users have
    mapping(address => mapping(address => uint256)) tokenBalances_;

    function tokenBalances(address _owner, ERC20 _token) public view returns (uint256 balance) {
        return balance = tokenBalances_[_owner][_token];
    }

    function deposit(ERC20 _token, uint256 _amount) public {
        _token.transferFrom(msg.sender, address(this), _amount);
        tokenBalances_[msg.sender][_token] += _amount;
    }

    function swap(ERC20 _fromToken, ERC20 _toToken, uint256 _amount) public {
        tokenBalances_[msg.sender][_fromToken] -= _amount;
        tokenBalances_[msg.sender][_toToken] += _amount;
    }

    function withdraw(ERC20 _token, uint256 _amount) public {
        require(tokenBalances_[msg.sender][_token] >= _amount);

        _token.transfer(msg.sender, _amount);
    }
}
Henk, also kann 'TokenSwapper' jede Art von erc20token in TokenBalances halten, zusammen mit der angegebenen Adresse? Muss nicht wie beim Crowd Sales zunächst ein Objekt aus der Oberfläche generiert werden? zB ERC20 öffentlicher Token; Danke für die Antwort, Schnittstellen stören mich seit einiger Zeit. Ist es nicht möglich, ERC20 anstelle von transferFrom zu übertragen?
Ja das ist richtig. Die Verwendung transferist nicht sicher, da der Smart Contract nicht erkennen kann, wann er Token erhalten hat
Vielleicht ist das eine dumme Frage, aber was wäre, wenn die Schnittstelle "Token" oder etwas anderes heißt, könnten Sie ERC20 immer noch als Eingabeargumenttyp für _token verwenden? im TokenSwapper-Vertrag?
Ja, der Name spielt keine Rolle. Die Namen der Funktionen, wie auch immer in der Schnittstelle deklariert, spielen eine Rolle.
Woher weiß TokenSwapper, dass es eine Schnittstelle verwenden muss, wenn sie nicht vom Vertrag geerbt oder im Vertrag angegeben ist? vielen Dank für die Beseitigung meiner Engpässe!