Skip to content

About

Proof of concept for trade finance on XDC: tokenized assets, agreements, forwards, futures, batches, portfolios and a marketplace. Foundry tests included. Not audited.

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Latest commit

 

History

128 Commits

Folders and files

Repository files navigation

XDC DeFi Instruments: Traditional finance tools as smart contract templates

build network: XDC language: Solidity status: proof of concept license: mixed

What is included · How it fits together · Try it · What is tested · Known issues

This repository explores how tools that banks and broker-dealers run today could work as automated contracts on XDC: tokenized assets, signed agreements, forwards, futures, batches of assets, portfolios and a marketplace. A broker could run these with almost no infrastructure, and users could keep custody of their portfolios and move between brokers.

Warning

These are concept templates. They have not been audited and have not run on a real network. Don't use them with real assets. See Known issues.

What is included

Contract Purpose
Asset.sol Represents commodities, securities or currencies as tokens, run by a broker
Contract.sol Agreement tied to a document hash, signed by two parties and two witnesses, with counter-proposals
DocToken.sol Registers documents as tokens
Forward.sol Forward contract: the buyer pays now and collects the asset after a set date
Future.sol Futures contract: a deposit and fee now, the price later, and a default if nobody pays in time
MultiAssetBatch.sol Holds assets from several token contracts behind one set of keys
marketplace.sol Listings, offers, auctions and escrow, forked from TronzitVeca's ERC1155-Marketplace, whose original repository is no longer online
portfolio.sol User portfolio that holds tokens and trades through marketplaces, plus a ledger of accounts
DelegatedExecutor.sol Holds funds and sends them on a user's behalf, controlled by keys
GeneralDeployer.sol Deploys contracts from bytecode and keeps a list
Macro_Contracts.sol Keeps a versioned history of a data schema. Acting on it is left to other contracts
Micro_Contracts.sol Holds rate parameters for other contracts to read

pyscripts/ has Python helpers for working with these contracts, and Documents/ has notes on individual contracts. The full article is in docs/WRITEUP.md.

How it fits together

