Safe remote purchase escrow holding a double deposit from both sides
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
MyToken
Same deployerThe first contract on Ethereum mainnet to carry balanceOf, transfer and a Transfer event together, deployed 23 October 2015. Supply 1,000,000, and it was never used.
0x3c655c...58b017October 23, 2015Contract 0xe65129...ec0c13
Same deployerThe same token code as 0x3C655ccb35666579511489af88153517fc58b017, the first contract on mainnet with balanceOf, transfer and Transfer, redeployed the same afternoon with a supply of 1,000.
0xe65129...ec0c13October 23, 2015MyToken
Same deployerThe October 2015 prototype where balances moved into a public mapping named balanceOf, with a lower case balanceof function returning the same value. Supply 200,000, never used.
0xcae62d...7a2b8bOctober 23, 2015Contract 0x11485c...304094
Same deployerIdentical token code to 0xCAe62D22E8480b230d7aD93039167a0FfA7A2B8B, redeployed four minutes later with the same 200,000 supply. No transfer was ever made.
0x11485c...304094October 23, 2015MyToken
Same deployerByte identical to 0xE274d18EF7b194A1EDEbB04cfE297CFe1489ef65 and deployed two minutes and twelve seconds later from a different account. Supply 10,000, and the one call that reached it emitted no Transfer event.
0x005762...515a2cOctober 26, 2015MyToken
Same deployerThe October 2015 prototype that was actually used, with eight Transfer events. Balances sit in a public mapping named balances and are read through a balanceOf function. Supply 132,325,360.
0x27cb40...e0c0edOctober 27, 2015