區塊鏈 程式開發

EIP-1167 Minimal Proxy – 低成本複製既有的合約

因為學長是 portto 的實習生,加上也在區塊鏈圈子打滾許久,因此我自然而然有了 Blocto 的錢包(?)。Blocto 的錢包是一種合約錢包,藉此來滿足一些設計(例如代替使用者發起交易等等)。部署這樣的一個合約錢包,從交易紀錄可以看到他花費了 0.02 ETH 左右,在撰文當下就是 26.64 美金,這樣的成本對營運者顯然是過高,轉交給消費者也不是很實際,有沒有辦法處理呢?有的,透過 Minimal Proxy Contract 就可以達成。

什麼是 Minimal Proxy ?

對於在網路世界遨遊許久的人,Proxy 應該不會是一個陌生的名詞,簡單來說,Proxy 可以理解成轉送者,它基本上不會篩選或對收到的訊息做處理,只會轉送給預先定義好的對象。

而在 EIP-1167 中,提出了 Minimal Proxy。當使用者呼叫 Proxy 合約時,這個合約將把呼叫轉送到另一個合約,稱之為 Implementation Contract(Proxy 合約則稱作 Redirecting Contract)。

因此若是需要建立多個相同功能,但地址、狀態需要獨立的合約,那 Minimal Proxy 或許就可以派上用場。例如前文提到的 Blocto 合約錢包,必須要讓每個使用者都有獨立的地址,也需要獨立儲存各種狀態。

由於 Redirecting Contract 本身沒有功能,因此在建立合約時就可以降低合約所需的儲存空間大小,藉此省下手續費。但在未來每次呼叫也都會額外經過一層合約,因此也會提高後面交易的手續費。這個手續費主要取決於函數參數的大小。

Minimal Proxy 的好壞

如前文所說,Minimal Proxy 可以降低相同合約部署的費用,但也會提高未來呼叫時的手續費。因此在選用 Minimal Proxy 時,應考慮未來的使用狀況,例如若每個函數都有大量的參數,並且可以預期會經常呼叫,那就需要斟酌是否直接部署完整合約較為合適。

使用 Minimal Proxy 的方法

在使用 Minimal Proxy 時,需要針對原始的合約做調整,最重要的部分是不能在函數外或在 constructor 指派需要隔離的變數值。例如這個合約:

contract People {
  string public name = "Default";
  function setName (string memory name_) public {
    name = name_;
  }
}

以及

contract People {
  string public name;
  constructor (string memory name_) {
    name = name_;
  }
}

中,複製出來的合約將會共用 name 變數,這是由於在函數外部或在 constructor 指派的變數(概念上)和合約程式碼放在一起,無論誰呼叫都將使用相同的儲存位置。而在函數內指派的就不會與合約程式碼放一起,因此可以達到隔離。

接著,我們開始部署 CloneFactory,提案者已經提供一份程式碼可利用了,只需要導入使用即可。

contract CloneFactory {
  // 略過
}

contract PeopleFactory is CloneFactory {
  address public template;
  constructor (address template_) {
    template = template_;
  }

  function create (string memory name) public returns (People result) {
    result = People(createClone(template));
    result.setName(name);
  }
}

contract People {
  string public name;
  function setName(string memory name_) public {
    name = name_;
  }
}

References

  1. Deep dive into the Minimal Proxy contract
  2. EIP-1167: Minimal Proxy Contract
  3. Reason Why You Should Use EIP1167 Proxy Contract. (With Tutorial)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *