Git Product home page Git Product logo

swap-swear-and-swindle's Introduction

sw3 contracts

Contracts for Swap, Swear and Swindle.

Please note that all contracts within this repository are considered highly experimental and may cause loss of funds if used in production.

The master branch only contains the SimpleSwap contract for now. Everything else (full Swap, Swear and Swindle) can be found in the experimental branch.

Tests

This is a hardhat project using the truffle plugin (for tests as this used to be truffle-based). You can run tests using yarn test.

yarn
yarn test

To also generate coverage information use yarn coverage instead.

Linting

This repo currently uses solhint as linter. It can be called through yarn:

yarn lint

Go-bindings

To generate go bindings use

yarn abigen

This will generate the bindings in the bindings/ directory. Suitable versions of solc and abigen have to be installed for this to work. Alternatively this can also be done through docker:

docker build -t sw3 -f Dockerfile.abigen .
docker run -v $(pwd)/bindings:/sw3/bindings sw3 yarn abigen

In addition to the file from abigen this will also generate a go file that includes the runtime bytecode.

The go bindings are automatically generated on every release git tag and the pushed to the ethersphere/go-sw3-abi repository.

Deployments

Swap is deployed on the following networks:

Network Factory Token
Mainnet - 0x19062190B1925b5b6689D7073fDfC8c2976EF8Cb
XDai 0xc2d5a532cf69aa9a1378737d8ccdef884b6e7420 0xdbf3ea6f5bee45c02255b2c26a16f300502f68da (bridged)

Test Deployments

Swap is deployed on the following testnets:

Network Factory Token
Sepolia 0x0fF044F6bB4F684a5A149B46D7eC03ea659F98A1 0x543dDb01Ba47acB11de34891cD86B675F04840db

Overview

SimpleSwap

SimpleSwap is a chequebook-style contract with support hard deposits.

Cheques

The issuer can issue cheques. Those are a signed piece of data containing the swap address, a beneficiary, and a cumulative amount. If the beneficiary wishes to cash the cheque it needs to be sent to the contract using the cashChequeBeneficiary function. Alternatively anyone else can also cash the cheque using cashCheque provided they have a signature from the beneficiary. In that case they might also get a portion of the payout as a fee. If there is not enough liquid balance in the contract part of the cheque might bounce (whether the full cheque was paid out should be verified through the ChequeCashed event). Later the beneficiary can try cashing again to get the remaining amount.

Hard Deposit

The issuer can lock a certain amount of the balance to a specific beneficiary (increaseHardDeposit) to give solvency guarantees up to the amount of the hard deposit. Decreasing a hard deposit is a two step process: First it needs to be prepared (prepareDecreaseHardDeposit) to start a security delay, which the beneficiary can use to cash the outstanding cheques. Afterwards the deposit can be decreased (decreaseHardDeposit). The balance not covered by hard deposits can be withdrawn by the issuer at any time.

Data Formats

Signatures

For signing purposes the chequebook uses EIP-712 Ethereum typed structured data hashing and signing. The EIP712Domain domain name is Chequebook in version 1.0. The chainId field is used, the verifyingContract and salt fields are omitted.

Cheques

Field Type Description
swap address  the swap contract this is for
beneficiary address  beneficiary of the cheque
cumulativePayout uint256 cumulative amount

CashOut

Field Type Description
swap address  the swap contract this is for
sender address the address allowed to submit this cheque
requestPayout uint256 the maximum amount that should be paid out
recipient address the target of the payment
calleePayout uint256 amount of the payout that should go the caller

CustomHardDepositDecreaseTimeout

Field Type Description
swap address  the swap contract this is for
beneficiary address  beneficiary of the hard deposit
decreaseTimeout uint256 new timeout

Factory

SimpleSwap has an accompanying factory contract SimpleSwapFactory. Deploying through the factory guarantees that the SimpleSwap contract was deployed with the correct init code.

Swap

Swap is SimpleSwap extended with support for promissory notes. You can find it in the experimental branch.

Swear and Swindle

Swear and Swindle are the contracts for the trial system of sw3. You can find them in the experimental branch.

Releasing

To release a new stable version, tag the commit without the -rcX suffix. For example, to release v0.4.0, execute the following command: git tag v0.4.0 && git push origin v0.4.0. This will generate Golang source code for the smart contracts and publish it to the ethersphere/go-sw3-abi/ repository.

swap-swear-and-swindle's People

Contributors

dependabot[bot] avatar eknir avatar n00b21337 avatar orenyodfat avatar ralph-pichler avatar skylenet avatar vandot 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

Watchers

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

swap-swear-and-swindle's Issues

abstract the swear/case/swindle contract to handle polymorphic evidence

