Newton's Preposterous Miscalculation

    ethereum-libraries-wallet

    1.2.0 • Public • Published

    WalletLib

    Build Status Discord

    !!!DO NOT USE, IN THE PROCESS OF UPGRADING!!! A wallet library family provided by Modular-Network composed of 3 libraries to use for multisig wallet contract deployment.

    Library Addresses

    WalletMainLib

    Main Ethereum Network:
    Rinkeby Test Network:

    WalletAdminLib

    Main Ethereum Network:
    Rinkeby Test Network:

    WalletGetterLib

    Main Ethereum Network:
    Rinkeby Test Network:

    License and Warranty

    Be advised that while we strive to provide professional grade, tested code we cannot guarantee its fitness for your application. This is released under The MIT License (MIT) and as such we will not be held liable for lost funds, etc. Please use your best judgment and note the following:

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    Installation and Usage

    How to install

    npm install ethereum-libraries-wallet

    How to link

    Amend the deployment .js file in your truffle migrations/ directory as follows:

    var WalletMainLib = artifacts.require("ethereum-libraries-wallet/contracts/WalletMainLib.sol");
    var WalletAdminLib = artifacts.require("ethereum-libraries-wallet/contracts/WalletAdminLib.sol");
    var WalletGetterLib = artifacts.require("ethereum-libraries-wallet/contracts/WalletGetterLib.sol");
    var YourWalletContract = artifacts.require("./YourWalletContract.sol");
    ...
     
    module.exports = function(deployer) {
      deployer.deploy(WalletMainLib, {overwrite: false});
      deployer.deploy(WalletAdminLib, {overwrite: false});
      deployer.deploy(WalletGetterLib, {overwrite: false});
      deployer.link(WalletMainLib, YourWalletContract);
      deployer.link(WalletAdminLib, YourWalletContract);
      deployer.link(WalletGetterLib, YourWalletContract);
      deployer.deploy(YourWalletContract);
    };

    Note: If you have not created a second deployment .js file in the migrations/ directory, this needs to be done first. You cannot use the 1_initial_migration.js file for your migrations.

    Note: The .link() function should be called before you .deploy(YourWalletContract). Also, be sure to include the {overwrite: false} when writing the deployer i.e. .deploy(WalletMainLib, {overwrite: false}). This prevents deploying the library onto the main network at your cost and uses the library already on the blockchain. The function should still be called however because it allows you to use it in your development environment. See below

    Testing

    Test: npm run test

    Test Coverage: Solidity coverage is not currently emitting events properly for Solidity v0.4.21

    solc Installation

    version 0.4.21

    For direction and instructions on how the Solidity command line compiler works see the documentation.

    With standard JSON input

    The Standard JSON Input provides an easy interface to include libraries. Include the following as part of your JSON input file:

    {
      "language": "Solidity",
      "sources":
      {
        "YourContract.sol": {
          ...
          ...
        },
        "WalletMainLib.sol": {
          "content": "[Contents of WalletMainLib.sol]"
        },
        "WalletAdminLib.sol": {
          "content": "[Contents of WalletAdminLib.sol]"
        },
        "WalletGetterLib.sol": {
          "content": "[Contents of WalletGetterLib.sol]"
        }
      },
      "settings":
      {
        ...
        "libraries": {
          "YourContract.sol": {
            "WalletMainLib": "",
            "WalletAdminLib": "",
            "WalletGetterLib": "",
          }
        }
      }
    }

    solc without standard JSON input

    When creating unlinked binary, the compiler currently leaves special substrings in the compiled bytecode in the form of 'LibraryName' which leaves a 20 byte space for the library's address. In order to include the deployed libraries in your bytecode create a file with one library string per line and include these libraries as follows:

    "WalletMainLib:"
    "WalletAdminLib:"
    "WalletGetterLib:"
    

    then add the following flag to your command:

    --libraries filename

    Finally, if you have an unlinked binary already stored with the 'LibraryName' placeholder, you can run the compiler with the --link flag and include each library with the following flag:

    --libraries "WalletMainLib:"

    solc documentation

    See the solc documentation for further information.

    solc-js Installation

    version 0.4.21

    Solc-js provides javascript bindings for the Solidity compiler and can be found here. Please refer to their documentation for detailed use.

    This version of Solc-js also uses the standard JSON input to compile a contract. The entry function is compileStandardWrapper() and you can create a standard JSON object explained under the solc section and incorporate it as follows:

    var solc = require('solc');
    var fs = require('fs');
     
    var file = fs.readFileSync('/path/to/YourWalletContract.sol','utf8');
    var mainLib = fs.readFileSync('./path/to/WalletMainLib.sol','utf8');
    var adminLib = fs.readFileSync('./path/to/WalletAdminLib.sol','utf8');
    var getterLib = fs.readFileSync('./path/to/WalletGetterLib.sol','utf8');
     
    var input = {
      "language": "Solidity",
      "sources":
      {
        "YourContract.sol": {
          "content": file
        },
        "WalletMainLib.sol": {
          "content": mainLib
        },
        "WalletAdminLib.sol": {
          "content": adminLib
        },
        "WalletGetterLib.sol": {
          "content": getterLib
        }
      },
      "settings":
      {
        ...
        "libraries": {
          "YourContract.sol": {
            "WalletMainLib": "",
            "WalletAdminLib": "",
            "WalletGetterLib": "",
          }
        }
        ...
      }
    }
     
    var output = JSON.parse(solc.compileStandardWrapper(JSON.stringify(input)));
     
    //Where the output variable is a standard JSON output object.

    Solc-js Installation via Linking

    Solc-js also provides a linking method if you have compiled binary code already with the placeholder. To link each library the call would be:

    bytecode = solc.linkBytecode(bytecode, { 'WalletMainLib': '' });

    Solc-js documentation

    See the Solc-js documentation for further information.

    Basic Usage

    The Wallet Libraries provide all of the functionality needed to generate a fully functional multisig wallet. Functionality is split into 3 different libraries. Each library serves the following purposes:

    1. WalletMainLib: This is the main library used to create a wallet and initialize parameters. It contains the WalletData struct which should be placed in the storage of your wallet contract. This library also contains the primary transaction initiating, confirming, and revocation code.

    2. WalletAdminLib: This library contains all of the functionality to change the parameters of your multisig wallet such as adding owners, changing signature requirements, etc.

    3. WalletGetterLib: This library contains all of the getter functions for your wallet data.

    The wallet generated will have some of these benefits and characteristics:

    • Can have up to 50 wallet owners.
    • Allows for signature requirements to be defined for three types of operations: administrative, minor transactions, and major transactions.
      Administrative: These are transactions that change signature requirements, add owners, remove owners, etc.
      Minor Transactions: These are ether or token transfers below a set daily threshold.
      Major Transactions: These are ether or token transfers at or above a set daily threshold.
    • Allows a major transaction threshold to be set individually for any token.
    • Provides a transaction hash for any pending transaction such as is implemented in Gav's wallet, allowing subsequent signatures to be submitted by hash.
    • Can create other contracts from within the wallet.
    • Any new token will automatically have a major threshold of 0 until a threshold is defined by the wallet owners.
    • Allows signatures to be revoked at any point in time prior to the transaction confirming.

    The wallet contract should put the init function from the WalletMainLib in the constructor with the required parameters given. Once deployed, owners can initiate any transaction by calling the appropriate function with the required data for admin functions, transfer or value data for token or ether transactions, or contract data for deploying new contracts. Most transaction requests end with a bool and bytes parameter. The bool parameter should be true for any transaction being initiated or confirmed and false for any signature revocation. The bytes parameter should be the msg.data passed automatically by the wallet contract. See our example wallet contract to get a better idea of its implementation.

    Most functions return two parameters, a bool and a bytes32. The transaction and admin functions will generally return false and log an error event when submitted parameters are either wrong or the call will not work. In the case of a non-owner attempting to submit a transaction or any failure during actual execution, the function will throw a standard out of gas error with no reason in order to successfully revert changes. These functions will return true if any confirm or revocation call is successful. The functions that return a bytes32 will also log this value in an event. Owners may choose to use the generic confirmTx or revokeConfirm functions by providing the id for any transaction already initiated, a concept artfully developed by Gav of York himself.

    DISCLAIMER: As always, please ensure you review this code thoroughly for your team's use. We strive to make our code as solid, clean, and well documented as possible but will not accept liability for unforeseen circumstances in which value is lost or stolen. This includes but not limited to any inability to meet signature requirements to move funds, loss of private keys, transactions you deem unauthorized from an owner's account, a non-owners ability to gain access to your wallet, etc. The library code has been thoroughly tested by our team and believe it to be suitable enough to be posted in our open source repository, however, you are still responsible for its implementation and security in your smart contract. Please use your best judgment. Please let us know immediately if you have discovered any issues or vulnerabilities with this library.

    Usage Example

    pragma solidity ^0.4.21;
    
    import "ethereum-libraries-wallet/contracts/WalletMainLib.sol";
    import "ethereum-libraries-wallet/contracts/WalletAdminLib.sol";
    import "ethereum-libraries-wallet/contracts/WalletGetterLib.sol";
    
    contract YourWalletContract {
      using WalletMainLib for WalletMainLib.WalletData;
    
      WalletMainLib.WalletData public wallet;
    
      event Deposit(uint value);
    
      function YourWalletContract() {
        address[] memory _owners = new address[](5);//Define initial account owners with your owners
        _owners[0] = 0xb4e205cd196bbe4b1b3767a5e32e15f50eb79623;
        _owners[1] = 0x40333d950b4c682e8aad143c216af52877d828bf;
        _owners[2] = 0x0a1f4fcde83ba12ee8343488964811218da3e00e;
        _owners[3] = 0x79b63228ff63659248b7c688870de388bdcf0c14;
        _owners[4] = 0x36994c7cff11859ba8b9715120a68aa9499329ee;
        wallet.init(_owners,4,3,1,100000000000000000000);
      }
    
      //Payable fallback function
      function() payable {
        Deposit(msg.value);
      }
    
      /*Getters*/
    
      function owners() constant returns (address[51]) {//Returns fixed array until fork
        return wallet.getOwners();
      }
    
      function ownerIndex(address _owner) constant returns (uint) {
        return wallet.getOwnerIndex(_owner);
      }
    
      ...
    }
    

    Functions

    The following is the list of functions available to use in your smart contract.

    Primary Functions

    init(WalletMainLib.WalletData storage, address[], uint256, uint256, uint256, uint256)

    (WalletMainLib.sol, line 88)

    Constructor. Initializes the wallet in the calling contract's storage. Caller passes in owners and signature settings for the wallet. Owners must be valid ethereum addresses and signature requirements must be greater than zero and less than or equal to the number of owners. _majorThreshold parameter should set the daily spend limit for minor ether transactions in wei.

    Arguments

    WalletMainLib.WalletData self The storage wallet in the calling contract.
    address[] _owners Array of initial wallet owner addresses
    uint256 _requiredAdmin The number of signatures required for administrative changes
    uint256 _requiredMajor The number of signatures required for major transactions
    uint256 _requiredMinor The number of signatures required for minor transactions
    uint256 _majorThreshold The daily Ether spend threshold for transactions to become major, in units of wei

    Returns

    bool

    serveTx(WalletMainLib.WalletData, address, uint256, bytes, bool, bytes)

    (WalletMainLib.sol, line 261)

    Sends the specified amount of Ether or tokens from the Wallet to an address. This function requires a certain number of signatures from the wallet owners, indicated by requiredMinor for minor transactions and requiredMajor for major transactions. If it is the first call with the given parameters, the transaction is created and a confirmation from the sender is recorded. Additional calls sent from different owners but with the same parameters act as confirmations of the transaction. If a previously confirmed owner calls this function with the same arguments for the pending transaction, but with the confirm flag set to false, their confirmation for the transaction will be revoked. When the confirmations reach the required number, the transaction is executed.

    Arguments

    WalletMainLib.WalletData self The storage wallet in the calling contract.
    address _to Intended recipient of transaction.
    uint256 _value Amount of Ether to be sent.
    bytes _txData Any transaction data to be sent to recipient.
    bool _confirm True if initiaing or confirming a transaction, false if revoking a signature.
    bytes _data Data for this call sent automatically by the calling contract.

    Returns

    bool True if transaction confirmed or revoked successfully
    bytes32 The transaction id which can be provided to confirmTx or revokeConfirm.

    confirmTx(WalletMainLib.WalletData storage, bytes32)

    (WalletMainLib.sol, line 351)

    Confirms the specified pending transaction with the sender's signature. If the transaction does not exist, the call will fail. If the callers signature is the final signature needed for the transaction to succeed, the transaction will execute.

    Arguments

    WalletMainLib.WalletData self
    bytes32 _id

    Returns

    bool

    revokeConfirm(WalletMainLib.WalletData storage, bytes32)

    (WalletMainLib.sol, line 391)

    Revokes the sender's confirmation from a pending transaction. If the transaction does not exist or has already succeeded, the call will fail. The caller also needs to have already confirmed the transaction.

    Arguments

    WalletMainLib.WalletData self
    bytes32 _id

    Returns

    bool

    Administrative Functions

    These functions are for performing actions that change the administrative settings of the Wallet contract such as owners, major/minor transaction threshholds, and number of signatures required. They behave almost exactly like ServeTx behaves above, but with requiredAdmin number of signatures required to execute changes.

    changeOwner(WalletMainLib.WalletData storage, address, address, bool, bytes)

    (WalletAdminLib.sol, line 139)

    Changes owner address to a new address. bool should be true if confirming or initiating the transaction and false if revoking a confirmation. bytes parameter should be passed as msg.data from wallet contract.

    Arguments

    WalletMainLib.WalletData self
    adress _from
    address _to
    bool _confirm
    bytes _data

    Returns

    bool
    bytes32

    addOwner(WalletMainLib.WalletData storage, address, bool, bytes)

    (WalletAdminLib.sol, line 209)

    Adds a new user as an owner of the wallet.

    Arguments

    WalletMainLib.WalletData self
    adress _newOwner
    bool _confirm
    bytes _data

    Returns

    bool
    bytes32

    removeOwner(WalletMainLib.WalletData storage, address, bool, bytes)

    (WalletAdminLib.sol, line 280)

    Removes an existing owner from the wallet.

    Arguments

    WalletMainLib.WalletData self
    adress _ownerRemoving
    bool _confirm
    bytes _data

    Returns

    bool
    bytes32

    changeRequiredAdmin(WalletMainLib.WalletData storage, uint256, bool, bytes)

    (WalletAdminLib.sol, line 351)

    Changes the number of signatures required to confirm administrative changes.

    Arguments

    WalletMainLib.WalletData self
    uint256 _requiredAdmin
    bool _confirm
    bytes _data

    Returns

    bool
    bytes32

    changeRequiredMajor(WalletMainLib.WalletData storage, uint256, bool, bytes)

    (WalletAdminLib.sol, line 418)

    Changes the number of signatures required to confirm major transactions.

    Arguments

    WalletMainLib.WalletData self
    uint256 _requiredMajor
    bool _confirm
    bytes _data

    Returns

    bool
    bytes32

    changeRequiredMinor(WalletMainLib.WalletData storage, uint256, bool, bytes)

    (WalletAdminLib.sol, line 485)

    Changes the number of signatures required to confirm minor transactions.

    Arguments

    WalletMainLib.WalletData self
    uint256 _requiredMinor
    bool _confirm
    bytes _data

    Returns

    bool
    bytes32

    changeMajorThreshold(WalletMainLib.WalletData storage, address, address, bool, bytes)

    (WalletAdminLib.sol, line 553)

    Changes the threshold of tokens or wei spent per day that needs to be crossed for the transaction to be considered major.

    Arguments

    WalletMainLib.WalletData self
    adress _from
    address _to
    bool _confirm
    bytes _data

    Returns

    bool
    bytes32

    Getter Functions

    getOwners(WalletMainLib.WalletData storage)

    (WalletGetterLib.sol, line 40)

    Get list of wallet owners, will return fixed 50 item array until Metro fork.

    Arguments

    WalletMainLib.WalletData self

    Returns

    address[51]

    getOwnerIndex(WalletMainLib.WalletData storage)

    (WalletGetterLib.sol, line 52)

    Get index of an owner.

    Arguments

    WalletMainLib.WalletData self

    Returns

    uint256

    getMaxOwners(WalletMainLib.WalletData storage)

    (WalletGetterLib.sol, line 59)

    Get max number of wallet owners.

    Arguments

    WalletMainLib.WalletData self

    Returns

    uint256

    getOwnerCount(WalletMainLib.WalletData storage)

    (WalletGetterLib.sol, line 66)

    Get number of wallet owners.

    Arguments

    WalletMainLib.WalletData self

    Returns

    uint256

    getRequiredAdmin(WalletMainLib.WalletData storage)

    (WalletGetterLib.sol, line 73)

    Get sig requirements for administrative changes.

    Arguments

    WalletMainLib.WalletData self

    Returns

    uint256

    getRequiredMinor(WalletMainLib.WalletData storage)

    (WalletGetterLib.sol, line 80)

    Get sig requirements for minor tx spends.

    Arguments

    WalletMainLib.WalletData self

    Returns

    uint256

    getRequiredMajor(WalletMainLib.WalletData storage)

    (WalletGetterLib.sol, line 87)

    Get sig requirements for major tx spends.

    Arguments

    WalletMainLib.WalletData self

    Returns

    uint256

    getCurrentSpend(WalletMainLib.WalletData storage, address)

    (WalletGetterLib.sol, line 95)

    Get current day spend for token.

    Arguments

    WalletMainLib.WalletData self
    address _token Address of the token contract, use 0 for ether.

    Returns

    uint256[2] 0-index is day timestamp, 1-index is the day spend

    getMajorThreshold(WalletMainLib.WalletData storage, address)

    (WalletGetterLib.sol, line 106)

    Get major tx threshold per token.

    Arguments

    WalletMainLib.WalletData self
    address _token

    Returns

    uint256

    getTransactionLength(WalletMainLib.WalletData storage, bytes32)

    (WalletGetterLib.sol, line 114)

    Get the number of tx's with the same id.

    Arguments

    WalletMainLib.WalletData self
    bytes32 _id

    Returns

    uint256 Number of transactions with this id, can be used to query for specific tx, see getTransactionConfirms

    getTransactionConfirms(WalletMainLib.WalletData storage, bytes32, uint256)

    (WalletGetterLib.sol, line 123)

    Get list of confirmations for a tx, use getTransactionLength to get latest number.

    Arguments

    WalletMainLib.WalletData self
    bytes32 _id
    uint256 _number

    Returns

    uint256[50] List of confirmations, fixed at 50 items until Metro fork

    getTransactionConfirmCount(WalletMainLib.WalletData storage, bytes32, uint256)

    (WalletGetterLib.sol, line 140)

    Retrieve tx confirmation count.

    Arguments

    WalletMainLib.WalletData self
    bytes32 _id
    uint256 _number

    Returns

    uint256 The current number of tx confirmations.

    getTransactionSuccess(WalletMainLib.WalletData storage, bytes32, uint256)

    (WalletGetterLib.sol, line 153)

    Retrieve if transaction was successful.

    Arguments

    WalletMainLib.WalletData self
    bytes32 _id
    uint256 _number

    Returns

    bool

    Install

    npm i ethereum-libraries-wallet

    DownloadsWeekly Downloads

    2

    Version

    1.2.0

    License

    MIT

    Unpacked Size

    7.96 MB

    Total Files

    23

    Last publish

    Collaborators

    • hackdom