Solidity

如何將所有權轉移到另一個契約?

  • July 16, 2018

Claimable我有一個繼承自OpenZeppelin的契約的契約(請參見此處):

pragma solidity ^0.4.24;
import "./Claimable.sol";

contract MyTestContract is Claimable {
   uint256 public id;
   function set(uint256 _id) external onlyOwner {id = _id;}
}

目的當然是限制 function 的呼叫權限set

這個函式只能從我用來部署合約的賬戶中呼叫。

部署後,我想將此帳戶的所有權轉移到另一個契約。

這樣做的原因不是我的問題的一部分,但無論如何,我需要對函式強制執行多重簽名,並且只有在 Y 個允許的使用者中的 X 個送出請求後才允許執行它。因此,我需要將合約的所有權從我的賬戶轉移到 Gnosis 的 MultiSig 合約(參見此處),我自己部署了該合約。

我遇到問題並且無法真正解決的問題是如何將所有權轉移到“不完全是帳戶”的東西。

當我將所有權從我的帳戶轉移到網路上的另一個帳戶時,它工作正常。

例如,我建立了一個有 8 個帳戶的 Ganache 網路,然後執行這個 Truffle 測試:

contract('MyTestContract', (accounts) => {
   it('Transfer Ownership', async () => {
       let   myTestContract = await artifacts.require('MyTestContract').new();
       let   owner = await myTestContract.owner();
       assert(owner === accounts[0]);
       await myTestContract.transferOwnership(accounts[1]);
       await myTestContract.claimOwnership({from: accounts[1]});
       let   newOwner = await myTestContract.owner();
       assert(newOwner === accounts[1]);
   });
});

但是當我將所有權從我的賬戶轉移到我部署到網路中的合約地址時,Truffle 報告:

錯誤:無法辨識發件人帳戶

現在,錯誤本身是有道理的,因為網路上沒有這樣的帳戶。

所以我的問題是 - 是否有可能做我想要實現的目標?

我覺得我對賬戶和契約之間的區別有一些基本的誤解,如果有人能為我澄清一下,我將非常感激。

非常感謝你!

更新:

澄清一下,這是我將所有權轉移到 MultiSig 合約的方式:

await myTestContract.transferOwnership(multiSigContract.address);
await myTestContract.claimOwnership({from: multiSigContract.address});

順便說一句,當我使用Ownable而不是Claimable,即:

鏈上程式碼:

contract MyTestContract is Ownable {...}

鏈下程式碼:

await myTestContract.transferOwnership(multiSigContract.address);

所有權轉移成功完成,MultiSig 合約是唯一可以呼叫該set函式的合約。

所以問題本質上是:

await myTestContract.claimOwnership({from: multiSigContract.address});

await myTestContract.claimOwnership({from: multiSigContract.address});

是問題所在。您是在告訴 truffle 發送由它無法控制的地址簽名的交易。因此錯誤

您可以將 Gnosis MultiSigContract 視為您發布交易的“中繼”,然後需要批准才能通過(如果需要,確認高於 1)。

為了使您的主契約的“契約”“聲明所有權”,您需要創建一個交易來執行此操作:

流動:

  1. 部署主合約
  2. 部署多重簽名(設置 2 個確認,並將賬戶 1 和 2 添加為所有者)
  3. 從“myTestcontract”呼叫 transferOwnership
  4. 創建並送出呼叫主合約上的“claimOwnership”方法的交易到多重簽名
  5. 從賬戶 1 和 2 呼叫多重簽名合約的“confirmTransaction”。
  6. multi-sig 應該是新的所有者。

困難的部分是第 4 步,它將帶您了解如何建構solidity abi 呼叫的內部工作原理。您可以選擇手動執行( bytes4(sha3(“contract_method(bytes,bool,uint256

$$ $$)”) ),或者讓 truffle instance.contract.metod.getData 助手為你做這件事。 看看https://github.com/gnosis/MultiSigWallet/blob/master/test/javascript/testExternalCalls.js

您的最終程式碼應類似於:(未經測試)

   // 1 - deploy main contract

   let   myTestContract = await artifacts.require('MyTestContract').new();
   let   owner = await myTestContract.owner();
   assert(owner === accounts[0]);

   // 2 - deploy multi-sig ( set 2 confirmations , and add account 1 and 2 as owner )
   const deployMultisig = (owners, confirmations) => {
       return MultiSigWallet.new(owners, confirmations)
   }

   let requiredConfirmations = 2
   let multisigInstance = await deployMultisig([accounts[1], accounts[2]], requiredConfirmations)

   // 3 - call transferOwnership from "myTestcontract"
   await myTestContract.transferOwnership(multisigInstance.address);

   // 4 - create and submit a transaction that calls the "claimOwnership" method on main contract to the multisig

   // Encode claimOwnership call for the multisig
   const claimOwnershipEncoded = myTestContract.contract.claimOwnership.getData()

   await multisigInstance.submitTransaction(
       myTestContract.address, // address to call with this transaction
       0,                      // value
       claimOwnershipEncoded,  // encoded data
       {from: accounts[1]}     // first owner
   );

   // 5 - call "confirmTransaction" on multi-sig contract from account 2nd account

   const transactionId = 1 // transactionCount starts at 0, so once we add one, we're at 1 
   await multisigInstance.confirmTransaction(transactionId, {from: accounts[2]})

   // 6 - multi-sig should be the new owner.

   let   newOwner = await myTestContract.owner();
   assert(newOwner === multisigInstance.address);

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