-
Notifications
You must be signed in to change notification settings - Fork 0
/
OracleEscrow.sol
109 lines (96 loc) · 3.98 KB
/
OracleEscrow.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
pragma solidity 0.4.23;
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
/**
* @title Oracle Escrow
* @dev The Oracle Escrow contract has an owner address, acting as the agent, a depositor,
* and a beneficiary. It allows for funds to be held in escrow until a given real-world
* external event has occurred. Relies on a unique Oracle contract address to be created
* using smartcontract.com. Inheriting the Ownable contract allows for the agent to be updated
* or removed from the contract without altering the execution of the contract or outcome.
*/
contract OracleEscrow is Ownable {
uint256 public expiration;
bool public contractExecuted;
address public depositor;
address public beneficiary;
IOracle internal oracle;
// Expected value is hard-coded into the contract and can be verified by all parties
// before any deposit is made.
bytes32 public constant EXPECTED = "yes";
// Expiration date should be a factor of days to prevent timestamp dependence.
// https://consensys.github.io/smart-contract-best-practices/recommendations/#timestamp-dependence
uint256 internal constant TO_EXPIRE = 30 days;
/**
* @dev The OracleEscrow constructor sets the oracle, depositor, and beneficiary addresses.
* It also sets the `contractExecuted` field to `false` and sets the expiration of the agreement
* to be 30 days after the OracleEscrow contract has been deployed.
* @param _oracle address, the address of the deployed Oracle contract.
* @param _depositor address, the address of the depositor.
* @param _beneficiary address, the address of the beneficiary.
*/
constructor(address _oracle, address _depositor, address _beneficiary) public payable Ownable() {
oracle = IOracle(_oracle);
depositor = _depositor;
beneficiary = _beneficiary;
contractExecuted = false;
expiration = now + TO_EXPIRE;
}
/**
* @dev Logs a message indicating where the escrow payment was sent to.
*/
event ContractExecuted(bytes32 message);
/**
* @dev payable fallback only allows the depositor to send funds, as long as the contract
* hasn't been executed already, and the expiration has not been passed.
*/
function() external payable onlyDepositor {
require(contractExecuted == false);
require(now < expiration);
}
/**
* @dev Executes the contract if called by an authorized user and the balance of the escrow
* is greater than 0. If the Oracle contract's reported value is the expected value, payment
* goes to the beneficiary. If the escrow contract has gone passed the expiration and the
* Oracle contract's reported value still is not what is expected, payment is returned to
* the depositor.
*/
function executeContract() public checkAuthorizedUser() {
require(address(this).balance > 0);
if (oracle.current() == EXPECTED) {
contractExecuted = true;
emit ContractExecuted("Payment sent to beneficiary.");
beneficiary.transfer(address(this).balance);
} else if (now >= expiration) {
contractExecuted = true;
emit ContractExecuted("Payment refunded to depositor.");
depositor.transfer(address(this).balance);
}
}
/**
* @dev Check the current value stored on the Oracle contract.
* @return The current value at the Oracle contract.
*/
function requestOracleValue() public view onlyOwner returns(bytes32) {
return oracle.current();
}
/**
* @dev Reverts if called by any account other than the owner, depositor, or beneficiary.
*/
modifier checkAuthorizedUser() {
require(msg.sender == owner || msg.sender == depositor || msg.sender == beneficiary, "Only authorized users may call this function.");
_;
}
/**
* @dev Reverts if called by any account other than the depositor.
*/
modifier onlyDepositor() {
require(msg.sender == depositor, "Only the depositor may call this function.");
_;
}
}
/**
* @dev Interface for the Oracle contract.
*/
interface IOracle{
function current() view external returns(bytes32);
}