Viktor :
a swear is a case state transition automata, where at each stage of the litigation, a witness contract is called with the same ABI: testimonyFor(status, serviceId, clientAddress) -> newstatus
and it is this contracts specific methods which you need to call to submit the evidence
this givesa a superclean and superlean swear abstraction.
Oren:
I like the idea.
so in the basic “mirror” game there will be two 2 expert witnesses .
First one , which validate and confirm the client subscription to the service by validate the service promise ,lets call it “SubscriptionWitness”.
It introduce an abi for clients to submit a “promise” as an evident.
Second , which check the actual mirroring staff by resolving both enss and compare them ,lets call it “MirrorWitness” .
For the case of the “mirror” game the client do not need to submit any evident because it the enss addresses are hard coded in the contract.
So the swear contract will call SubscriptionWitness.testimoryFor(status, serviceId, clientAddress) and if the status is OK it will call “MirrorWitness.testimoryFor(status, serviceId, clientAddress) ” and take decision according to that..
Further abstraction can be done by having the passing the swear contrat a list of witnesses contract addresses , so it then can iterate through each :
e.g
for (i=0;i<numberOfWitnesses;i++)
{
status = witness[i].testimoryFor(status, serviceId, clientAddress)
if status != STATUS_OK{
return status
}
}
return status

Create SimplestSwap.sol

Related to the discussion at SwarmResearch.
This issue removes anything related to waivers and means a simplification on both the smart-contract side as well as the side that implements the chequebook smart-contract.

don't store swap note fields to storage

By always submitting the note (in cashNote and submitPaidInvoice) the storage footprint (and hence gas cost) could be drastically reduced.

A first attempt at this can be found in #13

Rename availableBalanceFor

AvailableBalance is used on the go-side to calculate the balance against which cheques can be written without risking a ChequeBounced event.

Automatic Go Bindings

As discussed during a roundtable we should look into automatically generating go binding here using CI so it can be used on the go side as a vendored dependency.

Timeout confusing

The parameter timeout is confusing. At some places, it is used as an absolute point after which something can happen. At some places, timeout means a relative time (now + timeout) after which something can happen.
I propose to stick to timeout for the relative time, but consider a different name for the absolute time.

Using the newest version of openZeppelin solidity

Upgrading to the newest version of openzeppelin Solidity breaks the smart-contract when deployed on Ganache.
Reason: Ganache does not inject the correct value for v. (0 or 1, instead of 27 or 28).

Current solution in place: Use openzepplinSolidity version: 2.1.2
Desired solution: make the repository compatible with the newest version of openzeppelin solidity.

ERC20 integration

  1. Make chequebook ERC20-compatible
  2. Adapt ABIGEN script / CI script en push go-bindings to a different repo
  3. Make Swarm source-code work with ERC20 compatible go-bindings

Enable client to submit a signed "promise" from a service as an evident

// promise represents a promise from a service to serve client(beneficial) up to a certain blockNumber
type Promise struct {
Contract common.Address // address of swearGame contract, needed to avoid cross-contract submission
Beneficiary common.Address // address of Beneficiary (client)
BlockNumber *big.Int // Until which block number this promise is valid
Sig []byte // signature Sign(Keccak256(contract, beneficiary, blocknumber), prvKey)
}

Use go modules for the go-sw3 library

Description

Currently the build/CI process automatically creates a separate folder for a new version of the S/S/S contracts.

Use a go module with a major version update for a more idiomatic way to reference the generated code.

add license headers

Running yarn compile will show warning messages, warning that there are no license headers. Resolve this and add appropriate license headers (similar license as our bee repo).

Wrong factory and token contract

Hi, in the documentation this address: 0xA6B88705036F2a56807af157c116b7dfCDabf968 is said to be the default factory using this token address: 0xe1927106821DB21c8657B8EB483705E95903eE93

But the bee clients are currently setting this address: 0xf0277CAFfea72734853B834AFC9892461eA18474 as the default factory contract and this address 0x2aC3c1d3e24b45c6C310534Bc2Dd84B5ed576335 as the token contract.

Here is the bee code that set the factory: https://github.com/ethersphere/bee/blob/master/pkg/settlement/swap/chequebook/factory.go#L172

Which one is the correct? If is the latter, could you also validate the contract code in etherscan? https://goerli.etherscan.io/address/0x2ac3c1d3e24b45c6c310534bc2dd84b5ed576335#code

Automatically setting hard-deposits with peers

When reviewing the SimpleSwap.sol code with @holisticode , we came up with a potential vulnerability of SimpleSwap. If exploited, an attacker can lock the funds of the checkbook owner for a given period (equal to the hardDeposit timeout), resulting in the checkbook owner not being able to economically engage with other nodes for this period.

Assuming:

  • Harddeposits are the only way to guarantee solvency of the checkbook for a node
  • A node requires solvency of a checkbook to in order to engage in the SWAP protocol (start delivering chunks back and forth)*

Then:
For a honest node who expects to receive a check (A) and does not want a profit that approaches zero, this node first wants to see a hard-deposit guaranteed for him in the checkbook of a peer (B).
As B wants to start using SWARM, he has to commit himself to funding set a hard deposit aside for at least one (but probably multiple peers).

Attack:
Evil node C tricks B into believing that he/she needs a hard-deposit. C can have multiple nodes and the cumulative hard-deposits to all C's can be sufficiently high such that B cannot engage in Swarm anymore without the expected service of C, without topping up again. When this point is reached (can be a very little time if C sets up the attack well), C can stop providing services for B and B has to wait for a period equal to the hardDepositTimeout until she can engage again in SWAP with other nodes. This circle can repeat ad-infinitum.