flowchart LR
    B[Broker] -->|tokenizes| A[Asset]
    B -->|creates for a user| P[Portfolio]
    P -->|lists, buys, bids| M[Marketplace]
    A --> M
    M <-->|liquidity across brokers| M2[Another broker's marketplace]
Loading

Brokerage DApp

Diagrams of each instrument

Asset

Asset

Agreement

Agreement

Multi-asset batch

Multi-asset batch

Forward

Forward

Future

Future

Try it

git clone https://github.com/CoinClubQuincy/XDC-Defi-Instruments.git
cd XDC-Defi-Instruments
git clone --depth 1 -b v4.9.6 https://github.com/OpenZeppelin/openzeppelin-contracts lib/openzeppelin-contracts
git clone --depth 1 -b v1.9.7 https://github.com/foundry-rs/forge-std lib/forge-std
forge test

You need Foundry.

To try it on a network, use the Apothem testnet:

Network Chain ID RPC
Apothem testnet 51 https://rpc.apothem.network
XDC mainnet 50 https://rpc.xinfin.network
forge create contracts/Defi-Tools/Asset.sol:Asset --rpc-url https://rpc.apothem.network --interactive --broadcast --legacy \
  --constructor-args "https://example.com/{id}.json"

How money moves in the marketplace

Listed tokens stay with the seller until a sale, and auctioned tokens are held by the marketplace until the auction closes. Either way, the seller approves the marketplace on the token contract first. Sale money, replaced bids and fee shares wait in escrowAmount, and each person collects their own with withdrawEscrow. One recipient who can't receive money can't block a sale or an auction. Money behind an open offer is locked until the offer is accepted or cancelled.

What is tested

test/foundry has 152 tests, including 3 fuzz tests, and runs in CI on every push.

File Tests Covers
Instruments.t.sol 41 Contract, Asset, Document, DelegateExecutor, MACRO, MICRO and ManagerDeployer
Derivatives.t.sol 35 Forward, Future and MultiAssetBatch. Fuzz: money and tokens in equal money and tokens out
Marketplace.t.sol 53 Marketplace, Portfolio and portfolioLedger. Fuzz: after each random action, the marketplace holds exactly what it owes

Not tested: a real network, testnet or mainnet, an independent security audit, the Python helpers in pyscripts/, and whether the instruments meet any financial or securities rule.

Changes from earlier versions

Contracts already deployed are unaffected and keep the old behaviour. Most of these contracts could not work before, or lost money when they did.

Marketplace

  • acceptOffer paid the buyer instead of the seller. It now pays the seller.
  • claimAuction could be repeated, paying out of other people's money. An auction now closes once, and the creator can close it too.
  • Auctioned tokens are now held by the marketplace from the start, so a seller can't back out. The creator is paid when the auction closes, even if the winner's address refuses the tokens. The tokens then wait for collectAuctionTokens, which can send them to another address. This closes a way to win an auction, refuse the tokens and get the bid back.
  • A sale or auction now keeps the fee in force when it was created, and the fee limit is now 20% instead of 100%.
  • Auctions can last at most a year and start at most a year away. A very long duration could lock a bid for good.
  • A transfer of zero keys could point a portfolio's currentOwner at the wrong address, which broke broker recovery. Anyone could do this.
  • buyForwardsToken(token, id, date, price), initiateContract(date, price) and sign_proposal(documentHash) now name what the caller read. A handler or party can no longer change the terms while a purchase or signature is pending.
  • A Forward can no longer be bought after its maturity date.
  • MultiAssetBatch has a new redeemAsset, so one stuck token contract can't trap the rest.
  • Sales could be bought more than once and after their deadline. Sales now end when sold, and overpayment is refunded.
  • Sale money, replaced bids and fee shares now go to escrowAmount instead of being sent straight away, so sellers and recipients call withdrawEscrow.
  • Fee money with no recipient used to be stuck. It now goes to feeReserve, collected with withdrawFeeReserve. Fee settings have limits.
  • Bids on auctions that don't exist used to take the money. They are now refused. If the tokens can't reach an auction winner, the winner's bid is refunded.
  • Offers lock their money through the new lockedEscrow. withdrawEscrow can now take the full balance. New view viewAuction.
  • An auction's highestBid starts at 0, and an increment can be bigger than the start price.

Portfolio

  • depositEscrow withdrew instead of depositing. makeOffer and placeBid sent no money. A portfolio couldn't hold tokens or spend what it received. New functions withdrawFunds and approveMarketplace.
  • portfolioLedger left the marketplace keys in a contract that couldn't use them. They now go to whoever deploys the ledger. checkAccount no longer creates accounts while looking them up, and forwardFunds works.
  • deleteMarketplace only accepted marketplaces that were not saved. Saved marketplaces now keep their own names and numbers. resetOwner keeps working after the key moves.

Instruments

  • Contract: signing works, with each role signing once. The fourth signature completes it, and a counter-proposal clears signatures. The constructor takes a _holder, which also makes ContractDeployer work.
  • DelegateExecutor: delegateCall let anyone run outside code as this contract, so it is gone, replaced by a key-only executeCall. The password is gone too, because anything sent to a public chain is public. SendXRC1155 works and token transfers are checked.
  • Forward: a pending purchase fails if the terms change, and a forward redeems once and can't be transferred. New cancelListing returns an unsold asset.
  • Future: the constructor always reverted, the handler and future tokens shared an ID, and the handler could take the deposit at any time. It is rewritten around those rules, with new cancelSale, inDefault, handlerBalance, listed and divisable. The constructor takes one token address, and AssetTokens and TokenList are gone.
  • MultiAssetBatch: adding and redeeming always reverted. Both work now, the limit is exact, and redeeming empties the batch.
  • Document: the first document's token was also a handler key. They now have different IDs.
  • Asset: moveAsset needed an approval it could never have. It no longer does.
  • Macro_Contracts.sol and Micro_Contracts.sol now compile and work, with key-holder control.
  • Forward and Future no longer define their own ASSET contract, which clashed in Hardhat. Contracts refuse money and tokens they could never return.

Tooling

  • Removed the Hardhat setup (hardhat.config.js, package.json, package-lock.json, scripts/) and its tests, which could not run and no longer match, along with the Lock template. Foundry is the supported path.

The notes in Documents/ and the article in docs/WRITEUP.md describe the original design, and some details have changed.

Known issues

Issue Effect
Brokers have real power An Asset handler can move or destroy anyone's asset. A marketplace key holder can reset a portfolio's owner. That is the design, so a broker must be trusted
Any one key is enough Any MultiAssetBatch or DelegateExecutor key can take everything the contract holds, and executeCall can do anything
Listed sales rely on approvals Listed tokens stay with the seller. If the seller moves them, a buyer's purchase fails and the buyer keeps their money. Listings are not guaranteed to be fillable
A broker can raise fees for new listings The fee is fixed when a listing is created, but a key holder can raise it up to 20% just before one is created. Check listFee after listing
A key holder can change a portfolio's marketplace changeMarketplace also changes which brokers can recover it. Someone who steals the key can lock the original broker out
One person can hold several Contract roles Roles are tokens, so one person with two addresses can sign as both a party and a witness
Future terms include a default window redemptionTimeLimit can be as short as 1 second. Read it before buying, because missing it loses the deposit
Forward and Future have one buyer Each contract handles one sale. Deploy a new one for each deal
Buyers must check the token Forward and Future accept any token contract the handler names. A fake token passes every check
Listing loops grow viewAllAssetsAndBids reads every sale. It is meant for off-chain reads
Licenses are mixed Files declare GPL-3.0, MIT or UNLICENSED in their headers. Check each file before reuse
More XDC and EVM projects
Group Project What it is
Standards XRC-SHARES Dividend-paying NFT shares and SPLITS for a DApp
Standards XRCDividendPlus Dividend-paying XRC-20 token
Treasury and finance Multi-Sig-Treasury Treasury controlled by tokenized keys
Treasury and finance XRC-Airdrop Self-run token airdrop
Treasury and finance XRC-Credit Single-loan credit contract
Treasury and finance XRC1155-Equities-Market Shares, portfolios and a marketplace on ERC-1155
Treasury and finance NFTOTC Over-the-counter sale of a token collection
Treasury and finance DAppProxySwap Currency swaps for a DApp through a fixed router
Identity and access LoginMFAContract Login with an NFT and a signed second factor
Identity and access PrivateAccessToken Token access to encrypted off-chain data
Identity and access Delegated_Authority KYC notary proof of concept
Identity and access EncryptedNFT-Documents NFTs tied to encrypted off-chain documents
Learning and libraries XDC-LemonadeStand Workshop DApp built on XRC-SHARES
Learning and libraries Non-Financial-SmartContracts Games, inventory, keys and on-chain repositories
Learning and libraries ContractLedger On-chain list of contract addresses
Learning and libraries TimestampConverter Timestamps to calendar dates in Solidity
Tools XDC_Python_SDK_V1 Python client for the XDC JSON-RPC API
Tools PrivateXDCNode_SetupScript Private XDC network setup scripts
Tools WebApp_to_XDCPay Working web app connected to XDCPay
Multi-chain CoinClub_Framework Python library with an XDC adapter
Interfaces Contract_Interface_Model_Language Interface documents for smart contracts and APIs

License

Mixed. See the SPDX header of each file.

About

Proof of concept for trade finance on XDC: tokenized assets, agreements, forwards, futures, batches, portfolios and a marketplace. Foundry tests included. Not audited.

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Used by

Contributors

Languages