diff --git a/README.md b/README.md index 727cb51..5f4d457 100644 --- a/README.md +++ b/README.md @@ -33,23 +33,14 @@ Truffle 3. In terminal```truffle migrate``` #### Deploying to Matic -1. ```npm install truffle -g``` - -Mumbai Testnet configured in ```./truffle-config.js``` - -Test deployment using Truffle against a runnning Ganache instance: ```truffle migrate``` -Deploy to Mumbai testnet: ```truffle migrate --network matic``` - -Verify contract address at the [Matic Explorer](https://explorer-mumbai.maticvigil.com/) +Deployment to the Mumbai Testnet is configured in ```./truffle-config.js``` -*Verifying & publishing the contract code* - -In the [Matic Explorer](https://explorer-mumbai.maticvigil.com/) find your contract based on the address reported by Truffle. -Go to the tab ```Code``` - -Flattening contract: https://github.com/poanetwork/solidity-flattener and cleanup SPDX licenses and _Chainlink appended to classes like SafeMath, Buffer and ENSResolver +1. ```npm install truffle -g``` +2. Deploy to Mumbai testnet: ```truffle migrate --network matic``` +3. Find your contract based on the address reported by Truffle in the [Matic Explorer](https://explorer-mumbai.maticvigil.com/). -Quite note on setting up Matic: +Quite note on deploying to Matic: +* Test deployment using Truffle against a runnning Ganache instance: ```truffle migrate``` * Configure Matic network in [MetaMask](https://docs.matic.network/docs/develop/metamask/config-matic/) * Request funds at [faucet](https://faucet.matic.network/) * Use this wallet's seed phrase in the .env file to pay the deployment @@ -69,7 +60,7 @@ After deploying to a local node Example for interacting: ```await commitPool.withdraw(1000)``` ## Features -[Technical documentation](https://ipfs.io/ipfs/QmdJsGYi822G1azEMtGL39LRwXZtJRC58KT393TGPixP6z) +[Technical documentation](https://ipfs.io/ipfs/https://ipfs.io/ipfs/QmVrBwsQ67RE9CVzyQRvDucK4LrjgB7tkAserztyBDNfJi) #### Creation of Commitment A commitment consists of an ```activity```, a ```goalValue``` for given activity, a ```startTime```, and ```stake```. We will automagically set the ```endTime``` 7 days after the startdate. diff --git a/contracts/SinglePlayerCommit.sol b/contracts/SinglePlayerCommit.sol index 1e1c7b7..77ab667 100644 --- a/contracts/SinglePlayerCommit.sol +++ b/contracts/SinglePlayerCommit.sol @@ -274,7 +274,7 @@ contract SinglePlayerCommit is ChainlinkClient, Ownable { /// @notice Internal function for evaluating commitment and slashing funds if needed /// @dev Receive call with commitment object from storage function _settleCommitment(Commitment storage commitment) internal returns (bool success) { - commitment.met = commitment.reportedValue > commitment.goalValue; + commitment.met = commitment.reportedValue >= commitment.goalValue; if (!commitment.met) { _slashFunds(commitment.stake, msg.sender); @@ -481,7 +481,7 @@ contract SinglePlayerCommit is ChainlinkClient, Ownable { /// @notice Get address for ChainLink token contract /// @dev ChainLink contract method - function getChainlinkToken() public view returns (address chainlinkTokenAddress) { + function getChainlinkToken() public view returns (address tokenAddress) { return chainlinkTokenAddress(); } diff --git a/out/SinglePlayerCommit_flat.sol b/out/SinglePlayerCommit_flat.sol deleted file mode 100644 index bf88b3b..0000000 --- a/out/SinglePlayerCommit_flat.sol +++ /dev/null @@ -1,3218 +0,0 @@ - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/vendor/SafeMathChainlink.sol - -pragma solidity ^0.6.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMathChainlink { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a, "SafeMath: subtraction overflow"); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/vendor/ENSResolver.sol - -pragma solidity ^0.6.0; - -abstract contract ENSResolver { - function addr(bytes32 node) public view virtual returns (address); -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/interfaces/PointerInterface.sol - -pragma solidity ^0.6.0; - -interface PointerInterface { - function getAddress() external view returns (address); -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/interfaces/ChainlinkRequestInterface.sol - -pragma solidity ^0.6.0; - -interface ChainlinkRequestInterface { - function oracleRequest( - address sender, - uint256 requestPrice, - bytes32 serviceAgreementID, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external; - - function cancelOracleRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunctionId, - uint256 expiration - ) external; -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/interfaces/LinkTokenInterface.sol - -pragma solidity ^0.6.0; - -interface LinkTokenInterface { - function allowance(address owner, address spender) external view returns (uint256 remaining); - function approve(address spender, uint256 value) external returns (bool success); - function balanceOf(address owner) external view returns (uint256 balance); - function decimals() external view returns (uint8 decimalPlaces); - function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); - function increaseApproval(address spender, uint256 subtractedValue) external; - function name() external view returns (string memory tokenName); - function symbol() external view returns (string memory tokenSymbol); - function totalSupply() external view returns (uint256 totalTokensIssued); - function transfer(address to, uint256 value) external returns (bool success); - function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); - function transferFrom(address from, address to, uint256 value) external returns (bool success); -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/interfaces/ENSInterface.sol - -pragma solidity ^0.6.0; - -interface ENSInterface { - - // Logged when the owner of a node assigns a new owner to a subnode. - event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); - - // Logged when the owner of a node transfers ownership to a new account. - event Transfer(bytes32 indexed node, address owner); - - // Logged when the resolver for a node changes. - event NewResolver(bytes32 indexed node, address resolver); - - // Logged when the TTL of a node changes - event NewTTL(bytes32 indexed node, uint64 ttl); - - - function setSubnodeOwner(bytes32 node, bytes32 label, address _owner) external; - function setResolver(bytes32 node, address _resolver) external; - function setOwner(bytes32 node, address _owner) external; - function setTTL(bytes32 node, uint64 _ttl) external; - function owner(bytes32 node) external view returns (address); - function resolver(bytes32 node) external view returns (address); - function ttl(bytes32 node) external view returns (uint64); - -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/vendor/BufferChainlink.sol - -pragma solidity ^0.6.0; - -/** -* @dev A library for working with mutable byte buffers in Solidity. -* -* Byte buffers are mutable and expandable, and provide a variety of primitives -* for writing to them. At any time you can fetch a bytes object containing the -* current contents of the buffer. The bytes object should not be stored between -* operations, as it may change due to resizing of the buffer. -*/ -library BufferChainlink { - /** - * @dev Represents a mutable buffer. Buffers have a current value (buf) and - * a capacity. The capacity may be longer than the current value, in - * which case it can be extended without the need to allocate more memory. - */ - struct buffer { - bytes buf; - uint capacity; - } - - /** - * @dev Initializes a buffer with an initial capacity. - * @param buf The buffer to initialize. - * @param capacity The number of bytes of space to allocate the buffer. - * @return The buffer, for chaining. - */ - function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) { - if (capacity % 32 != 0) { - capacity += 32 - (capacity % 32); - } - // Allocate space for the buffer data - buf.capacity = capacity; - assembly { - let ptr := mload(0x40) - mstore(buf, ptr) - mstore(ptr, 0) - mstore(0x40, add(32, add(ptr, capacity))) - } - return buf; - } - - /** - * @dev Initializes a new buffer from an existing bytes object. - * Changes to the buffer may mutate the original value. - * @param b The bytes object to initialize the buffer with. - * @return A new buffer. - */ - function fromBytes(bytes memory b) internal pure returns(buffer memory) { - buffer memory buf; - buf.buf = b; - buf.capacity = b.length; - return buf; - } - - function resize(buffer memory buf, uint capacity) private pure { - bytes memory oldbuf = buf.buf; - init(buf, capacity); - append(buf, oldbuf); - } - - function max(uint a, uint b) private pure returns(uint) { - if (a > b) { - return a; - } - return b; - } - - /** - * @dev Sets buffer length to 0. - * @param buf The buffer to truncate. - * @return The original buffer, for chaining.. - */ - function truncate(buffer memory buf) internal pure returns (buffer memory) { - assembly { - let bufptr := mload(buf) - mstore(bufptr, 0) - } - return buf; - } - - /** - * @dev Writes a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The start offset to write to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns(buffer memory) { - require(len <= data.length); - - if (off + len > buf.capacity) { - resize(buf, max(buf.capacity, len + off) * 2); - } - - uint dest; - uint src; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Start address = buffer address + offset + sizeof(buffer length) - dest := add(add(bufptr, 32), off) - // Update buffer length if we're extending it - if gt(add(len, off), buflen) { - mstore(bufptr, add(len, off)) - } - src := add(data, 32) - } - - // Copy word-length chunks while possible - for (; len >= 32; len -= 32) { - assembly { - mstore(dest, mload(src)) - } - dest += 32; - src += 32; - } - - // Copy remaining bytes - uint mask = 256 ** (32 - len) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - - return buf; - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data, uint len) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, len); - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, data.length); - } - - /** - * @dev Writes a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write the byte at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeUint8(buffer memory buf, uint off, uint8 data) internal pure returns(buffer memory) { - if (off >= buf.capacity) { - resize(buf, buf.capacity * 2); - } - - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Address = buffer address + sizeof(buffer length) + off - let dest := add(add(bufptr, off), 32) - mstore8(dest, data) - // Update buffer length if we extended it - if eq(off, buflen) { - mstore(bufptr, add(buflen, 1)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) { - return writeUint8(buf, buf.buf.length, data); - } - - /** - * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (left-aligned). - * @return The original buffer, for chaining. - */ - function write(buffer memory buf, uint off, bytes32 data, uint len) private pure returns(buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - uint mask = 256 ** len - 1; - // Right-align data - data = data >> (8 * (32 - len)); - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + sizeof(buffer length) + off + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - return buf; - } - - /** - * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeBytes20(buffer memory buf, uint off, bytes20 data) internal pure returns (buffer memory) { - return write(buf, off, bytes32(data), 20); - } - - /** - * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chhaining. - */ - function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, bytes32(data), 20); - } - - /** - * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, 32); - } - - /** - * @dev Writes an integer to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (right-aligned). - * @return The original buffer, for chaining. - */ - function writeInt(buffer memory buf, uint off, uint data, uint len) private pure returns(buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - uint mask = 256 ** len - 1; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + off + sizeof(buffer length) + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the end of the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer. - */ - function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { - return writeInt(buf, buf.buf.length, data, len); - } -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/vendor/CBORChainlink.sol - -pragma solidity ^0.6.0; - - -library CBORChainlink { - using BufferChainlink for BufferChainlink.buffer; - - uint8 private constant MAJOR_TYPE_INT = 0; - uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; - uint8 private constant MAJOR_TYPE_BYTES = 2; - uint8 private constant MAJOR_TYPE_STRING = 3; - uint8 private constant MAJOR_TYPE_ARRAY = 4; - uint8 private constant MAJOR_TYPE_MAP = 5; - uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; - - function encodeType(BufferChainlink.buffer memory buf, uint8 major, uint value) private pure { - if(value <= 23) { - buf.appendUint8(uint8((major << 5) | value)); - } else if(value <= 0xFF) { - buf.appendUint8(uint8((major << 5) | 24)); - buf.appendInt(value, 1); - } else if(value <= 0xFFFF) { - buf.appendUint8(uint8((major << 5) | 25)); - buf.appendInt(value, 2); - } else if(value <= 0xFFFFFFFF) { - buf.appendUint8(uint8((major << 5) | 26)); - buf.appendInt(value, 4); - } else if(value <= 0xFFFFFFFFFFFFFFFF) { - buf.appendUint8(uint8((major << 5) | 27)); - buf.appendInt(value, 8); - } - } - - function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure { - buf.appendUint8(uint8((major << 5) | 31)); - } - - function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure { - encodeType(buf, MAJOR_TYPE_INT, value); - } - - function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure { - if(value >= 0) { - encodeType(buf, MAJOR_TYPE_INT, uint(value)); - } else { - encodeType(buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - value)); - } - } - - function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure { - encodeType(buf, MAJOR_TYPE_BYTES, value.length); - buf.append(value); - } - - function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure { - encodeType(buf, MAJOR_TYPE_STRING, bytes(value).length); - buf.append(bytes(value)); - } - - function startArray(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); - } - - function startMap(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); - } - - function endSequence(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); - } -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/Chainlink.sol - -pragma solidity ^0.6.0; - - - -/** - * @title Library for common Chainlink functions - * @dev Uses imported CBOR library for encoding to buffer - */ -library Chainlink { - uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase - - using CBORChainlink for BufferChainlink.buffer; - - struct Request { - bytes32 id; - address callbackAddress; - bytes4 callbackFunctionId; - uint256 nonce; - BufferChainlink.buffer buf; - } - - /** - * @notice Initializes a Chainlink request - * @dev Sets the ID, callback address, and callback function signature on the request - * @param self The uninitialized request - * @param _id The Job Specification ID - * @param _callbackAddress The callback address - * @param _callbackFunction The callback function signature - * @return The initialized request - */ - function initialize( - Request memory self, - bytes32 _id, - address _callbackAddress, - bytes4 _callbackFunction - ) internal pure returns (Chainlink.Request memory) { - BufferChainlink.init(self.buf, defaultBufferSize); - self.id = _id; - self.callbackAddress = _callbackAddress; - self.callbackFunctionId = _callbackFunction; - return self; - } - - /** - * @notice Sets the data for the buffer without encoding CBOR on-chain - * @dev CBOR can be closed with curly-brackets {} or they can be left off - * @param self The initialized request - * @param _data The CBOR data - */ - function setBuffer(Request memory self, bytes memory _data) - internal pure - { - BufferChainlink.init(self.buf, _data.length); - BufferChainlink.append(self.buf, _data); - } - - /** - * @notice Adds a string value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The string value to add - */ - function add(Request memory self, string memory _key, string memory _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeString(_value); - } - - /** - * @notice Adds a bytes value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The bytes value to add - */ - function addBytes(Request memory self, string memory _key, bytes memory _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeBytes(_value); - } - - /** - * @notice Adds a int256 value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The int256 value to add - */ - function addInt(Request memory self, string memory _key, int256 _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeInt(_value); - } - - /** - * @notice Adds a uint256 value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The uint256 value to add - */ - function addUint(Request memory self, string memory _key, uint256 _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeUInt(_value); - } - - /** - * @notice Adds an array of strings to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _values The array of string values to add - */ - function addStringArray(Request memory self, string memory _key, string[] memory _values) - internal pure - { - self.buf.encodeString(_key); - self.buf.startArray(); - for (uint256 i = 0; i < _values.length; i++) { - self.buf.encodeString(_values[i]); - } - self.buf.endSequence(); - } -} - -// File: https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/ChainlinkClient.sol - -pragma solidity ^0.6.0; - - - - - - - - -/** - * @title The ChainlinkClient contract - * @notice Contract writers can inherit this contract in order to create requests for the - * Chainlink network - */ -contract ChainlinkClient { - using Chainlink for Chainlink.Request; - using SafeMathChainlink for uint256; - - uint256 constant internal LINK = 10**18; - uint256 constant private AMOUNT_OVERRIDE = 0; - address constant private SENDER_OVERRIDE = address(0); - uint256 constant private ARGS_VERSION = 1; - bytes32 constant private ENS_TOKEN_SUBNAME = keccak256("link"); - bytes32 constant private ENS_ORACLE_SUBNAME = keccak256("oracle"); - address constant private LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; - - ENSInterface private ens; - bytes32 private ensNode; - LinkTokenInterface private link; - ChainlinkRequestInterface private oracle; - uint256 private requestCount = 1; - mapping(bytes32 => address) private pendingRequests; - - event ChainlinkRequested(bytes32 indexed id); - event ChainlinkFulfilled(bytes32 indexed id); - event ChainlinkCancelled(bytes32 indexed id); - - /** - * @notice Creates a request that can hold additional parameters - * @param _specId The Job Specification ID that the request will be created for - * @param _callbackAddress The callback address that the response will be sent to - * @param _callbackFunctionSignature The callback function signature to use for the callback address - * @return A Chainlink Request struct in memory - */ - function buildChainlinkRequest( - bytes32 _specId, - address _callbackAddress, - bytes4 _callbackFunctionSignature - ) internal pure returns (Chainlink.Request memory) { - Chainlink.Request memory req; - return req.initialize(_specId, _callbackAddress, _callbackFunctionSignature); - } - - /** - * @notice Creates a Chainlink request to the stored oracle address - * @dev Calls `chainlinkRequestTo` with the stored oracle address - * @param _req The initialized Chainlink Request - * @param _payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendChainlinkRequest(Chainlink.Request memory _req, uint256 _payment) - internal - returns (bytes32) - { - return sendChainlinkRequestTo(address(oracle), _req, _payment); - } - - /** - * @notice Creates a Chainlink request to the specified oracle address - * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to - * send LINK which creates a request on the target oracle contract. - * Emits ChainlinkRequested event. - * @param _oracle The address of the oracle for the request - * @param _req The initialized Chainlink Request - * @param _payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendChainlinkRequestTo(address _oracle, Chainlink.Request memory _req, uint256 _payment) - internal - returns (bytes32 requestId) - { - requestId = keccak256(abi.encodePacked(this, requestCount)); - _req.nonce = requestCount; - pendingRequests[requestId] = _oracle; - emit ChainlinkRequested(requestId); - require(link.transferAndCall(_oracle, _payment, encodeRequest(_req)), "unable to transferAndCall to oracle"); - requestCount += 1; - - return requestId; - } - - /** - * @notice Allows a request to be cancelled if it has not been fulfilled - * @dev Requires keeping track of the expiration value emitted from the oracle contract. - * Deletes the request from the `pendingRequests` mapping. - * Emits ChainlinkCancelled event. - * @param _requestId The request ID - * @param _payment The amount of LINK sent for the request - * @param _callbackFunc The callback function specified for the request - * @param _expiration The time of the expiration for the request - */ - function cancelChainlinkRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunc, - uint256 _expiration - ) - internal - { - ChainlinkRequestInterface requested = ChainlinkRequestInterface(pendingRequests[_requestId]); - delete pendingRequests[_requestId]; - emit ChainlinkCancelled(_requestId); - requested.cancelOracleRequest(_requestId, _payment, _callbackFunc, _expiration); - } - - /** - * @notice Sets the stored oracle address - * @param _oracle The address of the oracle contract - */ - function setChainlinkOracle(address _oracle) internal { - oracle = ChainlinkRequestInterface(_oracle); - } - - /** - * @notice Sets the LINK token address - * @param _link The address of the LINK token contract - */ - function setChainlinkToken(address _link) internal { - link = LinkTokenInterface(_link); - } - - /** - * @notice Sets the Chainlink token address for the public - * network as given by the Pointer contract - */ - function setPublicChainlinkToken() internal { - setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); - } - - /** - * @notice Retrieves the stored address of the LINK token - * @return The address of the LINK token - */ - function chainlinkTokenAddress() - internal - view - returns (address) - { - return address(link); - } - - /** - * @notice Retrieves the stored address of the oracle contract - * @return The address of the oracle contract - */ - function chainlinkOracleAddress() - internal - view - returns (address) - { - return address(oracle); - } - - /** - * @notice Allows for a request which was created on another contract to be fulfilled - * on this contract - * @param _oracle The address of the oracle contract that will fulfill the request - * @param _requestId The request ID used for the response - */ - function addChainlinkExternalRequest(address _oracle, bytes32 _requestId) - internal - notPendingRequest(_requestId) - { - pendingRequests[_requestId] = _oracle; - } - - /** - * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS - * @dev Accounts for subnodes having different resolvers - * @param _ens The address of the ENS contract - * @param _node The ENS node hash - */ - function useChainlinkWithENS(address _ens, bytes32 _node) - internal - { - ens = ENSInterface(_ens); - ensNode = _node; - bytes32 linkSubnode = keccak256(abi.encodePacked(ensNode, ENS_TOKEN_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(linkSubnode)); - setChainlinkToken(resolver.addr(linkSubnode)); - updateChainlinkOracleWithENS(); - } - - /** - * @notice Sets the stored oracle contract with the address resolved by ENS - * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously - */ - function updateChainlinkOracleWithENS() - internal - { - bytes32 oracleSubnode = keccak256(abi.encodePacked(ensNode, ENS_ORACLE_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(oracleSubnode)); - setChainlinkOracle(resolver.addr(oracleSubnode)); - } - - /** - * @notice Encodes the request to be sent to the oracle contract - * @dev The Chainlink node expects values to be in order for the request to be picked up. Order of types - * will be validated in the oracle contract. - * @param _req The initialized Chainlink Request - * @return The bytes payload for the `transferAndCall` method - */ - function encodeRequest(Chainlink.Request memory _req) - private - view - returns (bytes memory) - { - return abi.encodeWithSelector( - oracle.oracleRequest.selector, - SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address - AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent - _req.id, - _req.callbackAddress, - _req.callbackFunctionId, - _req.nonce, - ARGS_VERSION, - _req.buf.buf); - } - - /** - * @notice Ensures that the fulfillment is valid for this contract - * @dev Use if the contract developer prefers methods instead of modifiers for validation - * @param _requestId The request ID for fulfillment - */ - function validateChainlinkCallback(bytes32 _requestId) - internal - recordChainlinkFulfillment(_requestId) - // solhint-disable-next-line no-empty-blocks - {} - - /** - * @dev Reverts if the sender is not the oracle of the request. - * Emits ChainlinkFulfilled event. - * @param _requestId The request ID for fulfillment - */ - modifier recordChainlinkFulfillment(bytes32 _requestId) { - require(msg.sender == pendingRequests[_requestId], - "Source must be the oracle of the request"); - delete pendingRequests[_requestId]; - emit ChainlinkFulfilled(_requestId); - _; - } - - /** - * @dev Reverts if the request is already pending - * @param _requestId The request ID for fulfillment - */ - modifier notPendingRequest(bytes32 _requestId) { - require(pendingRequests[_requestId] == address(0), "Request is already pending"); - _; - } -} - -// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/token/ERC20/IERC20.sol - -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `sender` to `recipient` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); - - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/GSN/Context.sol - -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/* - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with GSN meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address payable) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes memory) { - this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} - -// File: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/access/Ownable.sol - -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * By default, the owner account will be the one that deploys the contract. This - * can later be changed with {transferOwnership}. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be applied to your functions to restrict their use to - * the owner. - */ -contract Ownable is Context { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor () internal { - address msgSender = _msgSender(); - _owner = msgSender; - emit OwnershipTransferred(address(0), msgSender); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(_owner == _msgSender(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Leaves the contract without owner. It will not be possible to call - * `onlyOwner` functions anymore. Can only be called by the current owner. - * - * NOTE: Renouncing ownership will leave the contract without an owner, - * thereby removing any functionality that is only available to the owner. - */ - function renounceOwnership() public virtual onlyOwner { - emit OwnershipTransferred(_owner, address(0)); - _owner = address(0); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public virtual onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } -} - -// File: https://github.com/nomiclabs/hardhat/blob/master/packages/hardhat-core/console.sol - -// SPDX-License-Identifier: MIT -pragma solidity >= 0.4.22 <0.8.0; - -library console { - address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); - - function _sendLogPayload(bytes memory payload) private view { - uint256 payloadLength = payload.length; - address consoleAddress = CONSOLE_ADDRESS; - assembly { - let payloadStart := add(payload, 32) - let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) - } - } - - function log() internal view { - _sendLogPayload(abi.encodeWithSignature("log()")); - } - - function logInt(int p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); - } - - function logUint(uint p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); - } - - function logString(string memory p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function logBool(bool p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function logAddress(address p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function logBytes(bytes memory p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); - } - - function logByte(byte p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(byte)", p0)); - } - - function logBytes1(bytes1 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); - } - - function logBytes2(bytes2 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); - } - - function logBytes3(bytes3 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); - } - - function logBytes4(bytes4 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); - } - - function logBytes5(bytes5 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); - } - - function logBytes6(bytes6 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); - } - - function logBytes7(bytes7 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); - } - - function logBytes8(bytes8 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); - } - - function logBytes9(bytes9 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); - } - - function logBytes10(bytes10 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); - } - - function logBytes11(bytes11 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); - } - - function logBytes12(bytes12 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); - } - - function logBytes13(bytes13 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); - } - - function logBytes14(bytes14 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); - } - - function logBytes15(bytes15 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); - } - - function logBytes16(bytes16 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); - } - - function logBytes17(bytes17 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); - } - - function logBytes18(bytes18 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); - } - - function logBytes19(bytes19 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); - } - - function logBytes20(bytes20 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); - } - - function logBytes21(bytes21 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); - } - - function logBytes22(bytes22 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); - } - - function logBytes23(bytes23 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); - } - - function logBytes24(bytes24 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); - } - - function logBytes25(bytes25 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); - } - - function logBytes26(bytes26 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); - } - - function logBytes27(bytes27 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); - } - - function logBytes28(bytes28 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); - } - - function logBytes29(bytes29 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); - } - - function logBytes30(bytes30 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); - } - - function logBytes31(bytes31 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); - } - - function logBytes32(bytes32 p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); - } - - function log(uint p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); - } - - function log(string memory p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function log(bool p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function log(address p0) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function log(uint p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); - } - - function log(uint p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); - } - - function log(uint p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); - } - - function log(uint p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); - } - - function log(string memory p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); - } - - function log(string memory p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); - } - - function log(string memory p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); - } - - function log(string memory p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); - } - - function log(bool p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); - } - - function log(bool p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); - } - - function log(bool p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); - } - - function log(bool p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); - } - - function log(address p0, uint p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); - } - - function log(address p0, string memory p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); - } - - function log(address p0, bool p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); - } - - function log(address p0, address p1) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); - } - - function log(uint p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); - } - - function log(uint p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); - } - - function log(uint p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); - } - - function log(uint p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); - } - - function log(uint p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); - } - - function log(uint p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); - } - - function log(uint p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); - } - - function log(uint p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); - } - - function log(uint p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); - } - - function log(uint p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); - } - - function log(uint p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); - } - - function log(uint p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); - } - - function log(uint p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); - } - - function log(uint p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); - } - - function log(uint p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); - } - - function log(uint p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); - } - - function log(string memory p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); - } - - function log(string memory p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); - } - - function log(string memory p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); - } - - function log(string memory p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); - } - - function log(string memory p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); - } - - function log(string memory p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); - } - - function log(string memory p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); - } - - function log(string memory p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); - } - - function log(bool p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); - } - - function log(bool p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); - } - - function log(bool p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); - } - - function log(bool p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); - } - - function log(bool p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); - } - - function log(bool p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); - } - - function log(bool p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); - } - - function log(bool p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); - } - - function log(bool p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); - } - - function log(bool p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); - } - - function log(bool p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); - } - - function log(bool p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); - } - - function log(address p0, uint p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); - } - - function log(address p0, uint p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); - } - - function log(address p0, uint p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); - } - - function log(address p0, uint p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); - } - - function log(address p0, string memory p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); - } - - function log(address p0, string memory p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); - } - - function log(address p0, string memory p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); - } - - function log(address p0, string memory p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); - } - - function log(address p0, bool p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); - } - - function log(address p0, bool p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); - } - - function log(address p0, bool p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); - } - - function log(address p0, bool p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); - } - - function log(address p0, address p1, uint p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); - } - - function log(address p0, address p1, string memory p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); - } - - function log(address p0, address p1, bool p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); - } - - function log(address p0, address p1, address p2) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); - } - - function log(uint p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); - } - - function log(uint p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, uint p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, string memory p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, bool p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, address p3) internal view { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); - } - -} - -// File: browser/SinglePlayerCommit.sol - -/* SPDX-License-Identifier: MIT */ -pragma solidity 0.6.10; -pragma experimental ABIEncoderV2; - - - - -//https://github.com/smartcontractkit/chainlink/issues/3153#issuecomment-655241638 - - -/// @title CommitPool single-player mode contract -/// @notice Enables staking and validating performance. No social/pool functionality. -contract SinglePlayerCommit is ChainlinkClient, Ownable { - using SafeMathChainlink for uint256; - - /****************** - GLOBAL CONSTANTS - ******************/ - IERC20 public token; - uint256 BIGGEST_NUMBER = uint256(-1); - uint256 constant private ORACLE_PAYMENT = 1 * LINK; - - /*************** - DATA TYPES - ***************/ - /// @notice Activity as part of commitment with oracle address. E.g. "cycling" with ChainLink Strava node - struct Activity { - string name; - address oracle; - bool allowed; - bool exists; - } - - struct Commitment { - address committer; // user - bytes32 activityKey; - uint256 goalValue; - uint256 startTime; - uint256 endTime; - uint256 stake; // amount of token staked, scaled by token decimals - uint256 reportedValue; // as reported by oracle - uint256 lastActivityUpdate; // when updated by oracle - bool met; // whether the commitment has been met - string userId; - bool exists; // flag to help check if commitment exists - } - - /*************** - EVENTS - ***************/ - event NewCommitment( - address committer, - string activityName, - uint256 goalValue, - uint256 startTime, - uint256 endTime, - uint256 stake - ); - event CommitmentEnded(address committer, bool met, uint256 amountPenalized); - event Deposit(address committer, uint256 amount); - event Withdrawal(address committer, uint256 amount); - event RequestActivityDistanceFulfilled( - bytes32 indexed requestId, - uint256 indexed distance - ); - event ActivityUpdated( - string name, - bytes32 activityKey, - address oracle, - bool allowed, - bool exists); - //TODO Error events - - - /****************** - INTERNAL ACCOUNTING - ******************/ - mapping(bytes32 => Activity) public activities; // get Activity object based on activity key - bytes32[] public activityKeyList; // List of activityKeys, used for indexing allowed activities - - mapping(address => Commitment) public commitments; // active commitments - // address[] public userCommitments; // addresses with active commitments - - mapping(address => uint256) public committerBalances; // current token balances per user - uint256 public totalCommitterBalance; // sum of current token balances - uint256 public slashedBalance; //sum of all slashed balances - - mapping(bytes32 => address) public jobAddresses; // holds the address that ran the job - - /******** - FUNCTIONS - ********/ - /// @notice Contract constructor used during deployment - /// @param _activityList String list of activities reported by oracle - /// @param _oracleAddress Address of oracle for activity data - /// @param _token Address of contract - /// @dev Configure token address, add activities to activities mapping by calling _addActivities method - constructor( - string[] memory _activityList, - address _oracleAddress, - address _token - ) - public { - console.log("Constructor called for SinglePlayerCommit contract"); - require(_activityList.length >= 1, "SPC::constructor - activityList empty"); - token = IERC20(_token); - - _addActivities(_activityList, _oracleAddress); - } - - // view functions - /// @notice Get name string of activity based on key - /// @param _activityKey Keccak256 hashed, encoded name of activity - /// @dev Lookup in mapping and get name field - function getActivityName(bytes32 _activityKey) public view returns (string memory activityName) { - return activities[_activityKey].name; - } - - // other public functions - /// @notice Deposit amount of into contract - /// @param amount Size of deposit - /// @dev Transfer amount to contract, update balance, emit event - function deposit(uint256 amount) public returns (bool success) { - console.log("Received call for depositing amount %s from sender %s", amount, msg.sender); - require( - token.transferFrom(msg.sender, address(this), amount), - "SPC::deposit - token transfer failed" - ); - - _changeCommitterBalance(msg.sender, amount, true); - - emit Deposit(msg.sender, amount); - - return true; - } - - /// @notice Public function to withdraw unstaked balance of user - /// @param amount Amount of to withdraw - /// @dev Check balances and active stake, withdraw from balances, emit event - function withdraw(uint256 amount) public returns (bool success) { - console.log("Received call for withdrawing amount %s from sender %s", amount, msg.sender); - uint256 available = committerBalances[msg.sender]; - Commitment storage commitment = commitments[msg.sender]; - - if(commitment.exists == true){ - available = available.sub(commitment.stake); - } - - require(amount <= available, "SPC::withdraw - not enough (unstaked) balance available"); - - _changeCommitterBalance(msg.sender, amount, false); - - require(token.transfer(msg.sender, amount), "SPC::withdraw - token transfer failed"); - - emit Withdrawal(msg.sender, amount); - - return true; - } - - /// @notice Create commitment, store on-chain and emit event - /// @param _activityKey Keccak256 hashed, encoded name of activity - /// @param _goalValue Distance of activity as goal - /// @param _startTime Starttime of commitment, also used for endTime - /// @param _stake Amount of to stake againt achieving goal - /// @param _userId ??? - /// @dev Check parameters, create commitment, store on-chain and emit event - function makeCommitment( - bytes32 _activityKey, - uint256 _goalValue, - uint256 _startTime, - uint256 _stake, - string memory _userId - ) - public - returns (bool success) - { - console.log("makeCommitment called by %s", msg.sender); - - require(!commitments[msg.sender].exists, "SPC::makeCommitment - msg.sender already has a commitment"); - require(activities[_activityKey].allowed, "SPC::makeCommitment - activity doesn't exist or isn't allowed"); - require(_startTime > block.timestamp, "SPC::makeCommitment - commitment cannot start in the past"); - require(_goalValue > 1, "SPC::makeCommitment - goal is too low"); - require(committerBalances[msg.sender] >= _stake, "SPC::makeCommitment - insufficient token balance"); - - uint256 endTime = _startTime.add(7 days); - - Commitment memory commitment = Commitment({ - committer: msg.sender, - activityKey: _activityKey, - goalValue: _goalValue, - startTime: _startTime, - endTime: endTime, - stake: _stake, - reportedValue: 0, - lastActivityUpdate: 0, - met: false, - userId: _userId, - exists: true - }); - - commitments[msg.sender] = commitment; - - emit NewCommitment( - msg.sender, - activities[_activityKey].name, - _goalValue, - _startTime, - endTime, - _stake); - - return true; - } - - /// @notice Wrapper function to deposit and create commitment in one call - /// @param _activityKey Keccak256 hashed, encoded name of activity - /// @param _goalValue Distance of activity as goal - /// @param _startTime Starttime of commitment, also used for endTime - /// @param _stake Amount of to stake againt achieving goale - /// @param _depositAmount Size of deposit - /// @param _userId ??? - /// @dev Call deposit and makeCommitment method - function depositAndCommit( - bytes32 _activityKey, - uint256 _goalValue, - uint256 _startTime, - uint256 _stake, - uint256 _depositAmount, - string memory _userId - ) - public - returns (bool success) - { - require(deposit(_depositAmount), "SPC::depositAndCommit - deposit failed"); - require(makeCommitment( - _activityKey, - _goalValue, - _startTime, - _stake, - _userId - ), "SPC::depositAndCommit - commitment creation failed"); - - return true; - } - - /// @notice Enables processing of open commitments after endDate that have not been processed by creator - /// @param committer address of the creator of the committer to process - /// @dev Process commitment by lookup based on address, checking metrics, state and updating balances - function processCommitment(address committer) public { - console.log("Processing commitment"); - require(commitments[committer].exists, "SPC::processCommitment - commitment does not exist"); - Commitment storage commitment = commitments[committer]; - - require(commitment.endTime < block.timestamp, "SPC::processCommitment - commitment is still active"); - require(commitment.endTime < commitment.lastActivityUpdate, "SPC::processCommitment - update activity"); - - require(_settleCommitment(commitment), "SPC::processCommitmentUser - settlement failed"); - - emit CommitmentEnded(committer, commitment.met, commitment.stake); - } - - /// @notice Enables control of processing own commitment. For instance when completed. - /// @dev Process commitment by lookup msg.sender, checking metrics, state and updating balances - function processCommitmentUser() public { - console.log("Processing commitment"); - require(commitments[msg.sender].exists, "SPC::processCommitmentUser - commitment does not exist"); - Commitment storage commitment = commitments[msg.sender]; - - require(_settleCommitment(commitment), "SPC::processCommitmentUser - settlement failed"); - emit CommitmentEnded(msg.sender, commitment.met, commitment.stake); - } - - /// @notice Internal function for evaluating commitment and slashing funds if needed - /// @dev Receive call with commitment object from storage - function _settleCommitment(Commitment storage commitment) internal returns (bool success) { - commitment.met = commitment.reportedValue > commitment.goalValue; - - if (!commitment.met) { - _slashFunds(commitment.stake, msg.sender); - } - - commitment.exists = false; - return true; - } - - /// @notice Contract owner can withdraw funds not owned by committers. E.g. slashed from failed commitments - /// @param amount Amount of to withdraw - /// @dev Check amount against slashedBalance, transfer amount and update slashedBalance - function ownerWithdraw(uint256 amount) public onlyOwner returns (bool success) { - console.log("Received call for owner withdrawal for amount %s", amount); - - require(amount <= slashedBalance, "SPC::ownerWithdraw - not enough available balance"); - slashedBalance = slashedBalance.sub(amount); - - require(token.transfer(msg.sender, amount), "SPC::ownerWithdraw - token transfer failed"); - - return true; - } - - /// @notice Internal function to update balance of caller and total balance - /// @param amount Amount of to deposit/withdraw - /// @param add Boolean toggle to deposit or withdraw - /// @dev Based on add param add or substract amount from msg.sender balance and total committerBalance - function _changeCommitterBalance(address committer, uint256 amount, bool add) internal returns (bool success) { - if (add) { - committerBalances[committer] = committerBalances[committer].add(amount); - totalCommitterBalance = totalCommitterBalance.add(amount); - } else { - committerBalances[committer] = committerBalances[committer].sub(amount); - totalCommitterBalance = totalCommitterBalance.sub(amount); - } - - return true; - } - - /// @notice Internal function to slash funds from user - /// @param amount Amount of to slash - /// @param committer Address of committer - /// @dev Substract amount from committer balance and add to slashedBalance - function _slashFunds(uint256 amount, address committer) internal returns (bool success) { - require(committerBalances[committer] >= amount, "SPC::_slashFunds - funds not available"); - _changeCommitterBalance(committer, amount, false); - slashedBalance = slashedBalance.add(amount); - return true; - } - - // internal functions - /// @notice Adds list of activities with oracle (i.e. datasource) to contract - /// @param _activityList String list of activities reported by oracle - /// @param oracleAddress Address of oracle for activity data - /// @dev Basically just loops over _addActivity for list - function _addActivities(string[] memory _activityList, address oracleAddress) internal { - require(_activityList.length > 0, "SPC::_addActivities - list appears to be empty"); - - for (uint256 i = 0; i < _activityList.length; i++) { - _addActivity(_activityList[i], oracleAddress); - } - - console.log("All provided activities added"); - } - - /// @notice Add activity to contract's activityKeyList - /// @param _activityName String name of activity - /// @param _oracleAddress Contract address of oracle - /// @dev Create key from name, create activity, push to activityKeyList, return key - function _addActivity(string memory _activityName, address _oracleAddress) - internal - returns (bytes32 activityKey) - { - bytes memory activityNameBytes = bytes(_activityName); - require(activityNameBytes.length > 0, "SPC::_addActivity - _activityName empty"); - - bytes32 _activityKey = keccak256(abi.encode(_activityName)); - - Activity memory activity = Activity({ - name: _activityName, - oracle: _oracleAddress, - allowed: true, - exists: true - }); - - console.log( - "Registered activity %s", - _activityName - ); - - activities[_activityKey] = activity; - activityKeyList.push(_activityKey); - emit ActivityUpdated( - activity.name, - _activityKey, - activity.oracle, - activity.allowed, - activity.exists); - return _activityKey; - } - - /// @notice Function to update oracle address of existing activity - /// @param _activityKey Keccak256 hashed, encoded name of activity - /// @param _oracleAddress Address of oracle for activity data - /// @dev Check activity exists, update state, emit event - function updateActivityOracle(bytes32 _activityKey, address _oracleAddress) - public - onlyOwner - returns (bool success) - { - require(activities[_activityKey].exists, "SPC::_updateActivityOracle - activity does not exist"); - Activity storage activity = activities[_activityKey]; - activity.oracle = _oracleAddress; - emit ActivityUpdated( - activity.name, - _activityKey, - activity.oracle, - activity.allowed, - activity.exists - ); - return true; - } - - /// @notice Function to update availability of activity of existing activity - /// @param _activityKey Keccak256 hashed, encoded name of activity - /// @param _allowed Toggle for allowing new commitments with activity - /// @dev Check activity exists, update state, emit event - function updateActivityAllowed(bytes32 _activityKey, bool _allowed) - public - onlyOwner - returns (bool success) - { - require(activities[_activityKey].exists, "SPC::_updateActivityOracle - activity does not exist"); - Activity storage activity = activities[_activityKey]; - activity.allowed = _allowed; - emit ActivityUpdated( - activity.name, - _activityKey, - activity.oracle, - activity.allowed, - activity.exists - ); - return true; - } - - /// @notice Function to 'delete' an existing activity. One way function, cannot be reversed. - /// @param _activityKey Keccak256 hashed, encoded name of activity - /// @dev Check activity exists, update state, emit event - function disableActivity(bytes32 _activityKey) - public - onlyOwner - returns (bool success) - { - require(activities[_activityKey].exists, "SPC::_updateActivityOracle - activity does not exist"); - Activity storage activity = activities[_activityKey]; - activity.exists = false; - emit ActivityUpdated( - activity.name, - _activityKey, - activity.oracle, - activity.allowed, - activity.exists - ); - return true; - } - - //Chainlink functions - /// @notice Call ChainLink node to report distance measured based on Strava data - /// @param _committer Address of creator of commitment - /// @param _oracle ChainLink oracle address - /// @param _jobId ??? - /// @dev Async function sending request to ChainLink node - function requestActivityDistance(address _committer, address _oracle, string memory _jobId) - public - { - Commitment memory commitment = commitments[_committer]; - Chainlink.Request memory req = buildChainlinkRequest( - stringToBytes32(_jobId), - address(this), - this.fulfillActivityDistance.selector - ); - req.add("type", activities[commitment.activityKey].name); - req.add("startTime", uint2str(commitment.startTime)); - req.add("endTime", uint2str(commitment.endTime)); - req.add("userId", commitment.userId); - - bytes32 requestId = sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); - jobAddresses[requestId] = _committer; - } - - /// @notice Register distance reported by ChainLink node - /// @param _requestId ID or request triggering the method call - /// @param _distance Distance to register - /// @dev Follow-up function to requestActivityDistance - function fulfillActivityDistance(bytes32 _requestId, uint256 _distance) - public - recordChainlinkFulfillment(_requestId) - { - emit RequestActivityDistanceFulfilled(_requestId, _distance); - address userAddress = jobAddresses[_requestId]; - commitments[userAddress].reportedValue = _distance; - commitments[userAddress].lastActivityUpdate = block.timestamp; - } - - /// @notice Get address for ChainLink token contract - /// @dev ChainLink contract method - function getChainlinkToken() public view returns (address tokenAddress) { - return chainlinkTokenAddress(); - } - - /// @notice Withdraw ChainLink token from contract to contract owner - function withdrawLink() public onlyOwner { - LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); - require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); - } - - function cancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) - public - onlyOwner - { - cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function stringToBytes32(string memory source) private pure returns (bytes32 result) { - bytes memory tempEmptyStringTest = bytes(source); - if (tempEmptyStringTest.length == 0) { - return 0x0; - } - - assembly { // solhint-disable-line no-inline-assembly - result := mload(add(source, 32)) - } - } - - function uint2str(uint i) internal pure returns (string memory str){ - if (i == 0) return "0"; - uint j = i; - uint length; - while (j != 0){ - length++; - j /= 10; - } - bytes memory bstr = new bytes(length); - uint k = length - 1; - while (i != 0){ - bstr[k--] = byte(uint8(48 + i % 10)); - i /= 10; - } - return string(bstr); - } -} \ No newline at end of file diff --git a/resources/SinglePlayerCommit_remix.sol b/resources/SinglePlayerCommit_remix.sol new file mode 100644 index 0000000..6bddc98 --- /dev/null +++ b/resources/SinglePlayerCommit_remix.sol @@ -0,0 +1,532 @@ +/* SPDX-License-Identifier: MIT */ +pragma solidity 0.6.10; +pragma experimental ABIEncoderV2; + +import { console } from "https://github.com/nomiclabs/hardhat/blob/master/packages/hardhat-core/console.sol"; +import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/access/Ownable.sol"; +import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/token/ERC20/IERC20.sol"; +import "https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/ChainlinkClient.sol"; +//https://github.com/smartcontractkit/chainlink/issues/3153#issuecomment-655241638 +import "https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/vendor/SafeMathChainlink.sol"; + +/// @title CommitPool single-player mode contract +/// @notice Enables staking and validating performance. No social/pool functionality. +contract SinglePlayerCommit is ChainlinkClient, Ownable { + using SafeMathChainlink for uint256; + + /****************** + GLOBAL CONSTANTS + ******************/ + IERC20 public token; + uint256 BIGGEST_NUMBER = uint256(-1); + uint256 constant private ORACLE_PAYMENT = 1 * LINK; + + /*************** + DATA TYPES + ***************/ + /// @notice Activity as part of commitment with oracle address. E.g. "cycling" with ChainLink Strava node + struct Activity { + string name; + address oracle; + bool allowed; + bool exists; + } + + struct Commitment { + address committer; // user + bytes32 activityKey; + uint256 goalValue; + uint256 startTime; + uint256 endTime; + uint256 stake; // amount of token staked, scaled by token decimals + uint256 reportedValue; // as reported by oracle + uint256 lastActivityUpdate; // when updated by oracle + bool met; // whether the commitment has been met + string userId; + bool exists; // flag to help check if commitment exists + } + + /*************** + EVENTS + ***************/ + event NewCommitment( + address committer, + string activityName, + uint256 goalValue, + uint256 startTime, + uint256 endTime, + uint256 stake + ); + event CommitmentEnded(address committer, bool met, uint256 amountPenalized); + event Deposit(address committer, uint256 amount); + event Withdrawal(address committer, uint256 amount); + event RequestActivityDistanceFulfilled( + bytes32 indexed requestId, + uint256 indexed distance + ); + event ActivityUpdated( + string name, + bytes32 activityKey, + address oracle, + bool allowed, + bool exists); + //TODO Error events + + + /****************** + INTERNAL ACCOUNTING + ******************/ + mapping(bytes32 => Activity) public activities; // get Activity object based on activity key + bytes32[] public activityKeyList; // List of activityKeys, used for indexing allowed activities + + mapping(address => Commitment) public commitments; // active commitments + // address[] public userCommitments; // addresses with active commitments + + mapping(address => uint256) public committerBalances; // current token balances per user + uint256 public totalCommitterBalance; // sum of current token balances + uint256 public slashedBalance; //sum of all slashed balances + + mapping(bytes32 => address) public jobAddresses; // holds the address that ran the job + + /******** + FUNCTIONS + ********/ + /// @notice Contract constructor used during deployment + /// @param _activityList String list of activities reported by oracle + /// @param _oracleAddress Address of oracle for activity data + /// @param _token Address of contract + /// @dev Configure token address, add activities to activities mapping by calling _addActivities method + constructor( + string[] memory _activityList, + address _oracleAddress, + address _token + ) + public { + console.log("Constructor called for SinglePlayerCommit contract"); + require(_activityList.length >= 1, "SPC::constructor - activityList empty"); + token = IERC20(_token); + + _addActivities(_activityList, _oracleAddress); + } + + // view functions + /// @notice Get name string of activity based on key + /// @param _activityKey Keccak256 hashed, encoded name of activity + /// @dev Lookup in mapping and get name field + function getActivityName(bytes32 _activityKey) public view returns (string memory activityName) { + return activities[_activityKey].name; + } + + // other public functions + /// @notice Deposit amount of into contract + /// @param amount Size of deposit + /// @dev Transfer amount to contract, update balance, emit event + function deposit(uint256 amount) public returns (bool success) { + console.log("Received call for depositing amount %s from sender %s", amount, msg.sender); + require( + token.transferFrom(msg.sender, address(this), amount), + "SPC::deposit - token transfer failed" + ); + + _changeCommitterBalance(msg.sender, amount, true); + + emit Deposit(msg.sender, amount); + + return true; + } + + /// @notice Public function to withdraw unstaked balance of user + /// @param amount Amount of to withdraw + /// @dev Check balances and active stake, withdraw from balances, emit event + function withdraw(uint256 amount) public returns (bool success) { + console.log("Received call for withdrawing amount %s from sender %s", amount, msg.sender); + uint256 available = committerBalances[msg.sender]; + Commitment storage commitment = commitments[msg.sender]; + + if(commitment.exists == true){ + available = available.sub(commitment.stake); + } + + require(amount <= available, "SPC::withdraw - not enough (unstaked) balance available"); + + _changeCommitterBalance(msg.sender, amount, false); + + require(token.transfer(msg.sender, amount), "SPC::withdraw - token transfer failed"); + + emit Withdrawal(msg.sender, amount); + + return true; + } + + /// @notice Create commitment, store on-chain and emit event + /// @param _activityKey Keccak256 hashed, encoded name of activity + /// @param _goalValue Distance of activity as goal + /// @param _startTime Starttime of commitment, also used for endTime + /// @param _stake Amount of to stake againt achieving goal + /// @param _userId ??? + /// @dev Check parameters, create commitment, store on-chain and emit event + function makeCommitment( + bytes32 _activityKey, + uint256 _goalValue, + uint256 _startTime, + uint256 _stake, + string memory _userId + ) + public + returns (bool success) + { + console.log("makeCommitment called by %s", msg.sender); + + require(!commitments[msg.sender].exists, "SPC::makeCommitment - msg.sender already has a commitment"); + require(activities[_activityKey].allowed, "SPC::makeCommitment - activity doesn't exist or isn't allowed"); + require(_startTime > block.timestamp, "SPC::makeCommitment - commitment cannot start in the past"); + require(_goalValue > 1, "SPC::makeCommitment - goal is too low"); + require(committerBalances[msg.sender] >= _stake, "SPC::makeCommitment - insufficient token balance"); + + uint256 endTime = _startTime.add(7 days); + + Commitment memory commitment = Commitment({ + committer: msg.sender, + activityKey: _activityKey, + goalValue: _goalValue, + startTime: _startTime, + endTime: endTime, + stake: _stake, + reportedValue: 0, + lastActivityUpdate: 0, + met: false, + userId: _userId, + exists: true + }); + + commitments[msg.sender] = commitment; + + emit NewCommitment( + msg.sender, + activities[_activityKey].name, + _goalValue, + _startTime, + endTime, + _stake); + + return true; + } + + /// @notice Wrapper function to deposit and create commitment in one call + /// @param _activityKey Keccak256 hashed, encoded name of activity + /// @param _goalValue Distance of activity as goal + /// @param _startTime Starttime of commitment, also used for endTime + /// @param _stake Amount of to stake againt achieving goale + /// @param _depositAmount Size of deposit + /// @param _userId ??? + /// @dev Call deposit and makeCommitment method + function depositAndCommit( + bytes32 _activityKey, + uint256 _goalValue, + uint256 _startTime, + uint256 _stake, + uint256 _depositAmount, + string memory _userId + ) + public + returns (bool success) + { + require(deposit(_depositAmount), "SPC::depositAndCommit - deposit failed"); + require(makeCommitment( + _activityKey, + _goalValue, + _startTime, + _stake, + _userId + ), "SPC::depositAndCommit - commitment creation failed"); + + return true; + } + + /// @notice Enables processing of open commitments after endDate that have not been processed by creator + /// @param committer address of the creator of the committer to process + /// @dev Process commitment by lookup based on address, checking metrics, state and updating balances + function processCommitment(address committer) public { + console.log("Processing commitment"); + require(commitments[committer].exists, "SPC::processCommitment - commitment does not exist"); + Commitment storage commitment = commitments[committer]; + + require(commitment.endTime < block.timestamp, "SPC::processCommitment - commitment is still active"); + require(commitment.endTime < commitment.lastActivityUpdate, "SPC::processCommitment - update activity"); + + require(_settleCommitment(commitment), "SPC::processCommitmentUser - settlement failed"); + + emit CommitmentEnded(committer, commitment.met, commitment.stake); + } + + /// @notice Enables control of processing own commitment. For instance when completed. + /// @dev Process commitment by lookup msg.sender, checking metrics, state and updating balances + function processCommitmentUser() public { + console.log("Processing commitment"); + require(commitments[msg.sender].exists, "SPC::processCommitmentUser - commitment does not exist"); + Commitment storage commitment = commitments[msg.sender]; + + require(_settleCommitment(commitment), "SPC::processCommitmentUser - settlement failed"); + emit CommitmentEnded(msg.sender, commitment.met, commitment.stake); + } + + /// @notice Internal function for evaluating commitment and slashing funds if needed + /// @dev Receive call with commitment object from storage + function _settleCommitment(Commitment storage commitment) internal returns (bool success) { + commitment.met = commitment.reportedValue >= commitment.goalValue; + + if (!commitment.met) { + _slashFunds(commitment.stake, msg.sender); + } + + commitment.exists = false; + return true; + } + + /// @notice Contract owner can withdraw funds not owned by committers. E.g. slashed from failed commitments + /// @param amount Amount of to withdraw + /// @dev Check amount against slashedBalance, transfer amount and update slashedBalance + function ownerWithdraw(uint256 amount) public onlyOwner returns (bool success) { + console.log("Received call for owner withdrawal for amount %s", amount); + + require(amount <= slashedBalance, "SPC::ownerWithdraw - not enough available balance"); + slashedBalance = slashedBalance.sub(amount); + + require(token.transfer(msg.sender, amount), "SPC::ownerWithdraw - token transfer failed"); + + return true; + } + + /// @notice Internal function to update balance of caller and total balance + /// @param amount Amount of to deposit/withdraw + /// @param add Boolean toggle to deposit or withdraw + /// @dev Based on add param add or substract amount from msg.sender balance and total committerBalance + function _changeCommitterBalance(address committer, uint256 amount, bool add) internal returns (bool success) { + if (add) { + committerBalances[committer] = committerBalances[committer].add(amount); + totalCommitterBalance = totalCommitterBalance.add(amount); + } else { + committerBalances[committer] = committerBalances[committer].sub(amount); + totalCommitterBalance = totalCommitterBalance.sub(amount); + } + + return true; + } + + /// @notice Internal function to slash funds from user + /// @param amount Amount of to slash + /// @param committer Address of committer + /// @dev Substract amount from committer balance and add to slashedBalance + function _slashFunds(uint256 amount, address committer) internal returns (bool success) { + require(committerBalances[committer] >= amount, "SPC::_slashFunds - funds not available"); + _changeCommitterBalance(committer, amount, false); + slashedBalance = slashedBalance.add(amount); + return true; + } + + // internal functions + /// @notice Adds list of activities with oracle (i.e. datasource) to contract + /// @param _activityList String list of activities reported by oracle + /// @param oracleAddress Address of oracle for activity data + /// @dev Basically just loops over _addActivity for list + function _addActivities(string[] memory _activityList, address oracleAddress) internal { + require(_activityList.length > 0, "SPC::_addActivities - list appears to be empty"); + + for (uint256 i = 0; i < _activityList.length; i++) { + _addActivity(_activityList[i], oracleAddress); + } + + console.log("All provided activities added"); + } + + /// @notice Add activity to contract's activityKeyList + /// @param _activityName String name of activity + /// @param _oracleAddress Contract address of oracle + /// @dev Create key from name, create activity, push to activityKeyList, return key + function _addActivity(string memory _activityName, address _oracleAddress) + internal + returns (bytes32 activityKey) + { + bytes memory activityNameBytes = bytes(_activityName); + require(activityNameBytes.length > 0, "SPC::_addActivity - _activityName empty"); + + bytes32 _activityKey = keccak256(abi.encode(_activityName)); + + Activity memory activity = Activity({ + name: _activityName, + oracle: _oracleAddress, + allowed: true, + exists: true + }); + + console.log( + "Registered activity %s", + _activityName + ); + + activities[_activityKey] = activity; + activityKeyList.push(_activityKey); + emit ActivityUpdated( + activity.name, + _activityKey, + activity.oracle, + activity.allowed, + activity.exists); + return _activityKey; + } + + /// @notice Function to update oracle address of existing activity + /// @param _activityKey Keccak256 hashed, encoded name of activity + /// @param _oracleAddress Address of oracle for activity data + /// @dev Check activity exists, update state, emit event + function updateActivityOracle(bytes32 _activityKey, address _oracleAddress) + public + onlyOwner + returns (bool success) + { + require(activities[_activityKey].exists, "SPC::_updateActivityOracle - activity does not exist"); + Activity storage activity = activities[_activityKey]; + activity.oracle = _oracleAddress; + emit ActivityUpdated( + activity.name, + _activityKey, + activity.oracle, + activity.allowed, + activity.exists + ); + return true; + } + + /// @notice Function to update availability of activity of existing activity + /// @param _activityKey Keccak256 hashed, encoded name of activity + /// @param _allowed Toggle for allowing new commitments with activity + /// @dev Check activity exists, update state, emit event + function updateActivityAllowed(bytes32 _activityKey, bool _allowed) + public + onlyOwner + returns (bool success) + { + require(activities[_activityKey].exists, "SPC::_updateActivityOracle - activity does not exist"); + Activity storage activity = activities[_activityKey]; + activity.allowed = _allowed; + emit ActivityUpdated( + activity.name, + _activityKey, + activity.oracle, + activity.allowed, + activity.exists + ); + return true; + } + + /// @notice Function to 'delete' an existing activity. One way function, cannot be reversed. + /// @param _activityKey Keccak256 hashed, encoded name of activity + /// @dev Check activity exists, update state, emit event + function disableActivity(bytes32 _activityKey) + public + onlyOwner + returns (bool success) + { + require(activities[_activityKey].exists, "SPC::_updateActivityOracle - activity does not exist"); + Activity storage activity = activities[_activityKey]; + activity.exists = false; + emit ActivityUpdated( + activity.name, + _activityKey, + activity.oracle, + activity.allowed, + activity.exists + ); + return true; + } + + //Chainlink functions + /// @notice Call ChainLink node to report distance measured based on Strava data + /// @param _committer Address of creator of commitment + /// @param _oracle ChainLink oracle address + /// @param _jobId ??? + /// @dev Async function sending request to ChainLink node + function requestActivityDistance(address _committer, address _oracle, string memory _jobId) + public + { + Commitment memory commitment = commitments[_committer]; + Chainlink.Request memory req = buildChainlinkRequest( + stringToBytes32(_jobId), + address(this), + this.fulfillActivityDistance.selector + ); + req.add("type", activities[commitment.activityKey].name); + req.add("startTime", uint2str(commitment.startTime)); + req.add("endTime", uint2str(commitment.endTime)); + req.add("userId", commitment.userId); + + bytes32 requestId = sendChainlinkRequestTo(_oracle, req, ORACLE_PAYMENT); + jobAddresses[requestId] = _committer; + } + + /// @notice Register distance reported by ChainLink node + /// @param _requestId ID or request triggering the method call + /// @param _distance Distance to register + /// @dev Follow-up function to requestActivityDistance + function fulfillActivityDistance(bytes32 _requestId, uint256 _distance) + public + recordChainlinkFulfillment(_requestId) + { + emit RequestActivityDistanceFulfilled(_requestId, _distance); + address userAddress = jobAddresses[_requestId]; + commitments[userAddress].reportedValue = _distance; + commitments[userAddress].lastActivityUpdate = block.timestamp; + } + + /// @notice Get address for ChainLink token contract + /// @dev ChainLink contract method + function getChainlinkToken() public view returns (address tokenAddress) { + return chainlinkTokenAddress(); + } + + /// @notice Withdraw ChainLink token from contract to contract owner + function withdrawLink() public onlyOwner { + LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); + require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); + } + + function cancelRequest( + bytes32 _requestId, + uint256 _payment, + bytes4 _callbackFunctionId, + uint256 _expiration + ) + public + onlyOwner + { + cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); + } + + function stringToBytes32(string memory source) private pure returns (bytes32 result) { + bytes memory tempEmptyStringTest = bytes(source); + if (tempEmptyStringTest.length == 0) { + return 0x0; + } + + assembly { // solhint-disable-line no-inline-assembly + result := mload(add(source, 32)) + } + } + + function uint2str(uint i) internal pure returns (string memory str){ + if (i == 0) return "0"; + uint j = i; + uint length; + while (j != 0){ + length++; + j /= 10; + } + bytes memory bstr = new bytes(length); + uint k = length - 1; + while (i != 0){ + bstr[k--] = byte(uint8(48 + i % 10)); + i /= 10; + } + return string(bstr); + } +} \ No newline at end of file