文件 1 的 1:PayResolver.sol
pragma solidity ^0.5.0;
library Pb {
enum WireType { Varint, Fixed64, LengthDelim, StartGroup, EndGroup, Fixed32 }
struct Buffer {
uint idx;
bytes b;
}
function fromBytes(bytes memory raw) internal pure returns (Buffer memory buf) {
buf.b = raw;
buf.idx = 0;
}
function hasMore(Buffer memory buf) internal pure returns (bool) {
return buf.idx < buf.b.length;
}
function decKey(Buffer memory buf) internal pure returns (uint tag, WireType wiretype) {
uint v = decVarint(buf);
tag = v / 8;
wiretype = WireType(v & 7);
}
function cntTags(Buffer memory buf, uint maxtag) internal pure returns (uint[] memory cnts) {
uint originalIdx = buf.idx;
cnts = new uint[](maxtag+1);
uint tag;
WireType wire;
while (hasMore(buf)) {
(tag, wire) = decKey(buf);
cnts[tag] += 1;
skipValue(buf, wire);
}
buf.idx = originalIdx;
}
function decVarint(Buffer memory buf) internal pure returns (uint v) {
bytes10 tmp;
bytes memory bb = buf.b;
v = buf.idx;
assembly {
tmp := mload(add(add(bb, 32), v))
}
uint b;
v = 0;
for (uint i=0; i<10; i++) {
assembly {
b := byte(i, tmp)
}
v |= (b & 0x7F) << (i * 7);
if (b & 0x80 == 0) {
buf.idx += i + 1;
return v;
}
}
revert();
}
function decBytes(Buffer memory buf) internal pure returns (bytes memory b) {
uint len = decVarint(buf);
uint end = buf.idx + len;
require(end <= buf.b.length);
b = new bytes(len);
bytes memory bufB = buf.b;
uint bStart;
uint bufBStart = buf.idx;
assembly {
bStart := add(b, 32)
bufBStart := add(add(bufB, 32), bufBStart)
}
for (uint i=0; i<len; i+=32) {
assembly{
mstore(add(bStart, i), mload(add(bufBStart, i)))
}
}
buf.idx = end;
}
function decPacked(Buffer memory buf) internal pure returns (uint[] memory t) {
uint len = decVarint(buf);
uint end = buf.idx + len;
require(end <= buf.b.length);
uint[] memory tmp = new uint[](len);
uint i = 0;
while (buf.idx < end) {
tmp[i] = decVarint(buf);
i++;
}
t = new uint[](i);
for (uint j=0; j<i; j++) {
t[j] = tmp[j];
}
return t;
}
function skipValue(Buffer memory buf, WireType wire) internal pure {
if (wire == WireType.Varint) { decVarint(buf); }
else if (wire == WireType.LengthDelim) {
uint len = decVarint(buf);
buf.idx += len;
require(buf.idx <= buf.b.length);
} else { revert(); }
}
function _bool(uint x) internal pure returns (bool v) {
return x != 0;
}
function _uint256(bytes memory b) internal pure returns (uint256 v) {
require(b.length <= 32);
assembly { v := mload(add(b, 32)) }
v = v >> (8 * (32 - b.length));
}
function _address(bytes memory b) internal pure returns (address v) {
v = _addressPayable(b);
}
function _addressPayable(bytes memory b) internal pure returns (address payable v) {
require(b.length == 20);
assembly { v := div(mload(add(b, 32)), 0x1000000000000000000000000) }
}
function _bytes32(bytes memory b) internal pure returns (bytes32 v) {
require(b.length == 32);
assembly { v := mload(add(b, 32)) }
}
function uint8s(uint[] memory arr) internal pure returns (uint8[] memory t) {
t = new uint8[](arr.length);
for (uint i = 0; i < t.length; i++) { t[i] = uint8(arr[i]); }
}
function uint32s(uint[] memory arr) internal pure returns (uint32[] memory t) {
t = new uint32[](arr.length);
for (uint i = 0; i < t.length; i++) { t[i] = uint32(arr[i]); }
}
function uint64s(uint[] memory arr) internal pure returns (uint64[] memory t) {
t = new uint64[](arr.length);
for (uint i = 0; i < t.length; i++) { t[i] = uint64(arr[i]); }
}
function bools(uint[] memory arr) internal pure returns (bool[] memory t) {
t = new bool[](arr.length);
for (uint i = 0; i < t.length; i++) { t[i] = arr[i]!=0; }
}
}
pragma solidity ^0.5.0;
library PbChain {
using Pb for Pb.Buffer;
struct OpenChannelRequest {
bytes channelInitializer;
bytes[] sigs;
}
function decOpenChannelRequest(bytes memory raw) internal pure returns (OpenChannelRequest memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.sigs = new bytes[](cnts[2]);
cnts[2] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.channelInitializer = bytes(buf.decBytes());
}
else if (tag == 2) {
m.sigs[cnts[2]] = bytes(buf.decBytes());
cnts[2]++;
}
else { buf.skipValue(wire); }
}
}
struct CooperativeWithdrawRequest {
bytes withdrawInfo;
bytes[] sigs;
}
function decCooperativeWithdrawRequest(bytes memory raw) internal pure returns (CooperativeWithdrawRequest memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.sigs = new bytes[](cnts[2]);
cnts[2] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.withdrawInfo = bytes(buf.decBytes());
}
else if (tag == 2) {
m.sigs[cnts[2]] = bytes(buf.decBytes());
cnts[2]++;
}
else { buf.skipValue(wire); }
}
}
struct CooperativeSettleRequest {
bytes settleInfo;
bytes[] sigs;
}
function decCooperativeSettleRequest(bytes memory raw) internal pure returns (CooperativeSettleRequest memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.sigs = new bytes[](cnts[2]);
cnts[2] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.settleInfo = bytes(buf.decBytes());
}
else if (tag == 2) {
m.sigs[cnts[2]] = bytes(buf.decBytes());
cnts[2]++;
}
else { buf.skipValue(wire); }
}
}
struct ResolvePayByConditionsRequest {
bytes condPay;
bytes[] hashPreimages;
}
function decResolvePayByConditionsRequest(bytes memory raw) internal pure returns (ResolvePayByConditionsRequest memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.hashPreimages = new bytes[](cnts[2]);
cnts[2] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.condPay = bytes(buf.decBytes());
}
else if (tag == 2) {
m.hashPreimages[cnts[2]] = bytes(buf.decBytes());
cnts[2]++;
}
else { buf.skipValue(wire); }
}
}
struct SignedSimplexState {
bytes simplexState;
bytes[] sigs;
}
function decSignedSimplexState(bytes memory raw) internal pure returns (SignedSimplexState memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.sigs = new bytes[](cnts[2]);
cnts[2] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.simplexState = bytes(buf.decBytes());
}
else if (tag == 2) {
m.sigs[cnts[2]] = bytes(buf.decBytes());
cnts[2]++;
}
else { buf.skipValue(wire); }
}
}
struct SignedSimplexStateArray {
SignedSimplexState[] signedSimplexStates;
}
function decSignedSimplexStateArray(bytes memory raw) internal pure returns (SignedSimplexStateArray memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(1);
m.signedSimplexStates = new SignedSimplexState[](cnts[1]);
cnts[1] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.signedSimplexStates[cnts[1]] = decSignedSimplexState(buf.decBytes());
cnts[1]++;
}
else { buf.skipValue(wire); }
}
}
struct ChannelMigrationRequest {
bytes channelMigrationInfo;
bytes[] sigs;
}
function decChannelMigrationRequest(bytes memory raw) internal pure returns (ChannelMigrationRequest memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.sigs = new bytes[](cnts[2]);
cnts[2] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.channelMigrationInfo = bytes(buf.decBytes());
}
else if (tag == 2) {
m.sigs[cnts[2]] = bytes(buf.decBytes());
cnts[2]++;
}
else { buf.skipValue(wire); }
}
}
}
pragma solidity ^0.5.0;
library PbEntity {
using Pb for Pb.Buffer;
enum TokenType { INVALID, ETH, ERC20 }
function TokenTypes(uint[] memory arr) internal pure returns (TokenType[] memory t) {
t = new TokenType[](arr.length);
for (uint i = 0; i < t.length; i++) { t[i] = TokenType(arr[i]); }
}
enum TransferFunctionType { BOOLEAN_AND, BOOLEAN_OR, BOOLEAN_CIRCUIT, NUMERIC_ADD, NUMERIC_MAX, NUMERIC_MIN }
function TransferFunctionTypes(uint[] memory arr) internal pure returns (TransferFunctionType[] memory t) {
t = new TransferFunctionType[](arr.length);
for (uint i = 0; i < t.length; i++) { t[i] = TransferFunctionType(arr[i]); }
}
enum ConditionType { HASH_LOCK, DEPLOYED_CONTRACT, VIRTUAL_CONTRACT }
function ConditionTypes(uint[] memory arr) internal pure returns (ConditionType[] memory t) {
t = new ConditionType[](arr.length);
for (uint i = 0; i < t.length; i++) { t[i] = ConditionType(arr[i]); }
}
struct AccountAmtPair {
address account;
uint256 amt;
}
function decAccountAmtPair(bytes memory raw) internal pure returns (AccountAmtPair memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.account = Pb._address(buf.decBytes());
}
else if (tag == 2) {
m.amt = Pb._uint256(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct TokenInfo {
TokenType tokenType;
address tokenAddress;
}
function decTokenInfo(bytes memory raw) internal pure returns (TokenInfo memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.tokenType = TokenType(buf.decVarint());
}
else if (tag == 2) {
m.tokenAddress = Pb._address(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct TokenDistribution {
TokenInfo token;
AccountAmtPair[] distribution;
}
function decTokenDistribution(bytes memory raw) internal pure returns (TokenDistribution memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.distribution = new AccountAmtPair[](cnts[2]);
cnts[2] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.token = decTokenInfo(buf.decBytes());
}
else if (tag == 2) {
m.distribution[cnts[2]] = decAccountAmtPair(buf.decBytes());
cnts[2]++;
}
else { buf.skipValue(wire); }
}
}
struct TokenTransfer {
TokenInfo token;
AccountAmtPair receiver;
}
function decTokenTransfer(bytes memory raw) internal pure returns (TokenTransfer memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.token = decTokenInfo(buf.decBytes());
}
else if (tag == 2) {
m.receiver = decAccountAmtPair(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct SimplexPaymentChannel {
bytes32 channelId;
address peerFrom;
uint seqNum;
TokenTransfer transferToPeer;
PayIdList pendingPayIds;
uint lastPayResolveDeadline;
uint256 totalPendingAmount;
}
function decSimplexPaymentChannel(bytes memory raw) internal pure returns (SimplexPaymentChannel memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.channelId = Pb._bytes32(buf.decBytes());
}
else if (tag == 2) {
m.peerFrom = Pb._address(buf.decBytes());
}
else if (tag == 3) {
m.seqNum = uint(buf.decVarint());
}
else if (tag == 4) {
m.transferToPeer = decTokenTransfer(buf.decBytes());
}
else if (tag == 5) {
m.pendingPayIds = decPayIdList(buf.decBytes());
}
else if (tag == 6) {
m.lastPayResolveDeadline = uint(buf.decVarint());
}
else if (tag == 7) {
m.totalPendingAmount = Pb._uint256(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct PayIdList {
bytes32[] payIds;
bytes32 nextListHash;
}
function decPayIdList(bytes memory raw) internal pure returns (PayIdList memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(2);
m.payIds = new bytes32[](cnts[1]);
cnts[1] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.payIds[cnts[1]] = Pb._bytes32(buf.decBytes());
cnts[1]++;
}
else if (tag == 2) {
m.nextListHash = Pb._bytes32(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct TransferFunction {
TransferFunctionType logicType;
TokenTransfer maxTransfer;
}
function decTransferFunction(bytes memory raw) internal pure returns (TransferFunction memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.logicType = TransferFunctionType(buf.decVarint());
}
else if (tag == 2) {
m.maxTransfer = decTokenTransfer(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct ConditionalPay {
uint payTimestamp;
address src;
address dest;
Condition[] conditions;
TransferFunction transferFunc;
uint resolveDeadline;
uint resolveTimeout;
address payResolver;
}
function decConditionalPay(bytes memory raw) internal pure returns (ConditionalPay memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(8);
m.conditions = new Condition[](cnts[4]);
cnts[4] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.payTimestamp = uint(buf.decVarint());
}
else if (tag == 2) {
m.src = Pb._address(buf.decBytes());
}
else if (tag == 3) {
m.dest = Pb._address(buf.decBytes());
}
else if (tag == 4) {
m.conditions[cnts[4]] = decCondition(buf.decBytes());
cnts[4]++;
}
else if (tag == 5) {
m.transferFunc = decTransferFunction(buf.decBytes());
}
else if (tag == 6) {
m.resolveDeadline = uint(buf.decVarint());
}
else if (tag == 7) {
m.resolveTimeout = uint(buf.decVarint());
}
else if (tag == 8) {
m.payResolver = Pb._address(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct CondPayResult {
bytes condPay;
uint256 amount;
}
function decCondPayResult(bytes memory raw) internal pure returns (CondPayResult memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.condPay = bytes(buf.decBytes());
}
else if (tag == 2) {
m.amount = Pb._uint256(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct VouchedCondPayResult {
bytes condPayResult;
bytes sigOfSrc;
bytes sigOfDest;
}
function decVouchedCondPayResult(bytes memory raw) internal pure returns (VouchedCondPayResult memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.condPayResult = bytes(buf.decBytes());
}
else if (tag == 2) {
m.sigOfSrc = bytes(buf.decBytes());
}
else if (tag == 3) {
m.sigOfDest = bytes(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct Condition {
ConditionType conditionType;
bytes32 hashLock;
address deployedContractAddress;
bytes32 virtualContractAddress;
bytes argsQueryFinalization;
bytes argsQueryOutcome;
}
function decCondition(bytes memory raw) internal pure returns (Condition memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.conditionType = ConditionType(buf.decVarint());
}
else if (tag == 2) {
m.hashLock = Pb._bytes32(buf.decBytes());
}
else if (tag == 3) {
m.deployedContractAddress = Pb._address(buf.decBytes());
}
else if (tag == 4) {
m.virtualContractAddress = Pb._bytes32(buf.decBytes());
}
else if (tag == 5) {
m.argsQueryFinalization = bytes(buf.decBytes());
}
else if (tag == 6) {
m.argsQueryOutcome = bytes(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct CooperativeWithdrawInfo {
bytes32 channelId;
uint seqNum;
AccountAmtPair withdraw;
uint withdrawDeadline;
bytes32 recipientChannelId;
}
function decCooperativeWithdrawInfo(bytes memory raw) internal pure returns (CooperativeWithdrawInfo memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.channelId = Pb._bytes32(buf.decBytes());
}
else if (tag == 2) {
m.seqNum = uint(buf.decVarint());
}
else if (tag == 3) {
m.withdraw = decAccountAmtPair(buf.decBytes());
}
else if (tag == 4) {
m.withdrawDeadline = uint(buf.decVarint());
}
else if (tag == 5) {
m.recipientChannelId = Pb._bytes32(buf.decBytes());
}
else { buf.skipValue(wire); }
}
}
struct PaymentChannelInitializer {
TokenDistribution initDistribution;
uint openDeadline;
uint disputeTimeout;
uint msgValueReceiver;
}
function decPaymentChannelInitializer(bytes memory raw) internal pure returns (PaymentChannelInitializer memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.initDistribution = decTokenDistribution(buf.decBytes());
}
else if (tag == 2) {
m.openDeadline = uint(buf.decVarint());
}
else if (tag == 3) {
m.disputeTimeout = uint(buf.decVarint());
}
else if (tag == 4) {
m.msgValueReceiver = uint(buf.decVarint());
}
else { buf.skipValue(wire); }
}
}
struct CooperativeSettleInfo {
bytes32 channelId;
uint seqNum;
AccountAmtPair[] settleBalance;
uint settleDeadline;
}
function decCooperativeSettleInfo(bytes memory raw) internal pure returns (CooperativeSettleInfo memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint[] memory cnts = buf.cntTags(4);
m.settleBalance = new AccountAmtPair[](cnts[3]);
cnts[3] = 0;
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.channelId = Pb._bytes32(buf.decBytes());
}
else if (tag == 2) {
m.seqNum = uint(buf.decVarint());
}
else if (tag == 3) {
m.settleBalance[cnts[3]] = decAccountAmtPair(buf.decBytes());
cnts[3]++;
}
else if (tag == 4) {
m.settleDeadline = uint(buf.decVarint());
}
else { buf.skipValue(wire); }
}
}
struct ChannelMigrationInfo {
bytes32 channelId;
address fromLedgerAddress;
address toLedgerAddress;
uint migrationDeadline;
}
function decChannelMigrationInfo(bytes memory raw) internal pure returns (ChannelMigrationInfo memory m) {
Pb.Buffer memory buf = Pb.fromBytes(raw);
uint tag;
Pb.WireType wire;
while (buf.hasMore()) {
(tag, wire) = buf.decKey();
if (false) {}
else if (tag == 1) {
m.channelId = Pb._bytes32(buf.decBytes());
}
else if (tag == 2) {
m.fromLedgerAddress = Pb._address(buf.decBytes());
}
else if (tag == 3) {
m.toLedgerAddress = Pb._address(buf.decBytes());
}
else if (tag == 4) {
m.migrationDeadline = uint(buf.decVarint());
}
else { buf.skipValue(wire); }
}
}
}
pragma solidity ^0.5.1;
interface IPayRegistry {
function calculatePayId(bytes32 _payHash, address _setter) external pure returns(bytes32);
function setPayAmount(bytes32 _payHash, uint _amt) external;
function setPayDeadline(bytes32 _payHash, uint _deadline) external;
function setPayInfo(bytes32 _payHash, uint _amt, uint _deadline) external;
function setPayAmounts(bytes32[] calldata _payHashes, uint[] calldata _amts) external;
function setPayDeadlines(bytes32[] calldata _payHashes, uint[] calldata _deadlines) external;
function setPayInfos(bytes32[] calldata _payHashes, uint[] calldata _amts, uint[] calldata _deadlines) external;
function getPayAmounts(
bytes32[] calldata _payIds,
uint _lastPayResolveDeadline
) external view returns(uint[] memory);
function getPayInfo(bytes32 _payId) external view returns(uint, uint);
event PayInfoUpdate(bytes32 indexed payId, uint amount, uint resolveDeadline);
}
pragma solidity ^0.5.1;
interface IPayResolver {
function resolvePaymentByConditions(bytes calldata _resolvePayRequest) external;
function resolvePaymentByVouchedResult(bytes calldata _vouchedPayResult) external;
event ResolvePayment(bytes32 indexed payId, uint amount, uint resolveDeadline);
}
pragma solidity ^0.5.0;
interface IBooleanCond {
function isFinalized(bytes calldata _query) external view returns (bool);
function getOutcome(bytes calldata _query) external view returns (bool);
}
pragma solidity ^0.5.0;
interface INumericCond {
function isFinalized(bytes calldata _query) external view returns (bool);
function getOutcome(bytes calldata _query) external view returns (uint);
}
pragma solidity ^0.5.1;
interface IVirtContractResolver {
function deploy(bytes calldata _code, uint _nonce) external returns (bool);
function resolve(bytes32 _virtAddr) external view returns (address);
event Deploy(bytes32 indexed virtAddr);
}
pragma solidity ^0.5.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
pragma solidity ^0.5.0;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
pragma solidity ^0.5.0;
library ECDSA {
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
if (signature.length != 65) {
return (address(0));
}
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return (address(0));
} else {
return ecrecover(hash, v, r, s);
}
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}
pragma solidity ^0.5.1;
contract PayResolver is IPayResolver {
using SafeMath for uint;
using ECDSA for bytes32;
IPayRegistry public payRegistry;
IVirtContractResolver public virtResolver;
constructor(address _registryAddr, address _virtResolverAddr) public {
payRegistry = IPayRegistry(_registryAddr);
virtResolver = IVirtContractResolver(_virtResolverAddr);
}
function resolvePaymentByConditions(bytes calldata _resolvePayRequest) external {
PbChain.ResolvePayByConditionsRequest memory resolvePayRequest =
PbChain.decResolvePayByConditionsRequest(_resolvePayRequest);
PbEntity.ConditionalPay memory pay = PbEntity.decConditionalPay(resolvePayRequest.condPay);
uint amount;
PbEntity.TransferFunctionType funcType = pay.transferFunc.logicType;
if (funcType == PbEntity.TransferFunctionType.BOOLEAN_AND) {
amount = _calculateBooleanAndPayment(pay, resolvePayRequest.hashPreimages);
} else if (funcType == PbEntity.TransferFunctionType.BOOLEAN_OR) {
amount = _calculateBooleanOrPayment(pay, resolvePayRequest.hashPreimages);
} else if (_isNumericLogic(funcType)) {
amount = _calculateNumericLogicPayment(pay, resolvePayRequest.hashPreimages, funcType);
} else {
assert(false);
}
bytes32 payHash = keccak256(resolvePayRequest.condPay);
_resolvePayment(pay, payHash, amount);
}
function resolvePaymentByVouchedResult(bytes calldata _vouchedPayResult) external {
PbEntity.VouchedCondPayResult memory vouchedPayResult =
PbEntity.decVouchedCondPayResult(_vouchedPayResult);
PbEntity.CondPayResult memory payResult =
PbEntity.decCondPayResult(vouchedPayResult.condPayResult);
PbEntity.ConditionalPay memory pay = PbEntity.decConditionalPay(payResult.condPay);
require(
payResult.amount <= pay.transferFunc.maxTransfer.receiver.amt,
"Exceed max transfer amount"
);
bytes32 hash = keccak256(vouchedPayResult.condPayResult).toEthSignedMessageHash();
address recoveredSrc = hash.recover(vouchedPayResult.sigOfSrc);
address recoveredDest = hash.recover(vouchedPayResult.sigOfDest);
require(
recoveredSrc == address(pay.src) && recoveredDest == address(pay.dest),
"Check sigs failed"
);
bytes32 payHash = keccak256(payResult.condPay);
_resolvePayment(pay, payHash, payResult.amount);
}
function _resolvePayment(
PbEntity.ConditionalPay memory _pay,
bytes32 _payHash,
uint _amount
)
internal
{
uint blockNumber = block.number;
require(blockNumber <= _pay.resolveDeadline, "Passed pay resolve deadline in condPay msg");
bytes32 payId = _calculatePayId(_payHash, address(this));
(uint currentAmt, uint currentDeadline) = payRegistry.getPayInfo(payId);
require(
currentDeadline == 0 || blockNumber <= currentDeadline,
"Passed onchain resolve pay deadline"
);
if (currentDeadline > 0) {
require(_amount > currentAmt, "New amount is not larger");
if (_amount == _pay.transferFunc.maxTransfer.receiver.amt) {
payRegistry.setPayInfo(_payHash, _amount, blockNumber);
emit ResolvePayment(payId, _amount, blockNumber);
} else {
payRegistry.setPayAmount(_payHash, _amount);
emit ResolvePayment(payId, _amount, currentDeadline);
}
} else {
uint newDeadline;
if (_amount == _pay.transferFunc.maxTransfer.receiver.amt) {
newDeadline = blockNumber;
} else {
newDeadline = Math.min(
blockNumber.add(_pay.resolveTimeout),
_pay.resolveDeadline
);
require(newDeadline > 0, "New resolve deadline is 0");
}
payRegistry.setPayInfo(_payHash, _amount, newDeadline);
emit ResolvePayment(payId, _amount, newDeadline);
}
}
function _calculateBooleanAndPayment(
PbEntity.ConditionalPay memory _pay,
bytes[] memory _preimages
)
internal
view
returns(uint)
{
uint j = 0;
bool hasFalseContractCond = false;
for (uint i = 0; i < _pay.conditions.length; i++) {
PbEntity.Condition memory cond = _pay.conditions[i];
if (cond.conditionType == PbEntity.ConditionType.HASH_LOCK) {
require(keccak256(_preimages[j]) == cond.hashLock, "Wrong preimage");
j++;
} else if (
cond.conditionType == PbEntity.ConditionType.DEPLOYED_CONTRACT ||
cond.conditionType == PbEntity.ConditionType.VIRTUAL_CONTRACT
) {
address addr = _getCondAddress(cond);
IBooleanCond dependent = IBooleanCond(addr);
require(dependent.isFinalized(cond.argsQueryFinalization), "Condition is not finalized");
if (!dependent.getOutcome(cond.argsQueryOutcome)) {
hasFalseContractCond = true;
}
} else {
assert(false);
}
}
if (hasFalseContractCond) {
return 0;
} else {
return _pay.transferFunc.maxTransfer.receiver.amt;
}
}
function _calculateBooleanOrPayment(
PbEntity.ConditionalPay memory _pay,
bytes[] memory _preimages
)
internal
view
returns(uint)
{
uint j = 0;
bool hasContractCond = false;
bool hasTrueContractCond = false;
for (uint i = 0; i < _pay.conditions.length; i++) {
PbEntity.Condition memory cond = _pay.conditions[i];
if (cond.conditionType == PbEntity.ConditionType.HASH_LOCK) {
require(keccak256(_preimages[j]) == cond.hashLock, "Wrong preimage");
j++;
} else if (
cond.conditionType == PbEntity.ConditionType.DEPLOYED_CONTRACT ||
cond.conditionType == PbEntity.ConditionType.VIRTUAL_CONTRACT
) {
address addr = _getCondAddress(cond);
IBooleanCond dependent = IBooleanCond(addr);
require(dependent.isFinalized(cond.argsQueryFinalization), "Condition is not finalized");
hasContractCond = true;
if (dependent.getOutcome(cond.argsQueryOutcome)) {
hasTrueContractCond = true;
}
} else {
assert(false);
}
}
if (!hasContractCond || hasTrueContractCond) {
return _pay.transferFunc.maxTransfer.receiver.amt;
} else {
return 0;
}
}
function _calculateNumericLogicPayment(
PbEntity.ConditionalPay memory _pay,
bytes[] memory _preimages,
PbEntity.TransferFunctionType _funcType
)
internal
view
returns(uint)
{
uint amount = 0;
uint j = 0;
bool hasContractCond = false;
for (uint i = 0; i < _pay.conditions.length; i++) {
PbEntity.Condition memory cond = _pay.conditions[i];
if (cond.conditionType == PbEntity.ConditionType.HASH_LOCK) {
require(keccak256(_preimages[j]) == cond.hashLock, "Wrong preimage");
j++;
} else if (
cond.conditionType == PbEntity.ConditionType.DEPLOYED_CONTRACT ||
cond.conditionType == PbEntity.ConditionType.VIRTUAL_CONTRACT
) {
address addr = _getCondAddress(cond);
INumericCond dependent = INumericCond(addr);
require(dependent.isFinalized(cond.argsQueryFinalization), "Condition is not finalized");
if (_funcType == PbEntity.TransferFunctionType.NUMERIC_ADD) {
amount = amount.add(dependent.getOutcome(cond.argsQueryOutcome));
} else if (_funcType == PbEntity.TransferFunctionType.NUMERIC_MAX) {
amount = Math.max(amount, dependent.getOutcome(cond.argsQueryOutcome));
} else if (_funcType == PbEntity.TransferFunctionType.NUMERIC_MIN) {
if (hasContractCond) {
amount = Math.min(amount, dependent.getOutcome(cond.argsQueryOutcome));
} else {
amount = dependent.getOutcome(cond.argsQueryOutcome);
}
} else {
assert(false);
}
hasContractCond = true;
} else {
assert(false);
}
}
if (hasContractCond) {
require(amount <= _pay.transferFunc.maxTransfer.receiver.amt, "Exceed max transfer amount");
return amount;
} else {
return _pay.transferFunc.maxTransfer.receiver.amt;
}
}
function _getCondAddress(PbEntity.Condition memory _cond) internal view returns(address) {
if (_cond.conditionType == PbEntity.ConditionType.DEPLOYED_CONTRACT) {
return _cond.deployedContractAddress;
} else if (_cond.conditionType == PbEntity.ConditionType.VIRTUAL_CONTRACT) {
return virtResolver.resolve(_cond.virtualContractAddress);
} else {
assert(false);
}
}
function _isNumericLogic(PbEntity.TransferFunctionType _funcType) internal pure returns(bool) {
return _funcType == PbEntity.TransferFunctionType.NUMERIC_ADD ||
_funcType == PbEntity.TransferFunctionType.NUMERIC_MAX ||
_funcType == PbEntity.TransferFunctionType.NUMERIC_MIN;
}
function _calculatePayId(bytes32 _payHash, address _setter) internal pure returns(bytes32) {
return keccak256(abi.encodePacked(_payHash, _setter));
}
}