Created
January 11, 2019 14:13
-
-
Save diminator/9efaa672d0ccf2b274c915db8c118648 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.2+commit.1df8f40c.js&optimize=false&gist=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
import 'browser/Condition.sol'; | |
contract AgreementStore { | |
struct Agreement { | |
bool exists; | |
bytes32 templateId; | |
bool state; | |
bytes32 did; | |
} | |
mapping(bytes32 => Agreement) _agreements; | |
} | |
contract TemplateStore { | |
struct Template { | |
bool exists; | |
bytes32[] conditionTypes; | |
bytes32 rewardType; | |
} | |
mapping(bytes32 => Template) _templates; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
import 'github.com/OpenZeppelin/zeppelin-solidity/contracts/cryptography/ECDSA.sol'; | |
import 'browser/OceanToken.sol'; | |
contract ConditionStore { | |
enum ConditionState { Uninitialized, Unfufilled, Fulfilled, Aborted } | |
struct Condition { | |
address _type; | |
ConditionState state; | |
uint timeout; | |
bytes32 dependency; | |
} | |
mapping(bytes32 => Condition) internal _conditions; | |
function exists(bytes32 id) public view returns (bool) { | |
return _conditions[id].state != ConditionState.Uninitialized; | |
} | |
function getType(bytes32 id) public view returns (address) { | |
return _conditions[id]._type; | |
} | |
function getState(bytes32 id) public view returns (ConditionState) { | |
return _conditions[id].state; | |
} | |
function getTimeout(bytes32 id) public view returns (uint) { | |
return _conditions[id].timeout; | |
} | |
function getDependency(bytes32 id) public view returns (bytes32) { | |
return _conditions[id].dependency; | |
} | |
function create(bytes32 id) public returns (bool) { | |
// TODO: can only be executed by Condition contract | |
if (!exists(id)) { | |
_conditions[id].state = ConditionState.Unfufilled; | |
_conditions[id]._type = address(msg.sender); | |
} | |
} | |
function updateState(bytes32 id, ConditionState state) public returns (bool) { | |
// TODO: can only be executed by Condition contract | |
// TODO: check ._type | |
if (isDependencyFulfilled(id)) { | |
// TODO: check valid state transitions | |
_conditions[id].state = state; | |
return true; | |
} | |
return false; | |
} | |
function updateTimeout(bytes32 id, uint timeout) public returns (bool) { | |
// TODO: can only be executed by Condition owner | |
// TODO: can only be executed upon creation | |
_conditions[id].timeout = block.number + timeout; | |
return true; | |
} | |
function isTimeout(bytes32 id) public view returns (bool) { | |
return ( (_conditions[id].timeout > 0) && (block.number > _conditions[id].timeout) ); | |
} | |
function updateDependency(bytes32 id, bytes32 dependentId) public returns (bool) { | |
// TODO: can only be executed by Condition owner | |
// TODO: can only be executed upon creation | |
_conditions[id].dependency = dependentId; | |
return true; | |
} | |
function isDependencyFulfilled(bytes32 id) public view returns (bool) { | |
if (getDependency(id) > 0x0) { | |
if (!(getState(getDependency(id)) == ConditionState.Fulfilled)) return false; | |
} | |
return true; | |
} | |
} | |
contract Condition { | |
ConditionStore internal conditionStore; | |
event ConditionFulfilled(bytes32 indexed agreementId, address indexed _type, bytes32 id); | |
// function hashValues(uint256 preimage) public pure returns (bytes32); | |
function generateId(bytes32 agreementId, bytes32 valueHash) public pure returns (bytes32){ | |
return keccak256(abi.encodePacked(agreementId, valueHash)); | |
} | |
function create(bytes32 id) internal returns (bool) { | |
return conditionStore.create(id); | |
} | |
function fulfill(bytes32 id, ConditionStore.ConditionState state) internal returns (bool) { | |
return conditionStore.updateState(id, state); | |
} | |
} | |
contract HashCondition is Condition { | |
constructor(address conditionStoreAddress) public { | |
conditionStore = ConditionStore(conditionStoreAddress); | |
} | |
function hashValues(uint256 preimage) public pure returns (bytes32) { | |
return hashValues(abi.encodePacked(preimage)); | |
} | |
function hashValues(string memory preimage) public pure returns (bytes32) { | |
return hashValues(abi.encodePacked(preimage)); | |
} | |
function hashValues(bytes32 preimage) public pure returns (bytes32) { | |
return hashValues(abi.encodePacked(preimage)); | |
} | |
function hashValues(bytes memory preimage) public pure returns (bytes32) { | |
return keccak256(preimage); | |
} | |
function create(bytes32 agreementId, bytes32 hash) public returns (bool){ | |
bytes32 id = generateId(agreementId, hash); | |
return super.create(id); | |
} | |
function fulfill(bytes32 agreementId, uint256 preimage) public returns (bool) { | |
bytes32 id = generateId(agreementId, hashValues(preimage)); | |
return _fulfill(agreementId, id); | |
} | |
function fulfill(bytes32 agreementId, string memory preimage) public returns (bool) { | |
bytes32 id = generateId(agreementId, hashValues(preimage)); | |
return _fulfill(agreementId, id); | |
} | |
function fulfill(bytes32 agreementId, bytes32 preimage) public returns (bool) { | |
bytes32 id = generateId(agreementId, hashValues(preimage)); | |
return _fulfill(agreementId, id); | |
} | |
function _fulfill(bytes32 agreementId, bytes32 id) private returns (bool) { | |
bool result = super.fulfill(id, ConditionStore.ConditionState.Fulfilled); | |
emit ConditionFulfilled(agreementId, address(this), id); | |
return result; | |
} | |
} | |
contract SignCondition is Condition { | |
constructor(address conditionStoreAddress) public { | |
conditionStore = ConditionStore(conditionStoreAddress); | |
} | |
function hashValues(bytes32 message, address publicKey) public pure returns (bytes32) { | |
return keccak256(abi.encodePacked(message, publicKey)); | |
} | |
function hashValues(string memory message, address publicKey) public pure returns (bytes32) { | |
return keccak256(abi.encodePacked(message, publicKey)); | |
} | |
function hashValues(bytes memory message, address publicKey) public pure returns (bytes32) { | |
return keccak256(abi.encodePacked(message, publicKey)); | |
} | |
function create(bytes32 agreementId, bytes32 message, address publicKey) public returns (bool){ | |
bytes32 id = generateId(agreementId, hashValues(message, publicKey)); | |
return super.create(id); | |
} | |
function fulfill(bytes32 agreementId, bytes32 message, address publicKey, bytes memory signature) public returns (bool) { | |
bytes32 id = generateId(agreementId, hashValues(message, publicKey)); | |
bool fulfills = ECDSA.recover(message, signature) == publicKey; | |
if (fulfills) { | |
bool result = super.fulfill(id, ConditionStore.ConditionState.Fulfilled); | |
if (result) emit ConditionFulfilled(agreementId, address(this), id); | |
} | |
return false; | |
} | |
} | |
contract LockPaymentCondition is Condition { | |
ERC20 private token; | |
constructor(address conditionStoreAddress, address tokenAddress) public { | |
conditionStore = ConditionStore(conditionStoreAddress); | |
token = OceanToken(tokenAddress); | |
} | |
function hashValues(address rewardContractAddress, uint256 amount) public pure returns (bytes32) { | |
return keccak256(abi.encodePacked(rewardContractAddress, amount)); | |
} | |
function create(bytes32 agreementId, address rewardContractAddress, uint256 amount) public returns (bool){ | |
bytes32 id = generateId(agreementId, hashValues(rewardContractAddress, amount)); | |
return super.create(id); | |
} | |
function fulfill(bytes32 agreementId, address rewardContractAddress, uint256 amount) public payable returns (bool _result) { | |
bool result = false; | |
if (token.transferFrom(msg.sender, rewardContractAddress, amount)) { | |
bytes32 id = generateId(agreementId, hashValues(rewardContractAddress, amount)); | |
result = super.fulfill(id, ConditionStore.ConditionState.Fulfilled); | |
if (result) emit ConditionFulfilled(agreementId, address(this), id); | |
} | |
return result; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
import 'github.com/OpenZeppelin/zeppelin-solidity/contracts/ownership/Ownable.sol'; | |
import 'github.com/OpenZeppelin/zeppelin-solidity/contracts/math/SafeMath.sol'; | |
import 'browser/OceanToken.sol'; | |
/** | |
@title Ocean Protocol Marketplace Contract | |
@author Team: Fang Gong, Samer Sallam, Ahmed Ali, Sebastian Gerske | |
*/ | |
contract OceanMarket is Ownable { | |
using SafeMath for uint256; | |
using SafeMath for uint; | |
// ============ | |
// DATA STRUCTURES: | |
// ============ | |
// limit period for request of tokens | |
mapping(address => uint256) private tokenRequest; // mapping from address to last time of request | |
uint256 maxAmount = 10000 * 10 ** 18; // max amount of tokens user can get for each request | |
uint256 minPeriod = 0; // min amount of time to wait before request token again | |
// marketplace global variables | |
OceanToken public oceanToken; | |
// ============ | |
// EVENTS: | |
// ============ | |
event FrequentTokenRequest( | |
address indexed requester, | |
uint256 minPeriod | |
); | |
event LimitTokenRequest( | |
address indexed requester, | |
uint256 amount, | |
uint256 maxAmount | |
); | |
// ============ | |
// modifier: | |
// ============ | |
modifier validAddress(address sender) { | |
require( | |
sender != address(0x0), | |
'Sender address is 0x0.' | |
); | |
_; | |
} | |
/** | |
* @dev OceanMarket Constructor | |
* @param tokenAddress The deployed contract address of OceanToken | |
* Runs only on initial contract creation. | |
*/ | |
constructor( | |
address tokenAddress | |
) | |
public | |
{ | |
require( | |
tokenAddress != address(0x0), | |
'Token address is 0x0.' | |
); | |
// instantiate Ocean token contract | |
oceanToken = OceanToken(tokenAddress); | |
// set the token receiver to be marketplace | |
oceanToken.setReceiver(address(this)); | |
} | |
/** | |
* @dev user can request some tokens for testing | |
* @param amount the amount of tokens to be requested | |
* @return valid Boolean indication of tokens are requested | |
*/ | |
function requestTokens( | |
uint256 amount | |
) | |
public validAddress(msg.sender) | |
returns (bool) | |
{ | |
/* solium-disable-next-line security/no-block-members */ | |
if (block.timestamp < tokenRequest[msg.sender] + minPeriod) { | |
emit FrequentTokenRequest( | |
msg.sender, | |
minPeriod | |
); | |
return false; | |
} | |
// amount should not exceed maxAmount | |
if (amount > maxAmount) { | |
require( | |
oceanToken.transfer(msg.sender, maxAmount), | |
'Token transfer failed.' | |
); | |
emit LimitTokenRequest( | |
msg.sender, | |
amount, | |
maxAmount | |
); | |
} else { | |
require( | |
oceanToken.transfer(msg.sender, amount), | |
'Token transfer failed.' | |
); | |
} | |
/* solium-disable-next-line security/no-block-members */ | |
tokenRequest[msg.sender] = block.timestamp; | |
return true; | |
} | |
/** | |
* @dev Owner can limit the amount and time for token request in Testing | |
* @param amount the max amount of tokens that can be requested | |
* @param period the min amount of time before next request | |
*/ | |
function limitTokenRequest( | |
uint amount, | |
uint period | |
) | |
public | |
onlyOwner() | |
{ | |
// set min period of time before next request (in seconds) | |
minPeriod = period; | |
// set max amount for each request | |
maxAmount = amount; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
import 'github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/ERC20.sol'; | |
import 'github.com/OpenZeppelin/zeppelin-solidity/contracts/token/ERC20/IERC20.sol'; | |
import 'github.com/OpenZeppelin/zeppelin-solidity/contracts/math/SafeMath.sol'; | |
/** | |
@title Ocean Protocol ERC20 Token Contract | |
@author Team: Fang Gong | |
*/ | |
contract OceanToken is ERC20 { | |
using SafeMath for uint256; | |
// ============ | |
// DATA STRUCTURES: | |
// ============ | |
string public constant name = 'OceanToken'; // Set the token name for display | |
string public constant symbol = 'OCN'; // Set the token symbol for display | |
// SUPPLY | |
uint8 public constant decimals = 18; // Set the number of decimals for display | |
uint256 public constant TOTAL_SUPPLY = 1400000000 * 10 ** 18; // OceanToken total supply | |
// EMIT TOKENS | |
address public receiver = address(0); // address to receive TOKENS | |
uint256 public _totalSupply; // total supply of Ocean tokens including | |
// initial tokens plus block rewards | |
/** | |
* @dev OceanToken Constructor | |
* Runs only on initial contract creation. | |
*/ | |
constructor() public { | |
_totalSupply = TOTAL_SUPPLY; | |
} | |
/** | |
* @dev setReceiver set the address to receive the emitted tokens | |
* @param to The address to send tokens | |
* @return success setting is successful. | |
*/ | |
function setReceiver(address to) public returns (bool success){ | |
// make sure receiver is not set already | |
require(receiver == address(0), 'Receiver address already set.'); | |
// Creator address is assigned initial available tokens | |
super._mint(to, TOTAL_SUPPLY); | |
// set receiver | |
receiver = to; | |
return true; | |
} | |
/** | |
* @dev Transfer token for a specified address when not paused | |
* @param to The address to transfer to. | |
* @param value The amount to be transferred. | |
*/ | |
function transfer( | |
address to, | |
uint256 value | |
) | |
public | |
returns (bool) | |
{ | |
require( | |
to != address(0), | |
'To address is 0x0.' | |
); | |
return super.transfer(to, value); | |
} | |
/** | |
* @dev Transfer tokens from one address to another when not paused | |
* @param _from address The address which you want to send tokens from | |
* @param to address The address which you want to transfer to | |
* @param value uint256 the amount of tokens to be transferred | |
*/ | |
function transferFrom( | |
address _from, | |
address to, | |
uint256 value | |
) | |
public | |
returns (bool) | |
{ | |
require( | |
to != address(0), | |
'To address is 0x0.' | |
); | |
return super.transferFrom(_from, to, value); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
import "browser/Condition.sol"; | |
interface IReward { | |
function generateId(bytes32 agreementId, uint256 amount, address receiver, address sender, bytes32 condition) external pure returns (bytes32); | |
function create(bytes32 agreementId, uint256 amount, address receiver, address sender, bytes32 condition) external pure returns (bytes32); | |
function reward(bytes32 id) external returns (bool); | |
} | |
contract Reward { | |
ERC20 internal token; | |
ConditionStore internal conditionStore; | |
} | |
contract EscrowRewardStore is Reward { | |
struct EscrowReward { | |
uint256 amount; | |
address receiver; | |
address sender; | |
bytes32 lockCondition; // 0xLOCK | |
bytes32 rewardCondition; // 0xACCESS | |
} | |
mapping(bytes32 => EscrowReward) _rewards; | |
constructor(address conditionStoreAddress, address tokenAddress) public payable { | |
conditionStore = ConditionStore(conditionStoreAddress); | |
token = OceanToken(tokenAddress); | |
} | |
function generateId(bytes32 agreementId, uint256 amount, address receiver, address sender, bytes32 lockCondition, bytes32 rewardCondition) public pure returns (bytes32){ | |
return keccak256(abi.encodePacked(agreementId, amount, receiver, sender, lockCondition, rewardCondition)); | |
} | |
function create(bytes32 agreementId, uint256 amount, address receiver, address sender, bytes32 lockCondition, bytes32 rewardCondition) public returns (bool) { | |
// TODO: only allow agreement contract to call this function | |
bytes32 id = generateId(agreementId, amount, receiver, sender, lockCondition, rewardCondition); | |
// TODO: check state of conditions > Uninitialized | |
_rewards[id] = EscrowReward(amount, receiver, sender, lockCondition, rewardCondition); | |
} | |
function isRewardLocked(bytes32 id) public view returns (bool) { | |
return conditionStore.getState(_rewards[id].lockCondition) == ConditionStore.ConditionState.Fulfilled; | |
} | |
function isConditionExecuted(bytes32 id) public view returns (bool) { | |
return conditionStore.getState(_rewards[id].rewardCondition) == ConditionStore.ConditionState.Fulfilled; | |
} | |
function isConditionAborted(bytes32 id) public view returns (bool) { | |
return conditionStore.getState(_rewards[id].rewardCondition) == ConditionStore.ConditionState.Aborted; | |
} | |
function reward(bytes32 id) public returns (bool) { | |
if (isRewardLocked(id)) { | |
if (isConditionExecuted(id)) { | |
return transfer(id, _rewards[id].receiver, _rewards[id].amount); | |
} else if (isConditionAborted(id)) { | |
return transfer(id, _rewards[id].sender, _rewards[id].amount); | |
} | |
} | |
return false; | |
} | |
function transfer(bytes32 id, address receiver, uint256 amount) private returns (bool) { | |
if (token.transfer(receiver, amount)) { | |
_rewards[id].amount -= amount; // TODO: SafeMath | |
return true; | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment