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.
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
Greeter
Same eraA HelloWorld greeter deployed at block 51,909 on 8 August 2015, one of a run of contracts from the same account that week.
0x412fda...7267edAugust 8, 2015Greeter
Same eraA Greeter with the message 'Ethereum will change the world smarter' - deployed Aug 8, 2015 by a developer connected to the Tokyo Smart Contract meetup.
0xda0c1c...7a68ebAugust 8, 2015MessageStore
Same eraA 6-line contract storing a single public string, deployed Day 9 of Ethereum by a prolific early experimenter who shipped 18 contracts in one week.
0xd2eccd...ff3d6bAugust 8, 2015Greeter
Same eraThe go-ethereum Contract Tutorial greeter, deployed with the greeting: Hello World!
0x506f4b...466983August 8, 2015Contract 0xd4eae4...a2c77a
Same eraThe ethereum.org crowdsale tutorial, deployed on the ninth day of the public chain, with the funding goal, deadline and price fixed at construction.
0xd4eae4...a2c77aAugust 8, 2015Greeter
Same eraA Frontier-era Greeter contract with the message: 'Hello World!'
0x113158...72fa8aAugust 8, 2015