Customizing and Using Multisig Contracts For Contract Executions
Cryptocurrencies are thought to be the safest way to store assets. But most of usage are designed for single addresses that secured by private keys. Loss of this private key means you will never be able to reach your account. Or stolen of your private key means someone is now owner of your account and wealth. A better solution may be the MultiSig contracts (Wallet Contracts) that owned by many people and ownership of this contract requires predefined minimum account’s keys. So it can provide both security and reliance.
In classic approach, you transfer your partnership’s balance to created MultiSig contract, and whenever you decide to spend from this balance, you and your partners confirm this transaction and specified Ether amount will be transferred. So you can use only for Ether transfers. Because it is a Smart Contract, we can modify it and use for contract executions like token transfers or other custom function executions. In this article, we will use it for a simple contract execution but as I said you can use it for your own projects.
Firstly we start with modifying basic MultiSig contract. In this one, main function that we will change is “execute” function which is used for very first transaction that saves our confirmation request and notify other owners of contract. It uses a predefined daily limit to specify spend limit for owners. Because we will not use Ether as value (value will be “0") in our transactions, we don’t need daily limit in our contract. Final state of our MultiSig contract’s “execute” function as the following;
In our MultiSig transactions, we will define “_to” as our final contract address that will be executed after confirmation, “_value” will be “0” as we do not want to use Ether in our transaction, and “_data” will be the call input data of our final contract’s function. At the final confirmation, MultiSig contract will call our Example Final Contract with this “data” and this data will determine which function with which parameters will be executed at this contract.
After modifying our MultiSig Contract, we can deploy it using online solidity IDE “Remix” or via Ethereum Wallet. I will use remix for this deployment. When you deploy contract, it will ask you for some information like “who are the owners?” and “what is the minimum approve limit for executions?”, we will define these parameters in our contracts constructor. In these example there will be four owners and required confirmation will be three. As I creator of this contract, i will determine three other addresses. Here is the constructor value which I used in my example;
["0xE771e5B197C8211fa4EB3fB442E97199630C2cf2", "0x8570FC52E708534A25408Ac67A4d570D82c5f031", "0x5903A8584526656E5F644292f2A0069a77CEc220"], 3, 0
And here is the deployment of contract;
After deployment we will get our newly created MultiSig Contract’s address. In my example it is “0x1F271047cC3F971D8B2D226A1Af0B5e7DEE5aF20”. We will use this address in our wallet to import this contract. Here is the import process of our contract;
As you can see, it finds out that I am one of the owners of this contract. We will repeat this process for other owners of this contract. After that we can see this wallet contract in our wallet;
Next step is to execute our Example Contracts function in our MultiSig Contract. This example contract is as simple as that in includes only one function and it changes only a uint variable in this contract;
The deployed address of this contract is as following “0xf8318fC2BDDc6F46F356EcBEe300064213DA9FA5”. To execute this contract in our MultiSig contract, we need call input data of this example function. You can get it via Nethereum, a .Net integration library for ethereum. You need contract address and contract ABI for this process, here is the sample code;
var web3 = new Web3("http://localhost:8545");var exampleContractAddress = "0xf8318fC2BDDc6F46F356EcBEe300064213DA9FA5";
var exampleContract = web3.Eth.GetContract(MultiSigExample.Properties.Resources.ExampleContractABI, exampleContractAddress);var exampleExecuteFunction = exampleContract.GetFunction("Execute");
var data = exampleExecuteFunction.CreateCallInput(20).Data;
In this code, we get the callinput data for “Execute” function of our ExampleContract with a value “20”. Generated call input data for this is; “0xddb556f10000000000000000000000000000000000000000000000000000000000000014”. We will use this data in our MultiSig contract for executing this contract after confirmation. You can use it via Ethereum Wallet by selecting our wallet contract and selecting “execute” function of MultiSig contract.
Or using Nethereum, you can create transaction to MultiSig contract via code as follows;
var account = new Account("privatekey");
var web3 = new Web3(account, "http://localhost:8545");var exampleContractAddress = "0xf8318fC2BDDc6F46F356EcBEe300064213DA9FA5";
var exampleContract = web3.Eth.GetContract(MultiSigExample.Properties.Resources.ExampleContractABI, exampleContractAddress);
var exampleExecuteFunction = exampleContract.GetFunction("Execute");
var data = exampleExecuteFunction.CreateCallInput(20).Data;
var byteData = data.HexToByteArray();var multiSigContractAddress = "0x1F271047cC3F971D8B2D226A1Af0B5e7DEE5aF20";
var multiSigContract = web3.Eth.GetContract(MultiSigExample.Properties.Resources.MultiSigABI, multiSigContractAddress);
var multiSigExecuteFunction = multiSigContract.GetFunction("execute");
var gas = await multiSigExecuteFunction.EstimateGasAsync(exampleContractAddress, 0, byteData);
var transactionHash = await multiSigExecuteFunction.SendTransactionAsync(account.Address, gas, null, exampleContractAddress, 0, byteData);
After execution of our MultiSig Contract, you can see the notification from wallet contract in our wallet;
The next step is to wait for other owners’ confirmation. As you can see as follows, they also will get a notification from our wallet contract;
After last confirmation that we needed as third confirmation, we can see the transaction details and fired log events. One of them is our Example Contract’s “Execution” event, and that means this transaction also triggered our Example Contract and our event has fired as we expected.
Even we can see our example value’s new value and fired events in our wallet. “My value” is now “20” as we specified in our data to MultiSig contract.
This article only describes a simple example of using MultiSig contracts for another contract’s execution. You can implement different variations of this perspective. For example; you can transfer your tokens to MultiSig contract and spend your token balance from MultiSig contract with multi-ownership. You can see and use resources for this article from my GitHub.