Solidity

智能合約設計:託管/控制器合約

  • May 16, 2018

我將如何創建以下內容:
託管/控制器合約 A 能夠接受來自合約 B 的 ERC20 代幣和來自 C 方的 ETH,並在滿足某些條件時進行交換。

同樣的合約 A 也應該能夠從合約 D 接收 ERC20 代幣,從合約 E 接收 ETH,並在滿足某些條件時進行交換。

問題的關鍵/相關性是,如何設計合約 A 以能夠處理不同類型的 ERC20 代幣輸入,例如 Walton(WTC) 和 FUSION(FSN) ERC20 代幣?

這就是介面的用武之地。太好了,因為 ERC-20 實際上是一個介面!下面我給你舉個例子。如您所見,TokenSwapper甚至不需要知道TokenAand TokenB,只需它們實現ERC20介面即可。

哦,在開始開發之前,您應該首先熟悉 ERC20 介面的基礎知識。閱讀此維基

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);
   }
}

引用自:https://ethereum.stackexchange.com/questions/48664