Consequence:
The attack can disrupt the usability of SWARM for B as it will diminish the resources that B has available from his deposit to spend on rewarding honest nodes at any given time.

*If there is no solvency guarantee, a node should always expect a bankrun on the checkbook of the peer as there is no way of knowing about other outstanding checks. Therefore, once a node has a cheque that is worth a positive sum of money, he should immediately cash out this cheque. A cheques worth is the cumulative value of the check - the gas costs of the cheque. We expect the worth to be negative initially and when the worth is marginally above zero it should be cashed out due to the logic above.

drop submitCheque and make sure this is safe for the owner

submitChequeLower supposedly can do everything which submitCheque can do as well. For code clarity, we can drop submitCheque and rename submitChequeLower to submitCheque.

We have to gather sufficient reasoning on the safety of dropping this function (no party should be able to game the other party), as well as a gas-cost analysis.

use swap notes logic for cheques

The cheque logic is currently completely separate from the notes logic. Notes also can be used for simple cheques (only value, beneficiary fields), but unlike cheques these notes cannot be replaced with higher index notes.

The cheque-specific logic could probably be dropped if #11 is implemented.

use index for cheque-like replacement in swap

Currently the index field is only used as a kind of nonce. There might be a way to have a replacement mechanism similar to cheques, although it is not yet clear how this would work in detail.

Think about agent / principle naming

Currently, we name the person receiving payment during submitCheque the beneficiaryAgent, whereas the beneficiary (Externally owned account) is the beneficiaryPrincipal. This might not be the best naming, let's think about it.

Branch management

Master will be for now for simpleSwap.sol + tests.
We create a branch "experimental" where we put all experimental code for the SW3 suite. When one feature is sufficiently tested and stable, we merge this feature from experimental to master.

Documentation update

Update the README.md of this directory to reflect the current state of the smart-contracts

Parameter orders in cheqeuHash function / keccak256 hash in body of function

Order of parameters in function cheqeuHash does not match the order of these parameters in the keccak256 hash.
Proposal: change the order of parameters in the function or change the order of parameters in the keccak256 hash in the body of this function.

  public pure returns (bytes32) {
    return keccak256(abi.encodePacked(swap, serial, beneficiary, amount, timeout));
  }```


decreaseHardDeposit

If there is a cash-out in between the prepareDecreaseHardDeposit and decreaseHardDeposit, the line
hardDeposit.amount = hardDeposit.amount.sub(hardDeposit.decreaseAmount); in decreaseHardDeposit might throw and decreasing the hardDeposit can be effectively blocked temporarily.
Proposed solution: if decreaseAmount is more than amount, set the hardDeposits to 0.
As an extra benefit: this makes the require(decreaseAmount <= hardDeposit.amount) in prepareDecreaseHardDeposit redundant.
@ralph-pichler

Global paidOut

The Swarm codebase has a need for a global paidOut call. Without this call, calculating availableBalance on the go-side requires a paidOut(peer) call for every peer and historical peer to the chequebook, which might grow to a substantial size when Swarm is longer-running.

Increasing serial

Currently, SimpleSwap.sol requires only that a cheque has an increasing serial number. If nodes just randomly increment the serial of every cheque with a number, the MAX_UINT of Solidity can be reached quickly and a cheque cannot be updated anymore, only cashed out.

The node's software should not sign cheques with a serial that is increasing with more than one from the last known cheque of this node.
@holisticode , where should we document such details?

_computePayout

The _computePayout function could be structured more simply.

Swear contract design

Problem: The current SWEAR design seems like it could be simplified. When I was reading through the orange papers, I came up with a design for a SWEAR deposit system (the name may be incorrect) that could look like this. With this design you can keep deposits moving through indefinitely and attach other modules that rely on information regarding deposits to different nodes. Keep in mind this is just an abstract sketch.

pragma solidity >= 0.4.13;

contract SWEAR {
    
    uint swarmEpoch = 3 days;
    
    mapping(address=>Deposit) public deposits;
    
    struct Deposit {
        bool inDepositPeriod;
        uint vestingPeriod;
        uint depositedAmount;
    }
    
    function() {
        revert();
    }
    
    function register(uint epochs) payable returns (bool) {
        if (!deposits[msg.sender].inDepositPeriod) {
            deposits[msg.sender] = Deposit({inDepositPeriod: true, vestingPeriod: now + epochs * swarmEpoch, depositedAmount: msg.value});
            return true;
        }
        if (msg.value > 0) { revert(); }
        // can't reregister, return false telling node that it cannot alter its deposit
        return false;
    }
    
    function collectDeposit() external returns (bool) {
        Deposit storage depositInfo = deposits[msg.sender];
        if (depositInfo.inDepositPeriod && depositInfo.vestingPeriod <= now) {
            uint toTransfer = depositInfo.depositedAmount;
            deposits[msg.sender] = Deposit(false, 0, 0);
            msg.sender.transfer(toTransfer);
            return true;
        }
        return false;
    }
}

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.