Coder Social home page Coder Social logo

marcoonroad / instrumental Goto Github PK

View Code? Open in Web Editor NEW
1.0 2.0 0.0 1.5 MB

Financial Instruments encoded as Smart Contracts. :moneybag: :bank: :chart_with_upwards_trend: :tulip: [Work In Progress]

License: MIT License

Shell 0.78% JavaScript 73.51% Solidity 25.71%
smart-contracts ethereum solidity financial-instruments financial-markets banking-applications

instrumental's Introduction

instrumental

Financial Instruments encoded as Smart Contracts.


Roadmap of Contracts

  • Authorization Hold (in-escrow, multisig contract)
  • Anticipation/Purchase of Receivables
  • Auction
  • Split (PoS/Gateway) Payment - Fan-in
  • Payables-Receivables Apportionment/Allocation - Fan-out
  • Loyalty/Cashback Reward Program (using MDR from Merchant Account)
  • Coin Flip/Toss, Commit-Reveal-based Lottery / Public RNG
  • Derivatives (futures, forwards, swaps and options)

Notes: The financial instruments regarding receivables will likely demand a proper Risk management/analysis. Also, for the derivative contracts, an Oracle to feed real-time market prices is needed as well (although on tests it could be mocked without any problem).

instrumental's People

Contributors

dependabot[bot] avatar marcoonroad avatar

Stargazers

 avatar

Watchers

 avatar  avatar

instrumental's Issues

Replace Clock contract instances by abstract Clock contract

Related to #4. Creating a single and sole contract to just track one variable / attribute, without any encapsulated business logic and business invariants, is non-sense. It impacts our application with huge costs associated with the contract creation instruction (and its underlying gas consumption).

A better alternative would be to make the Clock contract abstract, and then clients inherit from it. In this way, the Clock contract's API / methods can be still preserved, somehow, we will just need to pass the sender's address into every call and make such methods private (they will be just called internally within the contract itself, this is to prevent malicious players from affecting internal clock / timing logic).

Remove Transaction Fees on Tests

Without transaction fees, we can assert properly account and contract balances. Likewise, our tests would cover a wide range of cases for our smart contracts.

With the Ethereum's Web3 API, it's just a matter to provide the following option on transaction calls:

const txMethod = await contract.method(..., {
  ..., // some options here, and finally
  gasPrice: 0
});

It would be useful, tho, to run integration tests on Ethereum test networks (Rinkeby, Ropsten, Kovan, etc). Therefore, transaction fees here would make a huge sense. In this case, we must allow a predefined transaction fee per test network, or having a separated test suite for that. Anyways, it's just a matter for other issue. 😄

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

Global Clock (Testing / Mocking / Development Contract)

Related to issue #28.

Our current time-dependent logic relies on non-standard Ganache instructions such as evm_increaseTime and evm_mine (see the piece of code below). It doesn't scale to multiple contracts, as is the case for my Hold and Loyalty tests breaking due the sole addition of an Auction contract. Such black magic / workaround doesn't allow to go backwards in time, neither to undo the time travels forward in time.

const jsonrpc = '2.0'
const id = 0
const send = (method, params = []) =>
web3.currentProvider.send({ id, jsonrpc, method, params })
const timeTravel = async seconds => {
await send('evm_increaseTime', [seconds])
await send('evm_mine')
}

A good approach would be to deploy a Global Clock Contract. This contract would be a Singleton (in Ganache, it's possible to interact with the migrated / deployed contract on tests). A flag to describe either the development or production mode would be needed as well. The development mode of this contract allows to one owner to either forward or backward the clock for a given sender / caller (in the case, the contract relying on the current timestamp). So, the implementation carries 2 mappings from addresses to uint256 values. The first mapping is the amount to forward in time over block.timestamp, while the latter is the amount to backward (i.e, subtract) from block.timestamp.

Clients / users can rely and trust all of the contracts of this library whenever the Global Clock is deployed with the production mode. Otherwise, they must not interact with the contracts deployed, 'cause a malicious party could break the rules regarding the contracts (only if he has the authority to change the Global Clock).

To help us to hold such time invariant on the JavaScript / integration test side as well, the good library timekeeper could be used too. The possible sketch for the test support API could be:

await timeTravel(seconds, targetContract.address, async () => {
  // internal logic dealing with the contract <targetContract>
})

Where before the asynchronous block call, we forwards the time for the targetContract by seconds, and after the block call, we backwards the time by seconds for this contract, no matter if the asynchronous block call resolved with a value or rejected with a reason (that backward action could be regarded as a cleanup).

One Clock contract instance per Loyalty Club member/customer

The Loyalty contract uses a single Clock for everything. But the claimed at date for every customer/member is different. Thus:

This contract now disallows the multiple interactions with itself in a single, mined block.
That is, customers can't pay or cashback the merchant's loyalty contract on the same
mined block.

It's a huge, critical bug. The solution is to provide a local, per customer Clock contract instance. It would also be useful to cover multiple clients/customers interactions with such Loyalty contract on tests.


To close this issue, the following steps are needed:

  • Implement a Clock instance per Loyalty customer/member
  • Cover multiple client interactions on Loyalty contract test cases

Confusion about Escrows and Holds

The funding of the escrow contract must be called before the approval/authorization, while the funding and approval of the hold contract are at same time. After that escrow funding, the customer has some pending period to either approve or reject the escrow funds' transfer (in our pull-based payment design to avoid reentrance and out-of-gas attacks, the allowance of the seller to charge/claim the escrow contract's funds). In this sense, pre authorizations aren't quite an in-escrow mechanism. Therefore, we need a distinct contract for that, called Escrow (and remove from the documentation anything which relates Holds to Escrows as well).

Holds are used on Rent Services (for example, cars renting), where there's a gap between the Payment Authorization and the Payment Settlement. And due that, the charged value (that is, the cost) may change significantly due the time lapses (and due such price volatility based on time, derivatives were invented away). Therefore, the merchant can charge a higher value for safety, and settle a lower value if the rent service is terminated before the expiration date. Here the merchant creates the contract and define an estimated value. It's akin to the merchant putting a hold on our credit card.

Escrow mechanisms are used to protect parties from each other. For instance, they protect the buyer from frauds and the seller from chargebacks. Here, the buyer funds the escrow contract, and after the product is delivered, the buyer approves/confirms the purchase, allowing the seller to claim/settle such escrow's funds. Here, the customer/buyer creates the contract to lock his funds as a proof for the merchant. It's akin to the customer buying on the internet and making the payment through a gateway.


(Further discussion may be needed on that...)

Cleanup of Solidity Linters Warnings

Warnings from Solidity Linters are polluting our build logs. Both Solhint & Solium linters are complaining about the same thing (mostly): our Smart Contracts relying on time.

solidity-linters-warnings

'Cause we're depending on a time drift greater than 30 seconds, it's safe following the Consensys recommendations on timestamp dependence.

Nevertheless, the warnings are still there. The most good solution would be to deploy/migrate a helper contract for timestamp dependence. Therefore, we don't depend anymore to block data directly, only indirectly on this contract by contract calls. This is a huge improvement and fewer warnings would be generated. We can even assert on this Clock Contract that callers don't depend on a 30 seconds time drift, otherwise, we throw everything by revert the transaction.

Another issue is error messages for require. Solium is often complaining about that. With error messages, we can test effectively the negative cases, that is, we can assert that our code fails with the due/expected exceptions/failures instead corner cases where it's failing by other reasons - and it's not rare when our contract interacts with other contracts on the network...


So, we have the following steps to perform:

  • A Clock contract for reliable timestamp (30-seconds time-drift safe).
  • Proper messages/reasons on require calls and coverage for that on tests as well.

Ambiguous Split Payments Definitions

Just a thought. On the PoS / Gateway world, Split payments mean multiple sources of the payments, that is, the customer, can use many means to perform a single payment. For instance, the customer can pay a purchase with a Credit Card, a Discount / Gift Voucher and another Credit Card from a different issuing bank or acquirer bank.

The real complexity of PoS Split Payments lies behind handling multiple transactions as a single one. How can we ensure that between the time of authorizing payments and the store side of settling them, there's no invalid, out-of-scope state change? That is, suppose that the first mean of payment is a Debit Card. How can we ensure that the funds are still there after the last mean of payment is approved??

You may wonder, just approve-and-settle at the same time. But it has another complexity, if the last mean of payment fails (for instance, insufficient funds), the store must deal with the burden of refunds for the previous means. And fees for refunds could be really expensive!

The general implemented solution is to put a short-time hold on the mean of payment. After all the means of payments pass, the store just settle all the payment's holds. In any case of failure of a mean of payment, the store just releases all the holds associated with the payment. Keep in mind that hold is a feature implemented on banking services level.

On the other side, there's another Split Payment definition. It is associated with the Online Marketplaces, where a customer can make a purchase of diverse products, each one from many sellers and suppliers. This kind of Split is not complex, it just look on the invoice to gather all the product data, and relay the transaction for the associated sellers and suppliers. A small fee from the purchase is claimed by the Marketplace service provider.

split

Given that both definitions are different, but not exclusive, why not just merge them? I mean, let's call Split Payment a blockchain transaction made of multiple sender accounts and multiple receiver accounts. A Smart Contract for a Split Payment, so, would deal with such merged definition. In this Smart Contract, a Marketplace account (which claims fees after the checkout) inputs product data and track sellers, while, on the same time, accepts multiple sources of payment from a given client.

To avoid subtle attacks here, the customer pays from different accounts, but must open an associated commitment, previously & off-chain agreed upon hashes secrets. Likewise, to protect the purchase information, the product data could be hidden as well under hashes. The Marketplace account itself could on an off-chain basis track all the associated sellers and their allocated payment parts.

(Might still need further discussion...)

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.