Safe remote purchase escrow holding a double deposit from both sides
Historical Significance
Escrow without an escrow agent, which is the use people reached for first once a contract could hold money. The double deposit is the mechanism that makes it work: both sides have more at stake than the item is worth, so abandoning the trade costs the abandoner more than completing it, and no third party has to be trusted or paid. It is a worked example of designing incentives rather than enforcement.
Context
Deployed in November 2015 during the Frontier period, when the Solidity documentation examples were the main source of contract code in circulation.
Key Facts
Description
An escrow for a remote sale. The seller deploys the contract with twice the item price, which the constructor halves and records as the value. A buyer locks the sale by sending the same doubled amount through confirmPurchase. Calling confirmReceived returns the buyer's deposit and pays the seller the rest, and refund lets the seller unwind a locked sale instead. State transitions are guarded by a three-value enum and by modifiers that restrict each call to the buyer or the seller. It is an edited copy of the safe remote purchase example from the Solidity documentation, with a refund path and capitalised events added. This deployment was compiled with the optimiser enabled.
Source Verified
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Frontier Era
The initial release of Ethereum. A bare-bones implementation for technical users.
Bytecode Overview
Verified Source Available
Source verified through compiler archaeology and exact bytecode matching.
View Verification ProofShow source code (Solidity)
// Submitted by EthereumHistory (ethereumhistory.com)
contract Purchase {
uint public value;
address public seller;
address public buyer;
enum State { Created, Locked, Inactive }
State public state;
function Purchase() require(msg.value % 2 == 0) {
seller = msg.sender;
value = msg.value / 2;
}
modifier require(bool _condition) {
if (!_condition) throw;
_
}
modifier onlyBuyer() {
if (msg.sender != buyer) throw;
_
}
modifier onlySeller() {
if (msg.sender != seller) throw;
_
}
modifier inState(State _state) {
if (state != _state) throw;
_
}
event Aborted();
event PurchaseConfirmed();
event ItemReceived();
event Refunded();
function abort()
onlySeller
inState(State.Created)
{
seller.send(this.balance);
state = State.Inactive;
Aborted();
}
function confirmPurchase()
inState(State.Created)
require(msg.value == 2 * value)
{
buyer = msg.sender;
state = State.Locked;
PurchaseConfirmed();
}
function confirmReceived()
onlyBuyer
inState(State.Locked)
{
buyer.send(value);
seller.send(this.balance);
state = State.Inactive;
ItemReceived();
}
function refund()
onlySeller
inState(State.Locked)
{
buyer.send(2 * value);
seller.send(this.balance);
state = State.Inactive;
Refunded();
}
function() {
throw;
}
}External Links
Related contracts
Wallet
Same deployerGav Wood's multi-sig, daily-limited wallet: the shared implementation that 111 Frontier-era 49-byte forwarders CALLCODE into.
0x273930...2220a2August 20, 2015Wallet
Same deployerA 49-byte CALLCODE forwarder for an early Ethereum multi-sig wallet, delegating every call to Gav Wood's shared wallet library.
0xf5d2ae...8d9533August 20, 2015Wallet
Same deployerA 49-byte CALLCODE forwarder for an early Ethereum multi-sig wallet, delegating every call to Gav Wood's shared wallet library.
0x0ace96...0d68b1September 15, 2015Wallet
Same deployerA 49-byte CALLCODE forwarder for an early Ethereum multi-sig wallet, delegating every call to Gav Wood's shared wallet library.
0xbda7ae...d15497September 15, 2015Wallet
Same deployerA 49-byte CALLCODE forwarder for an early Ethereum multi-sig wallet, delegating every call to Gav Wood's shared wallet library.
0x035e62...4c3b00September 28, 2015MyToken
Same deployerThe first contract on Ethereum mainnet to carry balanceOf, transfer and a Transfer event together, deployed 23 October 2015 with a supply of 1,000,000.
0x3c655c...58b017October 23, 2015