Delivery vs Payment (DvP)
DvP is a common financial transaction exchange method where delivery of securities occurs at the same time that payment is made. It ensures that both parties fulfill their obligations simultaneously, reducing counterparty risk and the possibility of default.
Rayls supports two ERC token standards: ERC20 (a standard for creating fungible tokens) and ERC1155 (a standard for creating both fungible and non-fungible tokens).
Overview
The DvP contract allows anyone to create exchanges specifying some parameters (see methods below). Those exchanges are stored on the contract, referenced by their exchangeId
, and they can be later executed by the counterparty
(unless they are expired). A specific counterparty
can be informed on the exchange creation, otherwise, the exchange will be open to any counterparty
address to accept it.
Types
enum ExchangeStatus {
NOT_EXISTS,
INITIALIZED,
EXECUTED,
EXPIRED
}
enum AssetType {
ERC20,
ERC1155
}
struct Asset {
AssetType assetType;
address tokenAddress;
uint256 amount;
uint256 tokenId;
}
struct Exchange {
address creator;
Asset creatorAsset;
address creatorBeneficiary;
address counterparty;
Asset counterpartyAsset;
uint256 expirationDate;
ExchangeStatus status;
}
ExchangeStatus
enumerates the possible states the exchange can find itself in.AssetType
enumerates the token standards accepted by the contract.Asset
defines everything needed to know about an asset used in the exchange.assetType
represents the token standard;tokenAddress
represents the token's contract address;amount
represents the amount offered for the exchange;tokenId
is ERC1155-specific and defines the id for the token in the ERC1155 contract.
Exchange
defines everything that needs to be known about an exchange.creator
represents the exchange creator address;creatorAsset
represents theAsset
thecreator
is offering in the exchange;creatorBeneficiary
represents the address where the exchangecreator
wants thecounterparty
funds to be deposited;counterparty
represents the exchange acceptor address;counterpartyAsset
represents theAsset
thecounterparty
is offering in the exchange;expirationDate
represents an expiration date for the exchange to become invalid;status
represents the state the exchange finds itself in.
Observations
- The
creator
is the exchange initiator , thecounterparty
is the exchange acceptor.
Properties
uint256 public lastExchangeId;
mapping(uint256 => Exchange) public exchanges;
lastExchangeId
stores the most recently createdexchangeId
;exchanges
stores a mapping fromexchangeId
s toexchanges
;
Methods
createExchange(
Asset memory creatorAsset,
address creatorBeneficiary,
address counterparty,
Asset memory counterpartyAsset,
uint256 expirationDate
)
executeExchange(uint256 exchangeId)
- The
createExchange
method should be called by thecreator
of the exchange.creatorAsset
represents theAsset
thecreator
is offering in the exchange;creatorBeneficiary
represents the address where the exchangecreator
wants thecounterparty
funds to be deposited;counterparty
represents the exchange acceptor address;counterpartyAsset
represents theAsset
thecounterparty
is offering in the exchange;expirationDate
represents an expiration date for the exchange to become invalid;
- The
executeExchange
method should be called by thecounterparty
of the exchange.exchangeId
represents the id of the exchange thecounterparty
wants to accept.
Observations
- If the
creatorBeneficiary
address isaddress(0)
, then the address used to receive thecounterparty
funds will be thecreator
address. - If the
counterparty
address isaddress(0)
, then the exchange is open for anycounterparty
address to accept it. - The
exchangeId
starts as 1 for the first exchange created, and increases by 1 for each following exchange created.
Events
event ExchangeInitialized(
uint256 indexed exchangeId,
Exchange exchange
);
event ExchangeExecuted(
uint256 indexed exchangeId,
address indexed executor
);
- When the
createExchange
method is concluded successfully, theExchangeInitialized
event will be emitted. - When the
executeExchange
method is concluded successfully, theExchangeExecuted
event will be emitted.
Errors
'DvPExchange.createExchange: INVALID_EXPIRATION_DATE'
'DvPExchange.createExchange: INVALID_EXCHANGE_ID'
'DvPExchange.createExchange: INSUFFICIENT_ALLOWANCE'
'DvPExchange.createExchange: INSUFFICIENT_BALANCE'
'DvPExchange.createExchange: NOT_APPROVED_FOR_ALL'
'DvPExchange.createExchange: INVALID_ASSET_TYPE'
'DvPExchange.executeExchange: EXCHANGE_NOT_INITIALIZED'
'DvPExchange.executeExchange: EXCHANGE_EXPIRED'
'DvPExchange.executeExchange: UNAUTHORIZED_SENDER'
'DvPExchange.executeExchange: INVALID_ASSET_TYPE for creator'
'DvPExchange.executeExchange: INVALID_ASSET_TYPE for counterparty'
'DvPExchange.executeExchange: TRANSFER_FAILED'
createExchange
DvPExchange.createExchange: INVALID_EXPIRATION_DATE
occurs when you try to create an exchange with an expiration date in the past (that is, trying to create an exchange that would be born already expired).DvPExchange.createExchange: INVALID_EXCHANGE_ID
occurs in the extremely exceptional case where theexchangeId
s overflow theuint256
DvPExchange.createExchange: INSUFFICIENT_ALLOWANCE
occurs when thecreator
uses an ERC20 token and hasn't allowed the DvP contract to use enough funds to supply the exchange demand they are trying to create.DvPExchange.createExchange: INSUFFICIENT_BALANCE
occurs when thecreator
uses any token and they don't have enough balance to supply the exchange demand they are trying to create.DvPExchange.createExchange: NOT_APPROVED_FOR_ALL
occurs when thecreator
uses an ERC1155 token and hasn't approved the DvP contract to use funds to supply the exchange demand they are trying to create.DvPExchange.createExchange: INVALID_ASSET_TYPE
occurs when theAssetType
informed in thecreatorAsset
is invalid.
executeExchange
DvPExchange.executeExchange: EXCHANGE_NOT_INITIALIZED
when the exchangestatus
is not initialized (and thus it's not ready to be accepted).DvPExchange.executeExchange: EXCHANGE_EXPIRED
when the exchange is already expired.DvPExchange.executeExchange: UNAUTHORIZED_SENDER
when the acceptor, who is trying to execute the exchange, is not the one determined by thecreator
.DvPExchange.executeExchange: INVALID_ASSET_TYPE for creator
when theAssetType
informed in thecreatorAsset
is invalid.DvPExchange.executeExchange: INVALID_ASSET_TYPE for counterparty
when theAssetType
informed in thecounterpartyAsset
is invalid.DvPExchange.executeExchange: TRANSFER_FAILED
when it is an ERC20 transfer and the transfer fails.
Updated 5 months ago