Skip to content
This repository has been archived by the owner on Dec 13, 2019. It is now read-only.

Commit

Permalink
[contract] Interpreters
Browse files Browse the repository at this point in the history
  • Loading branch information
ldct committed Apr 22, 2019
1 parent e0b8a84 commit 59245be
Show file tree
Hide file tree
Showing 34 changed files with 319 additions and 421 deletions.
51 changes: 15 additions & 36 deletions packages/apps/contracts/HighRollerApp.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
pragma solidity 0.5.7;
pragma experimental "ABIEncoderV2";

import "@counterfactual/contracts/contracts/CounterfactualApp.sol";

import "@counterfactual/contracts/contracts/interfaces/CounterfactualApp.sol";
import "@counterfactual/contracts/contracts/libs/TwoPartyLumpAsEth.sol";

/// @title High Roller App
/// @notice This contract allows the playing of a dice rolling game.
Expand Down Expand Up @@ -33,7 +33,6 @@ contract HighRollerApp is CounterfactualApp {
}

struct AppState {
address[2] playerAddrs;
Stage stage;
bytes32 salt;
bytes32 commitHash;
Expand Down Expand Up @@ -120,59 +119,39 @@ contract HighRollerApp is CounterfactualApp {
return abi.encode(nextState);
}

function resolve(bytes calldata encodedState, Transfer.Terms calldata terms)
function resolve(bytes calldata encodedState)
external
pure
returns (Transfer.Transaction memory)
returns (TwoPartyLumpAsEth.Resolution)
{
AppState memory state = abi.decode(encodedState, (AppState));
AppState memory appState = abi.decode(encodedState, (AppState));

uint256[] memory amounts = new uint256[](2);
address[] memory to = new address[](2);
to[0] = state.playerAddrs[0];
to[1] = state.playerAddrs[1];
bytes32 expectedCommitHash = keccak256(
abi.encodePacked(state.salt, state.playerFirstNumber)
abi.encodePacked(appState.salt, appState.playerFirstNumber)
);
if (expectedCommitHash == state.commitHash) {
amounts = getWinningAmounts(
state.playerFirstNumber, state.playerSecondNumber, terms.limit
if (expectedCommitHash == appState.commitHash) {
return getWinningAmounts(
appState.playerFirstNumber, appState.playerSecondNumber
);
} else {
amounts[0] = 0;
amounts[1] = terms.limit;
return TwoPartyLumpAsEth.Resolution.SEND_TO_ADDR_TWO;
}

bytes[] memory data = new bytes[](2);

return Transfer.Transaction(
terms.assetType,
terms.token,
to,
amounts,
data
);
}

function getWinningAmounts(uint256 num1, uint256 num2, uint256 termsLimit)
function getWinningAmounts(uint256 num1, uint256 num2)
public
pure
returns (uint256[] memory)
returns (TwoPartyLumpAsEth.Resolution)
{
uint256[] memory amounts = new uint256[](2);
bytes32 randomSalt = calculateRandomSalt(num1, num2);
(uint8 playerFirstTotal, uint8 playerSecondTotal) = highRoller(randomSalt);
if (playerFirstTotal > playerSecondTotal) {
amounts[0] = termsLimit;
amounts[1] = 0;
return TwoPartyLumpAsEth.Resolution.SEND_TO_ADDR_ONE;
} else if (playerFirstTotal < playerSecondTotal) {
amounts[0] = 0;
amounts[1] = termsLimit;
return TwoPartyLumpAsEth.Resolution.SEND_TO_ADDR_TWO;
} else {
amounts[0] = termsLimit / 2;
amounts[1] = termsLimit / 2;
return TwoPartyLumpAsEth.Resolution.SPLIT_AND_SEND_TO_BOTH_ADDRS;
}
return amounts;
}

function highRoller(bytes32 randomness)
Expand Down
30 changes: 5 additions & 25 deletions packages/apps/contracts/NimApp.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity 0.5.7;
pragma experimental "ABIEncoderV2";

import "@counterfactual/contracts/contracts/CounterfactualApp.sol";
import "@counterfactual/contracts/contracts/interfaces/CounterfactualApp.sol";


/*
Expand All @@ -16,7 +16,6 @@ contract NimApp is CounterfactualApp {
}

struct AppState {
address[2] players;
uint256 turnNum;
uint256[3] pileHeights;
}
Expand Down Expand Up @@ -64,35 +63,16 @@ contract NimApp is CounterfactualApp {
return abi.encode(ret);
}

function resolve(
bytes calldata encodedState, Transfer.Terms calldata terms
)
function resolve(bytes calldata encodedState)
external
pure
returns (Transfer.Transaction memory)
returns (bytes memory)
{
AppState memory state = abi.decode(encodedState, (AppState));

require(isWin(state), "Resolution state was not in a winning position");
address loser = state.players[state.turnNum % 2];
address winner = state.players[1 - (state.turnNum % 2)];

uint256[] memory amounts = new uint256[](2);
amounts[0] = terms.limit;
amounts[1] = 0;

address[] memory to = new address[](2);
to[0] = loser;
to[1] = winner;
bytes[] memory data = new bytes[](2);

return Transfer.Transaction(
terms.assetType,
terms.token,
to,
amounts,
data
);

return abi.encodePacked(state.turnNum % 2);
}

function isWin(AppState memory state)
Expand Down
66 changes: 66 additions & 0 deletions packages/apps/contracts/PreimageApp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
pragma solidity 0.5.7;
pragma experimental "ABIEncoderV2";

import "@counterfactual/contracts/contracts/interfaces/CounterfactualApp.sol";


contract PreimageApp is CounterfactualApp {

struct AppState {
bytes32 image;
bool preimageRevealed;
}

struct Action {
bytes preimage;
}

function isStateTerminal(bytes memory encodedState)
public
pure
returns (bool)
{
AppState memory state = abi.decode(encodedState, (AppState));
return state.preimageRevealed;
}

function getTurnTaker(bytes memory /* encodedState */, address[] memory signingKeys)
public
pure
returns (address)
{
return signingKeys[0];
}

function applyAction(bytes memory encodedState, bytes memory encodedAction)
public
pure
returns (bytes memory)
{
AppState memory state = abi.decode(encodedState, (AppState));
Action memory action = abi.decode(encodedAction, (Action));

require(!state.preimageRevealed, "No actions possible after preimage revealed");

AppState memory nextState = state;

if (keccak256(action.preimage) == state.image) {
nextState.preimageRevealed = true;
}
return abi.encode(nextState);
}

function resolve(bytes memory encodedState)
public
pure
returns (bytes memory)
{
AppState memory state = abi.decode(encodedState, (AppState));

if (state.preimageRevealed) {
return abi.encode(1);
} else {
return abi.encode(0);
}
}
}
42 changes: 5 additions & 37 deletions packages/apps/contracts/TicTacToeApp.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pragma solidity 0.5.7;
pragma experimental "ABIEncoderV2";

import "@counterfactual/contracts/contracts/CounterfactualApp.sol";
import "@counterfactual/contracts/contracts/interfaces/CounterfactualApp.sol";


contract TicTacToeApp is CounterfactualApp {
Expand Down Expand Up @@ -102,50 +102,18 @@ contract TicTacToeApp is CounterfactualApp {
return abi.encode(postState);
}

function resolve(bytes calldata encodedState, Transfer.Terms calldata terms)
function resolve(bytes calldata encodedState)
external
pure
returns (Transfer.Transaction memory)
returns (bytes memory)
{
AppState memory state = abi.decode(encodedState, (AppState));
require(state.winner != 0, "Winner was set to 0; invalid");

uint256[] memory amounts = new uint256[](2);
address[] memory to = new address[](2);
bytes[] memory data = new bytes[](2);

if (state.winner == 3) {
amounts[0] = terms.limit / 2;
amounts[1] = terms.limit / 2;

to[0] = state.players[0];
to[1] = state.players[1];

return Transfer.Transaction(
terms.assetType,
terms.token,
to,
amounts,
data
);

return abi.encode(uint256(2));
} else {
address winner = state.players[state.winner - 1];
address loser = state.players[2 - state.winner];

amounts[0] = terms.limit;
amounts[1] = 0;

to[0] = winner;
to[1] = loser;

return Transfer.Transaction(
terms.assetType,
terms.token,
to,
amounts,
data
);
return abi.encode(state.winner - 1);
}

}
Expand Down
62 changes: 17 additions & 45 deletions packages/contracts/contracts/ETHVirtualAppAgreement.sol
Original file line number Diff line number Diff line change
@@ -1,36 +1,28 @@
pragma solidity 0.5.7;
pragma experimental "ABIEncoderV2";

import "./libs/Transfer.sol";
import "./AppRegistry.sol";
import "./NonceRegistry.sol";

/// todo(xuanji): rename to TwoPartyLumpAsEthVirtualApp

/// @title ETHVirtualAppAgreement
/// @notice Commitment target to support "virtual apps", i.e., apps which have
/// ETH committed to them via intermediary lock-up instead of having ETH directly
/// committed in a ledger channel.
/// The `target` contract must return via getResolution the outcome of the app
/// with the same asset type as `agreement.terms`. The value of the resolution
/// to the target's first beneficiary (i.e., `resolution.value[0]`) is
/// treated as the amount assigned to our first beneficiary (i.e.,
/// `agreement.beneficiaries[0]`). Note that `terms.limit` is explicitly
/// ignored since limits are enforced by `capitalProvided`.
/// The `target` contract must return via getResolution the outcome of the app,
/// and must return lump type.
contract ETHVirtualAppAgreement {

using Transfer for Transfer.Transaction;
using Transfer for Transfer.Terms;

// todo(xuanji): is it possible to make address(registry) a constant specified
// at link time?
struct Agreement {
AppRegistry registry;
NonceRegistry nonceRegistry;
Transfer.Terms terms;
uint256 expiry;
bytes32 appIdentityHash;
uint256 capitalProvided;
address[2] beneficiaries;
address payable[2] beneficiaries;
bytes32 uninstallKey;
}

Expand All @@ -40,50 +32,30 @@ contract ETHVirtualAppAgreement {
"agreement lockup time has not elapsed"
);

Transfer.Transaction memory resolution = agreement.registry
bytes memory resolution = agreement.registry
.getResolution(agreement.appIdentityHash);

require(
agreement.terms.assetType == resolution.assetType,
"returned incompatible resolution based on bad asset type"
);

require(
agreement.terms.token == resolution.token,
"returned incompatible resolution based on bad token value"
);

require(
agreement.capitalProvided > resolution.value[0],
"returned incompatible resolution"
);
uint256 resolutionAsValue = abi.decode(resolution, (uint256));

require(
!agreement.nonceRegistry.isFinalizedOrHasNeverBeenSetBefore(agreement.uninstallKey, 1),
"Virtual app agreement has been uninstalled"
);

uint256[] memory amount = new uint256[](2);

amount[0] = resolution.value[0];
amount[1] = agreement.capitalProvided - amount[0];
if (resolutionAsValue == 0) {
agreement.beneficiaries[0].send(agreement.capitalProvided);
return;
} else if (resolutionAsValue == 1) {
agreement.beneficiaries[1].send(agreement.capitalProvided);
return;
}

bytes[] memory data = new bytes[](2);
/* SPLIT_AND_SEND_TO_BOTH_ADDRS or default cases */

address[] memory beneficiaries = new address[](2);

beneficiaries[0] = agreement.beneficiaries[0];
beneficiaries[1] = agreement.beneficiaries[1];

Transfer.Transaction memory ret = Transfer.Transaction(
agreement.terms.assetType,
agreement.terms.token,
beneficiaries,
amount,
data
);
agreement.beneficiaries[0].transfer(agreement.capitalProvided / 2);
agreement.beneficiaries[1].transfer(agreement.capitalProvided - agreement.capitalProvided / 2);

ret.execute();
return;
}

}
Loading

0 comments on commit 59245be

Please sign in to comment.