Giter Club home page Giter Club logo

set-protocol-contracts's People

Contributors

0xzick avatar asoong avatar brian-biometrix avatar bweick avatar dependabot[bot] avatar felix2feng avatar fvictorio avatar hydrazines avatar inje avatar jaytoday avatar justinkchen avatar kermankohli avatar richardliang avatar rootulp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

set-protocol-contracts's Issues

Create Uniswap Exchange Wrapper

Summary

Integrate Uniswap as a liquidity provider for Set issuance orders by creating an Exchange Wrapper contract similar to what we have done with 0x and Kyber.

Implementation

Our exchanges wrappers expose a single public function exchange which implements the necessary logic behind the exchange protocol. Our current exchange wrapper implementations are here for reference.

In the case of Uniswap, there are 3 functions that will execute the swap: 1) ethToTokenSwapInput to swap ETH with ERC-20 Tokens, 2) tokenToEthSwapInput to swap ERC-20 Tokens with ETH, and 3) tokenToTokenSwapInput to swap ERC-20 Tokens with ERC-20 Tokens. More information on the Solidity interface here. Each function above takes in a number of parameters as specified in the interface. The Uniswap frontend code shows how these 3 functions work.

The exchange function should:

  1. check allowance for transfer
  2. parse order data from the Set issuance order
  3. execute ethToTokenSwapInput, tokenToEthSwapInput, or tokenToTokenSwapInput depending on ETH or ERC-20 swap
  4. transfer unused maker token back to the issuance order user

A good source of reference is how we've implemented our exchange wrappers linked above. Feel free to discuss with us further on Telegram!

Tests failing with Invalid JSON RPC response

To Repro:

  1. Run yarn run chain
  2. In another terminal yarn run test

I'm on master at commit ffc256e. I realize that's a bit behind this repo, but am unable to re-run the test

.....
  269 passing (8m)
  8 failing

  1) Contract: RebalancingSetTokenFactory
       "before each" hook:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

  2) Contract: RebalancingSetToken
       "before each" hook:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

  3) Contract: RebalancingSetToken
       "after each" hook:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

  4) Contract: Core
       "before all" hook: prepare suite:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

  5) Contract: Authorizable
       "before all" hook: prepare suite:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

  6) Contract: ERC20WrapperMock
       "before all" hook: prepare suite:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

  7) Contract: Bytes32Mock
       "before all" hook: prepare suite:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

  8) Contract: CommonMathMock
       "before all" hook: prepare suite:
     Uncaught Error: Invalid JSON RPC response: ""
      at Object.InvalidResponse (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/errors.js:35:16)
      at XMLHttpRequest.request.onreadystatechange (node_modules/truffle-hdwallet-provider/node_modules/web3/lib/web3/httpprovider.js:115:32)
      at XMLHttpRequestEventTarget.dispatchEvent (node_modules/xhr2/lib/xhr2.js:64:18)
      at XMLHttpRequest._setReadyState (node_modules/xhr2/lib/xhr2.js:354:12)
      at XMLHttpRequest._onHttpRequestError (node_modules/xhr2/lib/xhr2.js:544:12)
      at ClientRequest.<anonymous> (node_modules/xhr2/lib/xhr2.js:414:24)
      at TLSSocket.socketErrorListener (_http_client.js:395:9)
      at emitErrorNT (internal/streams/destroy.js:64:8)
      at process._tickCallback (internal/process/next_tick.js:178:19)

Support Sets with Decimal Place Component Quantities

Motivation:

We need to provide more flexibility in the token quantities that can be instantiated as they currently can only be done in whole quantities. For example, we are currently able to instantiate a Set with 1x Token A and 2x Token B with whole numbers:

Deploy with the following parameters([`address_token_a`, `address_token_b`],[1, 2], 'AB_Set`, `AB`)

If the price of Token A and Token B are sufficiently different, it will require large units of Token A and Token B to achieve certain percentage splits at a clean price. In the case that Token A is $100 and Token B is $1 and we want to achieve a 50/50 split, we'd need to have 1x Token A and 100x Token B. This results in a total Set price of $200. If a user wanted to purchase $1 of a Set, they'd need to purchase 0.005 of this Set, a figure that is psychologically unappealing.

If we wanted to represent the Set at a price of $1, we need to support decimal place representations in quantities with Set instantiation. In the same example, if we wanted to represent AB_Set with the same mix and have an initial price of $1, we can instantiate the Set with 0.05 Token A when Token A is $100 and 0.5 Token B that is $1.

Solution

In solidity, the standard ERC20 token supports up to 18 decimal places. We can support the same number in a Set.

Note: We do need to be mindful of the individual components and their decimal place limitations. For example, TRON is a ERC20 token that only supports 6 decimal places.

Handling of Paused Tokens

Summary

Allow withdrawal of other tokens in a Set in the event that one or many of the Tokens have been restricted from trading.

Motivation

Some ERC20 tokens deployed with an inherited Pausable contract, which allows the Owner of the smart contract to pause transfers or other functions in the event that something goes wrong. Some ERC20 tokens that employ this functionality include: OmiseGo and Tron.

SetToken's issue and redeem functions require that all tokens in the Set are successfully transferred. Otherwise, the whole transaction will revert. If a single or many components(s) has been disabled for transferring, the issue and redeem functions will fail as the simple component transfer has failed. When this has happened, it means that no user can issue or redeem Set tokens.

If the owners of the component token decide never to unpause the tokens, the second order consequence is that the other components in the Set are locked in the smart contract as well.

Currently, the Set contract, as is, does not have a way to deal with locked tokens.

In the event that the tokens are locked, it would be nice for the participants or holders of the Set to have an emergency function that can be called that allows for the redemption of tokens that have not been locked.

Centralized Naive Solution

This can be implemented in a centralized manner assigning a Set a single Owner. The owner has the ability to make a proposal that a token has been disabled for trading and enable Set holders to redeem all tokens excluding the locked token. To implement this, we can add two functions: proposeMalfunctioningToken, emergencyRedeem, withdrawPreviouslyFrozen and keep state of which tokens have been frozen, a boolean of whether emergencyRedeem is enabled, and whether a token has been redeemed during a frozen period.

When the token gets frozen, the owner can propose a malfunctioned token. This triggers the contract's emergencyRedeem function to be called by token holders. Then users can call the emergencyRedeem function, withdrawing only the unlocked tokens. Each call of the emergencyRedeem function gets recorded in the event that the frozen token gets unfrozen in the future.

If the frozen token manages to get unfrozen in the future, the partial withdrawers will have the opportunity to withdraw the tokens using the withdrawPreviouslyFrozen function.

Decentralized Solution

Instead of enabling the retrieval of non-frozen tokens that has to be enabled, we can allow owners of Set Tokens to redeem partial Sets at any time. Once an owner has redeemed a partial Set (redeeming some of the components), that specific Set goes out of circulation. At anytime, the user can withdraw the remaining components of the Set.

Create Bancor Exchange Wrapper

Summary

Integrate Bancor as a liquidity provider for Set issuance orders by creating an Exchange Wrapper contract similar to what we have done with 0x and Kyber.

Implementation

Our exchanges wrappers expose a single public function exchange which implements the necessary logic behind the exchange protocol. Our current exchange wrapper implementations are here for reference.

In the case of Bancor, it uses the quickConvert function to execute conversion between any 2 integrated tokens on its network. The function is payable and takes in a path, the message value, and the minimum return willing to receive back.

The exchange function should:

  1. check allowance for transfer
  2. parse order data from the Set issuance order
  3. execute quickConvert
  4. transfer unused maker token back to the issuance order user

A good source of reference is how we've implemented our exchange wrappers linked above. Feel free to discuss with us further on Telegram!

Support Retrieval of Airdrops and Forks

Summary

We propose adding functionality to retrieve token airdrops and forks using a centralized scheme similar to that of temporarily freezing and allowing for retrieval tokens in a way that doesn't change the underlying composition of a Set.

In the future (when ERC820's registry is deployed and trusted), we propose utilizing the ERC777's ERC777TokensRecipient as a hook to capture non-component tokens sent to the contract and allow retrieval through a withdrawal function by the end user.

Motivation

If Sets are to become an attractive investment vehicle, we envision that participants holding Sets need to be able to take advantage of airdrops and hard forks that accrue to the smart contract. Currently, tokens such as OmiseGo that are airdropped to the SetToken are forever lost, as the contract does not have a way to handle retrieval of these tokens. These strategies of taking advantage of airdrops are already being implemented in centralized index fund strategies such as Bitwise's Hold10 and Coinbase's Index.

Centralized Naive Solution

A centralized naive solution would involve the Owner of the Set initiating a proposal that an airdrop has occurred. The smart contract can check that the token proposed is not a component token and that the balance of that token is indeed non-zero. If the proposal is accepted, the airdropped tokens will be distributed equally within all existing SetToken holders.

Snapshotting

One complication is that the supply of SetToken's can be adjusted based on issuances and redemptions. If a Token Airdrop occurred at T0 for X number of tokens, then only the holders at that time should benefit / or at least at the proposal time. If we were only to attribute the Airdrop to those tokenholders, then we would need some sort of snapshotting mechanism on-chain to know which Set Holders indeed owned the tokens at the time of the airdrop proposal.

Note: This feature is still WIP.

Future Implementation (ERC777)

ERC777 is proposed to become Ethereum's new token standard and makes significant improvements upon the shortcomings of ERC20. One of which is the ability to allow Token Contracts to handle tokens sent to the contract via a ERC777TokensRecipient hook that must be called if an ERC777 token is to send a token to another ERC777 contract.

With a Set that wants to take advantage of an airdrop, it becomes as trivial as ensuring that non-component tokens sent to the contract automatically becomes retrievable by the SetToken holder.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.