██╗ ███████╗██╗ ██╗███████╗███████╗██████╗ ███████╗██╗ ██╗
██║ ██╔════╝ ██║ ██╔╝██╔════╝██╔════╝██╔══██╗██╔══██║██║ ██║
██║ █████╗ ╚██╔╝ ███████╗██║ ██████╔╝██║ ██║██║ █╗ ██║
██║ ██╔══╝ ██╔╝██╗ ╚════██║██║ ██╔══██╗██║ ██║██║███╗██║
███████╗███████╗██║ ██╗███████║███████╗██║ ██║███████║╚███╔███╔╝
╚══════╝╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝
///Immutable, non-custodial, conditional smart contract escrow.
╚═══════╝ ╚═╝ ╚═══════╝ ╚════════╝ ╚═══╝ ╚══════╝ ╚════╝
Immutable, non-custodial, flexibly-conditioned escrow, transfers, and swaps.
All LeXscroW types have the following features:
- Ownerless unique contract deployment
- Optional conditions for execution, including signatures, time, oracle-fed data, and more, which are immutable from construction and may be combined
- specify depositing part(ies) or allow any address to deposit (open offer)
- parties may replace their own address, and may be an EOA or a contract
- mutual early termination option
- expiration denominated in seconds / Unix time
- re-usable until expiration
As all parameters aside from parties' addresses are immutable upon a LeXscroW's deployment, configuration of each such parameter is critical.
Below is some basic information on each type of LeXscroW. For more details, please consult the documentation.
README
LICENSE
└─ docs
├─_overview.mdx
├─_design.mdx
├─_deploy.mdx
└─_use.mdx
└─ src
├─ DoubleTokenLexscrow.sol
├─ DoubleTokenLexscrowFactory.sol
├─ EthLexscrow.sol
├─ EthLexscrowFactory.sol
├─ TokenLexscrow.sol
├─ TokenLexscrowFactory.sol
└─ libs
└─ LexscrowConditionManager.sol
└─ test
├─ DoubleTokenLexscrow.t.sol
├─ DoubleTokenLexscrowFactory.t.sol
├─ EthLexscrow.t.sol
├─ EthLexscrowFactory.t.sol
├─ LexscrowConditionManager.t.sol
├─ TokenLexscrow.t.sol
└─ TokenLexscrowFactory.t.sol
Conditional Atomic Token Swaps
Bilateral smart escrow contract for (non-fee-on-transfer, non-rebasing) ERC20 tokens.
-
buyer
(or, if an open offer, any address) depositstoken1
andseller
(or if an open offer, any address) depositstoken2
viadepositTokens()
ordepositTokensWithPermit()
-
if desired,
buyer
may replace its address by passing the new address toupdateBuyer()
, andseller
may do the same withupdateSeller()
-
parties may choose to mutually terminate early by passing
true
toelectToTerminate()
; if both do so, their deposited tokens will be returned and the LeXscroW will be expired -
execute()
is not permissioned, and thus may be called by any address. If called, the LeXscrow executes and simultaneously releasestotalAmount1
oftoken1
toseller
andtotalAmount2
oftoken2
tobuyer
iff:(1)
buyer
andseller
have respectively depositedtotalAmount1
+ any applicablefee1
oftoken1
andtotalAmount2
+ any applicablefee2
oftoken2
,(2)
expirationTime
>block.timestamp
, and(3) if there is/are condition(s), such condition(s) is/are satisfied upon the external call in
execute()
.
If executed, the LeXscroW is re-usable by parties until the set expiration time.
Otherwise, all deposited amounts of token1
are returned to buyer
and all deposited amounts of token2
are returned to seller
if the LeXscroW expires.
Conditional Token Payments
Unilateral smart escrow contract for (non-fee-on-transfer, non-rebasing) ERC20 tokens.
-
initialized with a
deposit
amount which can be any amount up to thetotalAmount
, and may be refundable or non-refundable tobuyer
upon expiry -
buyer
(or, if an open offer, any address) deposits viadepositTokens()
ordepositTokensWithPermit()
-
if desired,
buyer
may replace its address by passing the new address toupdateBuyer()
, andseller
may do the same withupdateSeller()
-
seller
may callrejectDepositor()
to reject a depositing address, which will cause any amount deposited by such address to become withdrawable (viawithdraw()
) by the rejected depositor. Also enables early mutual termination. -
execute()
is not permissioned, and thus may be called by any address. If called, the LeXscroW executes and simultaneously releasestotalAmount
toseller
iff:(1)
buyer
has depositedtotalAmount
+ any applicablefee
net of anypendingWithdraw
amount,(2)
expirationTime
>block.timestamp
,(3) if there is/are condition(s), such condition(s) is/are satisfied upon the external call in
execute()
.
If executed, the LeXscroW is re-usable by parties until the set expiration time.
Otherwise, amount held in the LeXscroW will be treated according to the code in checkIfExpired()
when called following expiry. If expired, the applicable party must call withdraw()
to receive their tokens.
Conditional Gas Token Transfers
Unilateral smart escrow contract for native gas tokens, denominated in 1e18 decimals (wei).
-
initialized with a
deposit
amount which can be any amount up to thetotalAmount
, and may be refundable or non-refundable tobuyer
upon expiry -
buyer
(or, if an open offer, any address) deposits by sending amount directly to the LeXscroW contract address and thus invoking thereceive()
function. The conditional logic rejects any amount in excess oftotalWithFee
-
if desired,
buyer
may replace its address by passing the new address toupdateBuyer()
, andseller
may do the same withupdateSeller()
-
seller
may callrejectDepositor()
to reject a depositing address, which will cause any amount deposited by such address to become withdrawable (viawithdraw()
) by the rejected depositor. Also enables early mutual termination. -
execute()
is not permissioned, and thus may be called by any address. If called, the LeXscroW executes and simultaneously releasestotalAmount
toseller
iff:(1)
buyer
has depositedtotalAmount
+ any applicablefee
net of anypendingWithdraw
amount,(2)
expirationTime
>block.timestamp
, and(3) if there is/are condition(s), such condition(s) is/are satisfied upon the external call in
execute()
.
If executed, the LeXscroW is re-usable by parties until the set expiration time.
Otherwise, amount held in the LeXscroW will be treated according to the code in checkIfExpired()
when called following expiry. If expired, the applicable party must call withdraw()
to receive their funds.
-
DoubleTokenLexscrowFactory
,TokenLexscrowFactory
, andEthLexscrowFactory
set any applicable fee amounts, fee receiver address, and enable easy deployment of the corresponding LeXscroW type (including simultaneous deployment of a Ricardian Tripler and a corresponding LeXscroW where supported). -
LexscrowConditionManager
is an adaptation of the BORG-COREConditionManager
, without auth/access control (and thus also the ability to add or remove conditions post-deployment) in favor of immutability. -
Receipt
is an optional informational contract that provides a USD-value "receipt" for certain tokens with initialized and configured data feeds.
Before you begin, ensure you have the following installed:
To set up the project locally, follow these steps:
-
Clone the repository
git clone https://github.com/MetaLex-Tech/LeXscroW cd LeXscroW
-
Install dependencies
foundryup # Update Foundry tools forge install # Install project dependencies
-
Compile Contracts
forge build --optimize --optimizer-runs 200 --use solc:0.8.18 --via-ir