Skip to content

Instantly share code, notes, and snippets.

@diminator
Created January 11, 2019 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diminator/9efaa672d0ccf2b274c915db8c118648 to your computer and use it in GitHub Desktop.
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=
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;
}
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;
}
}
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;
}
}
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);
}
}
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