So you want to buy some crypto?

I had a couple calls earlier this week from a couple friends who want to increase their bitcoin holdings. One is an individual investor, and the second wanted to know how to best purchase as a group. I know this is only anecdote, but I think it goes to show that this latest pullback is being seen as a buying opportunity by many. This discussion will focus on Bitcoin and Ethereum-related assets. I’ll cover the individual case first and build out from there.

Dollar cost averaging

My first friend, R, is a successful professional who has less than one percent of their net worth in bitcoin, which they currently have in a Coinbase account. They want to increase their exposure with a five-figure purchase. Timing is important for R, they know we’re still early from a long-term, but worries that short term price fluctuations might give them a bit of stress. What I am recommending to R is that they open a BlockFi account and implement a dollar cost averaging setup to scale into a position over the next six months.

The benefit to using BlockFi is two-fold. First, USD funds on the platform are currently earning 8% APR, and the interest can be paid in BTC or other cryptocurrencies. Secondly, BlockFi allows recurring trades, which means R can set it and forget it while their fiat is converted to crypto. Six months from now, they can either re-up their cash allocation, or move funds to take advantage of more decentralized, on-chain solutions.

Exchanges

BlockFi, for all its benefits, has a couple drawbacks which make it ill-suited as a primary exchange for power users. It’s not really built for traders, and is only really good for the occasional swap. Also they discourage withdrawals from the platform with only one free withdrawal per month. Additional ones can run as much as thirty dollars. Plus they can take at least one business day to process, so woe to you if you need to move funds on a weekend. So you’ll need to open an account with a full-fledged exchange.

My wife recently asked me which exchanges I use to convert cash to crypto and my response was all of them. Literally. It’s hard to make a recommendation here as a lot depends on individual circumstances, like which tokens you want to trade, how you’re moving funds (wire vs. ACH), and your familiarity with trading interfaces. On the simpler end I’d put Coinbase, Voyager, and Gemini, with Coinbase Pro, Gemini Pro, FTX and Kraken on the other. Realistically, you’ll probably want to open accounts on at least two exchanges, one as a backup.

As a security precaution, you’ll want to make sure you set up two factor authentication on your account. Do not use SMS messaging as your phone’s SIM can be spoofed, use an app like Authy or Google Authenticator instead. And as an extra layer of security, you may also want to set up new email addresses for each exchange account as well. Using different email accounts other than your primary one will protect you should it get compromised.

Self-custody and hardware wallets

While centralized exchanges are the primary fiat on-ramps to the crypto ecosystem, there are custodial risks associated with them, hacks and outages being the primary ones. Most crypto-diehards will no doubt be screaming not your keys, not your coins at me or anyone else who suggests keeping large portions of your funds on BlockFi or any centralized exchange. Self custody is the way, and while there are a number of softwallets available for phones and computers, a hardware wallet is the way to go for significant sums of coin. I recommend a Trezor for most people, but anyone who plans on participating in DeFi, daos, NFTs or whatever else on the Ethereum ecosystem might want to take a look at the Lattice1, which has a large touchscreen for inspecting smart contract calls, as well as a host of other useful features. I don’t recommend Ledger products unless you plan on dealing with Solana, as it’s the only choice currently.

Lattice1 Hardware Wallet

An important note about purchasing hardware wallets: they should only be purchased from the vendor, and never from secondary markets. It’s recommended that you use an alias and a drop box for shipping to prevent your personal details from being exposed. Make sure the anti-tampering seals are intact on all the packaging. And make sure you generate your own private keys, never use any that have been given to you by someone else, and never record them in an electronic form. The Trezor will come with several slips for you to record your seed phrase, and the Lattice1 allows you to store your keys on a password protected smart cards. Either way, make several copies and store them securely in different locations to protect from loss.

Remember, if your device is destroyed or lost and you don’t have your private keys, or if anyone else gains access to them, your funds are lost forever. There’s no password reset button or customer service team you can contact if you forget this very important point.

Institutional accounts

If you’re buying crypto for a business, you’ll want to open an institutional account with an exchange. This could be for your LLC or partnership; I have a couple tied to my checkbook IRA account. You’ll need articles of incorporation as well as certificates of good standing from whatever jurisdiction that you’re registered in. You’ll also need to complete KYC for any authorized members of the entity that will have access to the account.

Now you’ve really got two ways you can go here if you are a corporation or business that wants to get into crypto. A lot of the big hedge funds rely on custodial accounts for their holdings, as dealing with self-custody is too much of a hassle for them. One of the most popular custodial firms is Coinbase, but I don’t have experience here to tell you much more. I can tell you that many of the crypto IRA products out there are basically built on top of Coinbase Custody, which charges an annual custodial fee as well as what I consider relatively high trading fees. You’ll also be limited to the assets that Coinbase has available. There are other custodial firms available, but again, I have no experience to speak of here.

Multisigs

This section is geared toward groups of people, whether they’re part of a formal corporate entity, or even an informal one. I’ll describe a couple ways that assets can be managed in a trustless way, that is, how a group can share management of assets, without allowing any one individual to have complete control of them.

The first, and most common is called a multi-signature wallet, or multisig for short. It’s a wallet in which a certain number of owners are required to sign off on a transaction before it can be approved, commonly referred to as m of n schemes, where n is the number of private keys associated with the address, and m is the number required for a valid transaction. These are most commonly configured as 2 of 3 or 3 of 5 setups, although you can have 2 of 2 or even 8 of 8 if you wanted to. There are a number of firms that provide bitcoin-specific multisig services, and it can also be configured via a Trezor hardware wallet and the Electrum desktop application.

There are no hardware based multisig solutions for Ethereum, although on-chain smart contract solutions do exist. The most popular is Gnosis Safe. With Gnosis, an on chain vault is created, and the m of n scheme and owners are specified. ERC20 tokens and NFTs can be sent to the vault address, and Gnosis has several plugins that allows the vault to interact with a variety of apps, such as Uniswap or OpenSea. Any owner can propose a transaction, and once the requisite number of owners have approved it it can be transacted on the Ethereum network. Many of the top defi projects on Ethereum use Gnosis vaults to manage their treasuries, and it’s a relatively trivial operation for less technical owners to approve transactions.

Other on-chain solutions

Gnosis is probably the most robust solution for a formal or informal group that is comfortable with a centralized, custodial solution. There are two others I’ll mention that might be more suited for other applications or groups, one that is non-custodial, and another that is decentralized.

The first is called Set Protocol. A Set is akin to a mutual fund, and can be created with anywhere between one and twenty assets within it. Users can issue Set tokens by providing assets to the Set, meaning that the value of each token is backed by the assets within the Set itself. They can’t be created out of thin air. The Set manager can perform a number of operations with these set assets, such as trading them for other tokens or providing them to a number of DeFi protocols. These actions are somewhat limited compared to what you can do with a Gnosis vault. While the manager does not have direct access to the funds in the Set, there are a couple ways that a manager can potentially exploit funds in the set, whether through changing the management fee or trading into a illiquid shitcoin, the manager address can be assigned to a Gnosis multisig for additional security. We used Set Protocol for the Homebrew.Finance $MUG NTF Fund.

The last one I’ll mention is DaoHaus, which is used to manage decentralized autonomous organizations, or daos. Daos are basically on-chain shareholder corporations, and are useful if you want to create a trustless organization. Users can deposit into the dao in exchange for voting shares or loot, both of which grant proportional ownership of funds in the dao’s bank. Many of the popular daos on DaoHaus are venture funds or non-profit/open source grant foundations. Users can create funding proposals, the membership votes, and funds are distributed accordingly. Managing a DaoHaus can get a bit complicated, but it can also be combined with a Gnosis safe to provide more accountability. Additional development on DaoHaus minions, or associated smart contracts, continues to add more functionality to the system. We are using DaoHaus to manage membership in SAIADao.

Wrapping up

One quick note about on-chain Ethereum solutions such as Gnosis and so forth: gas fees. Congestion on the Ethereum network lead to some pretty high transaction fees over the last few months. It cost me over $500 to create the $MUG Set, back in March, with trades costing over $150 each. Creating a Gnosis safe cost me over a hundred dollars earlier this year after gas had come down, but the vault overhead does add some overhead to transactions. I wouldn’t recommend them unless you’re dealing with several thousand dollars worth of funds. Thankfully, the release of other Ethereum-compatible sidechains such as Polygon and xDAI are making relieving some of this pressure, although a full discussion of this will need to wait for another day.

Hopefully this article is helpful for others who are looking to increase their exposure to Bitcoin or Ethereum-related assets.

Testing SetProtocol on Kovan

We’ve been talking about building a TokenSet for weeks now, it seems. We believe that having the ability to manage a Set has many advantages, and we’re hoping to build one under the Homebrew.Finance banner. My primary use case for it is being able to manage “customer funds” (e.g. friends and family) in a non-custodial way, while pooling gas costs among the entire capital pool. It’s also a way that others can follow along with my strategy as well, what TokenSets calls “social trading”.

Deploying a Set is costly, over 3.2m gas from what we’ve seen . With gas at 100 gwei and ETH close to $2000, we’re talking about $500-800 just to mint a set. That’s not something that I want to do without understanding the intricacies of managing a set, both from creating it, managing the modules and assets, and issuing/redeeming the tokens. And since there aren’t any published charts with gas costs for various operations, let’s do some testing on the Kovan testnet and see what we can come up with, shall we?

Preparation

The TokenSet docs have a list of procotol contracts, both for Mainnet and Kovan. Our first task is to execute the create function on the SetTokenCreator contract. We can do this using Etherscan, but first we need some setup tasks. First, you’ll need some Kovan tokens via this faucet, and we’ll need a list of ERC20 tokens that we can use. I started off with the Weenus ERC20 faucet tokens, but Balancer has Kovan faucets for popular tokens like WETH, DAI, USDC, WBTC and others.

Now I originally did this test deployment using the Etherscan write interaction, but I’ve since discovered the wonderful seth , a “Metamask for the command line. It’s much easier to use than writing a web3 script or using the Etherscan webpage. After a couple minutes setting it up I was able to interact with Kovan using my dev Ethereum address. The hardest part was exporting and saving the private key from Metamask to a JSON keystore file using the MEW CX Chrome plugin. I also put the password in a text file, then configured the .sethrc file to unlock the account and use it via my Infura project URL. Needless to say, I don’t use this account for anything of value, and don’t recommend you do this with production keys.

Creating the set

I literally spent hours trying to figure out how to call this transaction to create the set. Most of my time was spent trying to get things working on Etherscan, but I wasn’t quite sure how to call the contract arguments. First, let’s take a look at the function call parameters. Per the documentation:

function create(
    address[] memory _components,
    int256[] memory _units,
    address[] memory _modules,
    address _manager,
    string memory _name,
    string memory _symbol
)
    external
    returns (address)

Most of this is pretty easy to understand: _components is an array of the tokens in the set, _modules are the components of the Set Protocol that the set needs to operate. _manager, _name and _symbol don’t need any explanation. But what about _units? The docs define it as “the notional amount of each component in the starting allocation”, but the word notional doesn’t really have a definition that makes sense to me in a programming context.

So let’s take a look at the SetProtocol UI to see how this works.

To start with, let’s create a set with one-hundred percent allocation of USDC. Let’s set the Set price to one dollar. I’m calling it the “One Dollar Set”, and the token to 1USD. We can grab the hex data from the Metamask confirmation prompt, and throw it in this Ethereum input data decoder. For this contract, you can get the ABI from the Etherscan page, but for unverified ones you may need to compile it yourself.

Here’s how we can do that programmatically using seth:

$ export CREATE_SIGNATURE="create(address[],int256[],address[],address,string,string)"
$ export ONE_USD="0xa949dc3e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000d82cac867d8d08e880cd30c379e79d9e48876b8b00000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f7a7d0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d8ef3cace8b4907117a45b0b125c68560532f94d00000000000000000000000090f765f63e7dc5ae97d6c576bf693fb6af41c12900000000000000000000000008f866c74205617b6f3903ef481798eced10cdec000000000000000000000000000000000000000000000000000000000000000e4f6e6520446f6c6c61722053657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043155534400000000000000000000000000000000000000000000000000000000"

0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48  // USDC token address
1014397  // 'nominal' amount
0xd8EF3cACe8b4907117a45B0b125c68560532F94D,0x90F765F63E7DC5aE97d6c576BF693FB6AF41C129,0x08f866c74205617B6F3903EF481798EcED10cDEC // tokenset modules
0xd82Cac867d8D08E880Cd30C379e79d9e48876b8b // my dev address
One Dollar Set // name
1USD //symbol

So let’s take a look at this nominal amount. The documentation doesn’t really explain it, but I did some experimenting to see what the values come out to.

AllocationStarting PriceHexDecimal
100% USDC$1f4b2e1,000,286
$1098efce10,022,862
$1005f5e100100,000,000
$10003b9aca001,000,000,000
50/50 USDC/USDT$17a120500,000
$104c4b405,000,000

The single asset one and ten dollar prices seem to be anomalies, I’m guessing due to precision errors or something. Let’s look at a more realistic mix of a Set with an allocation between wBTC, wETH, USDC and DPI token:

Starting PriceTokenHexDecimal
$10wBTC14c65318
wETH524a299c0f0f11,447,655,666,413,809
USDC2634472503751
DPI1658cfe35c0f546,290,099,383,570,260
$100wBTCcfb853,176
wETH336757534418dd14,468,848,569,030,877
USDC17dd05125,022,545
DPIdf5708b80c3c0c62,864,614,765,640,716

So what we’ve determined here is that the decimal numbers correspond to the fractional portion of the various tokens in USD. For example, the value 5318 for BTC corresponds to 0.00005318 BTC, with BTC at $48k, corresponds to approximately $2.50 worth of BTC.

It seems that the TokenSet UI uses their an oracle system to determine these weights, based on the allocation and opening price given. One could compute these manually, or copy the values from the TokenSet UI as I did here. Just remember that the nominal value of each token you have in your set will determine the USD price. For practical reasons regarding issuance, you might want to consider starting with a single component, such as USDC, wETH or wBTC.

Deploying our set

The TokenSet UI creates new Sets with the following modules: basic issuance, trade module, and streaming fee. The basic issuance requires issuers to have the correct ratio of the Set’s inputs, and also requires approval for each spend. It is very expensive to do this. For this reason we want to use the NAV module, which allows users to deposit tokens using a single asset. However, the NAV module only supports issuance with assets that are supported using SetProtocol’s on-chain oracles, and these are limited. (More on this in our next post.)

Using Etherscan

One of the big problems I had trying to pass these parameters in via Etherscan was how to encode them the values. Eventually, with some help from a Set team member, I figured out that arrays of addresses, such as those for the component assets and modules, need to be enclosed in quotes, without the “0x” prefix intact. The int256 array for the component amounts need to be in hex form, with the 0x prefix intact. Here’s how it looks on Etherscan:

You can see the result of this transaction on Etherscan. The total gas used was 3,308,683. That’s about 0.13ETH at 40 gwei, but I doubt I’ll be able to get a tx through at that price given recent prices. Earlier testing on the UI actually showed a price around three thousand dollars last night when gas was closer to 400 gwei. I believe that Set creation is not a time sensitive process like trading on Uniswap, so we can try to sneak by with a lower cost gas fee if we want to.

Using SETH

export ETH_FROM=$(seth accounts | head -n1 | awk '{ print $1 }')
export ZERO=0x0000000000000000000000000000000000000000000000000000000000000000

export WEENUS=0xaFF4481D10270F50f203E0763e2597776068CBc5
export YEENUS=0xc6fDe3FD2Cc2b173aEC24cc3f267cb3Cd78a26B7
export XEENUS=0x022E292b44B5a146F2e8ee36Ff44D3dd863C915c
export ZEENUS=0x1f9061B953bBa0E36BF50F21876132DcF276fC6e

export SET_TOKEN_CREATOR=0xB24F7367ee8efcB5EAbe4491B42fA222EC68d411
export NAV_ISSUANCE_MODULE=0x5dB52450a8C0eb5e0B777D4e08d7A93dA5a9c848
export STREAMING_FEE_MODULE=0xE038E59DEEC8657d105B6a3Fb5040b3a6189Dd51
export TRADE_MODULE=0xC93c8CDE0eDf4963ea1eea156099B285A945210a

export CREATE_SIGNATURE="create(address[],int256[],address[],address,string,string)"
export COMPONENTS=[$WEENUS,$XEENUS,$YEENUS,$ZEENUS]
export UNITS=["0x1","0x1","0x1","0x1"]
export MODULES=[$NAV_ISSUANCE_MODULE,$STREAMING_FEE_MODULE,$TRADE_MODULE]
export NAME='"TEST"'
export SYMBOL='"TEST24"'

seth send $SET_TOKEN_CREATOR $CREATE_SIGNATURE $COMPONENTS $UNITS $MODULES $ETH_FROM $NAME $SYMBOL --gas=4000000

seth-send: Published transaction with 772 bytes of calldata.
seth-send: 0xc12a5402ff37e114d8951fef756ab6985e6387b0e5d74e8c6ee5b83913077a86
seth-send: Waiting for transaction receipt...........
seth-send: Transaction included in block 23634932.

Here, we are using export to create bash variables to make our code more readable. We set our own address $ETH_FROM, as well as the zero address for use later, then create vars for the components in our Set, WEENUS et al, the Set creator contract, as well as the modules that we’ll have in our set. We provide the signature for the create function, then bundle our parameters together before sending the transaction with four million gas.

Note that we could use the seth estimate function to get a fairly accurate measure of the actual gas needed:

seth estimate $SET_TOKEN_CREATOR $CREATE_SIGNATURE $COMPONENTS $UNITS $MODULES $ETH_FROM $NAME $SYMBOL --gas=4000000 
3308707

This is exactly how much gas was used by our actual Set creation transaction.

Using web3

Jacob Abiola was gracious enough to create this SetTokenCreator-boilerplate repo for me, showing how to create a Set using a Javascript file and web3 via Infura and Metamask.

Where’s my Set?

If you look at the internal transactions for the set creation call that we just minted, you’ll see the create call is made on a brand new contract. The one below, starting with 0x902d1ce… is our new $TEST24 token on Kovan.

On our next post, we’ll take a look at some of the challenges around issuing tokens. The basic and NAV issuance modules are very misunderstood, and we’ve had many requests from people asking how we’re dealing with it with the $MUG token.

Set Protocol for defi fund management

Over the years, I’ve been setting aside a small amount of cash for my daughters’ savings. A few bucks a week that I can use to teach them about money. My wife has been contributing to their 529 college savings plans, but I feel it’s better to give them the opportunity to learn investing and have funds available for entrepreneur activities, so I’ve been building up accounts for them in the hopes that I can involve them in the money management when they turn thirteen or so, before handing over the funds entirely when they turn eighteen.

When I first started, I decided to open LendingClub accounts for them, since the rates were much better than than standard savings accounts. At some point over the last three years, I decided to stop contributing to those accounts, and started putting the money into bitcoin instead. The LendingClub loans have three year repayment terms, so most of the outstanding notes have yet to be paid back. So once a month, I’ve been withdrawing the cash from LendingClub, into my bank account, and from there into their BlockFi accounts where the USD earns interest along with the BTC that I’ve bought for them.

As I’ve gotten more comfortable with DeFi, I’ve been moving USD and BTC funds from BlockFi accounts over to various yield farms, Yearn, mostly, but for the past week I have a significant amount of BTC wrapped and staked on BadgerDAO. More on that later. The issue that I’m having is that the funds are mixed, and tracking allocations between the various earmarks, as well as gas fees, has become a huge pain. I’ve been trying to keep track within a Notion sheet, but tracking who’s got what quantity of funds deposited and staked in this, that or the other pool is an obstacle.

The main reason for the commingling of funds is that Ethereum gas prices are making contract interactions with these farms cost prohibitive, and the problem is only going to get worse after $ETH breaks price discovery and goes 2x or more. A few months ago, when ETH was trading at three or four hundred dollars, I would have told you that it’s wasn’t worth doing yield farming unless you had a thousand dollars to put in for three months. Now, three months later, with ETH at $1400, I’d say that lower bound is up to five grand, probably really twice that when it comes down to entry and exit fees. Ethereum is quickly becoming a whale’s game.

The best solution that I’ve come across thus far has been Set Protocol. A Set is a basket of ETH and ERC tokens. The Set manager adds tokens and various strategies, and then users can buy into the Set to get access to the basket. Set Protocol is what powers TokenSets, which powers the DeFi Pulse Index ($DPI), a market-cap weighted index fund of DeFi tokens. (I’m very long on DPI). TokenSets has a limited number of funds available, as they go through a vetting process, but anyone can create their own Set using Set Protocol.

It’s a bit complicated right now, and not very user friendly as they have no UI, (yet,) but is seem like it might be an option for me to make a basic index fund. There are some margin opportunities, but unfortunately it doesn’t have any modules that support staking funds in liquidity pools, or participating in yield farms. That may change soon, and I’ll find out more when I talk with one of the co-founders tomorrow. Having my own Set will allow me to track the number of my Set’s ERC20 that belong to each family member, all I have to do is deposit USDC. Then once a quarter or so, I can reallocate the funds within whichever project I choose. And the best part, is that I can allow others to buy into the Set, permissionlessly.