Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
dcarlcf committed Apr 20, 2019
2 parents b8b2a70 + 0048eae commit eae01d0
Showing 1 changed file with 24 additions and 5 deletions.
29 changes: 24 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,30 @@ This is the source code for the Nifty Wallet, a smart contract wallet that makes

Below are some notes on design choices that were made, further detail on how the wallet is secured and general information about the wallet.

## Architecture

There are three contracts that interact to form the Nifty Wallet - deployed instances of the Nifty Wallet contract, a master contract, and a static calls contract.

The master contract stores the critical information, such as which keys are permitted to send transactions, and which key is supposed to have signed a transaction. A deployed Nifty Wallet instance checks with the master contract when it is evaluating whether or not it should execute a specific transaction. The master contract is secured with a multi sig architecture based on the Gnosis Multi Sig contract - any changes to the master contract can only be made by a multi sig transaction confirmed by 3 owners.

We cannot anticipate all future static calls that the Nifty Wallet will have to make. So the Nifty Wallet redirects static calls to another contract. This is implemented using the fallback function of the Nifty Wallet.

This architecture has two purposes - it reduces the deployment cost of deploying a Nifty Wallet instance, and it measn that we can add support for additional static calls in the future as the need arises.

The master contract stores a reference to the location of the static call contract. This reference can be changed with a multi sig transaction.

Here is a visualization of how the Nifty Wallet setup works:

![Nifty Wallet Visual](https://s3-us-west-1.amazonaws.com/nftgimagebucket/Screen+Shot+2019-04-20+at+3.30.53+PM.png
"Nifty Wallet Visual")

## Security

Secure system design should be the #1 priority for any project that helps users manage crypto assets of any kind, and that is certainly the case for the Nifty Wallet.

Each Nifty Wallet is secured by two separate private keys, both of which are stored on [HSMs](https://en.wikipedia.org/wiki/Hardware_security_module).
Each Nifty Wallet is secured by two separate private keys, both of which are stored on a [HSM](https://en.wikipedia.org/wiki/Hardware_security_module). So a Nifty Wallet can be thought of as a kinda of multisig, but one that executes transactions instantly.

This is implemented by assigning each wallet a specific signing key, which signs information for that wallet, and only permitting transactions that come approved sending keys which are controlled by Nifty Gateway.
This mechanism is implemented by assigning each wallet a specific signing key, which signs information for that wallet, and only permitting transactions that come approved sending keys which are controlled by Nifty Gateway.

Signing keys and sending keys are both stored in a master contract so that they can be changed or disabled in an emergency scenario if an HSM is somehow compromised. The key that has control over the master contract is stored in a completely cold environment.

Expand Down Expand Up @@ -39,15 +56,17 @@ You can build systems to track transaction executions if you like, but we provid

The transaction execution function borrows heavily from [Gnosis Multi Sig Wallet](https://github.com/gnosis/MultiSigWallet/blob/master/contracts/MultiSigWallet.sol). To reduce potential security vulnerabilites, we avoided rolling our own smart contract functions whenver possible.

## Signature functions
## Static Calls

We want to be able to upgrade the static calls that each deployed Nifty Wallet instance can support. To accomplish this, the Nifty Wallet uses the fallback function to redirect an unknown call to our static calls contract, which can be found in NiftyStaticCalls.sol.

The main limitation of smart contract wallets is that they cannot sign messages. The Nifty Wallet implements two functions that allow another smart contract to detect in a signature submitted is valid for a specific instance of a Nifty Wallet - isValidSignature(bytes32,bytes), which returns a bool, and isValidSiganture(bytes,bytes), which returns a bytes4 value and aligns with [EIP1271](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1271.md).

If a message or piece of data has been signed by the signing wallet for a specific instance of the Nifty Wallet, then isValidSignature will return a true for the (bytes32,bytes) version or the EIP1271 magic value 0x20c13b0b for the (bytes,bytes) version.

There are two separate versions of this function to accomodate both EIP1271 and existing smart contracts (like 0x's) that use the (bytes32,bytes) version and return a bool.
Because there are only 5 signing keys, and potentially millions of deployed instances of NiftyWallet.sol, we need to make sure that a signature from one Nifty Wallet cannot be used for another Nifty Wallet. To ensure a signature is globally unique, the data to be signed is concatenated with the address of the signing wallet before the recover function is executed. This ensures that a signature useed for one deployed Nifty Wallet with ID of 0 cannot also be used for another deployed Nifty Wallet with id of 0. You can see this implemented in NiftyStaticCalls.sol.

## Receivers
There are two separate versions of this function to accomodate both EIP1271 and existing smart contracts (like 0x's) that use the (bytes32,bytes) version and return a bool.

The Nifty Wallet also has a safe ERC721 receiver and a safe ERC1155 receiver, meaning that it can receive ERC721 and ERC1155 tokens sent with the safeTransferFrom or safeTransferBatchFrom methods.

Expand Down

0 comments on commit eae01d0

Please sign in to comment.