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

Commit

Permalink
TURING OFFCHAIN COMPUTE: add uniswapv2 fee example (incomplete) - WIP (
Browse files Browse the repository at this point in the history
…#315)

* add uniswapv2 fee example (incomplete)

* add offchain in uniswapv2pair

* feat: update fee-test

Co-authored-by: Mehul Agarwal <[email protected]>
Co-authored-by: souradeep-das <[email protected]>
Co-authored-by: CAPtheorem <[email protected]>
  • Loading branch information
4 people authored Sep 6, 2021
1 parent 5199db8 commit b9c2dfe
Show file tree
Hide file tree
Showing 7 changed files with 709 additions and 99 deletions.
127 changes: 127 additions & 0 deletions omgx_examples/hardhat_ERC721/contracts/boredBobaYachtClub.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// File: contracts/BoredBobaYachtClub.sol


pragma solidity ^0.7.0;



/**
* @title BoredBobaYachtClub contract
* @dev Extends ERC721 Non-Fungible Token Standard basic implementation
*/
contract BoredBobaYachtClub is ERC721, Ownable {
using SafeMath for uint256;

string public BAYC_PROVENANCE = "";

uint256 public startingIndexBlock;

uint256 public startingIndex;

uint256 public constant bobaPrice = 80000000000000000; //0.08 ETH

uint public constant maxBobaPurchase = 20;

uint256 public MAX_BOBAS;

bool public saleIsActive = false;

uint256 public REVEAL_TIMESTAMP;

constructor(string memory name, string memory symbol, uint256 maxNftSupply, uint256 saleStart) ERC721(name, symbol) {
MAX_BOBAS = maxNftSupply;
REVEAL_TIMESTAMP = saleStart + (86400 * 9);
}

function withdraw() public onlyOwner {
uint balance = address(this).balance;
msg.sender.transfer(balance);
}

/**
* Set some Bored Bobas aside
*/
function reserveBobas() public onlyOwner {
uint supply = totalSupply();
uint i;
for (i = 0; i < 30; i++) {
_safeMint(msg.sender, supply + i);
}
}

/**
* DM Gargamel in Discord that you're standing right behind him.
*/
function setRevealTimestamp(uint256 revealTimeStamp) public onlyOwner {
REVEAL_TIMESTAMP = revealTimeStamp;
}

/*
* Set provenance once it's calculated
*/
function setProvenanceHash(string memory provenanceHash) public onlyOwner {
BAYC_PROVENANCE = provenanceHash;
}

function setBaseURI(string memory baseURI) public onlyOwner {
_setBaseURI(baseURI);
}

/*
* Pause sale if active, make active if paused
*/
function flipSaleState() public onlyOwner {
saleIsActive = !saleIsActive;
}

/**
* Mints Bored Bobas
*/
function mintBoba(uint numberOfTokens) public payable {
require(saleIsActive, "Sale must be active to mint Boba");
require(numberOfTokens <= maxBobaPurchase, "Can only mint 20 tokens at a time");
require(totalSupply().add(numberOfTokens) <= MAX_BOBAS, "Purchase would exceed max supply of Bobas");
require(bobaPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");

for(uint i = 0; i < numberOfTokens; i++) {
uint mintIndex = totalSupply();
if (totalSupply() < MAX_BOBAS) {
_safeMint(msg.sender, mintIndex);
}
}

// If we haven't set the starting index and this is either 1) the last saleable token or 2) the first token to be sold after
// the end of pre-sale, set the starting index block
if (startingIndexBlock == 0 && (totalSupply() == MAX_BOBAS || block.timestamp >= REVEAL_TIMESTAMP)) {
startingIndexBlock = block.number;
}
}

/**
* Set the starting index for the collection
*/
function setStartingIndex() public {
require(startingIndex == 0, "Starting index is already set");
require(startingIndexBlock != 0, "Starting index block must be set");

startingIndex = uint(blockhash(startingIndexBlock)) % MAX_BOBAS;
// Just a sanity case in the worst case if this function is called late (EVM only stores last 256 block hashes)
if (block.number.sub(startingIndexBlock) > 255) {
startingIndex = uint(blockhash(block.number - 1)) % MAX_BOBAS;
}
// Prevent default sequence
if (startingIndex == 0) {
startingIndex = startingIndex.add(1);
}
}

/**
* Set the starting index block for the collection, essentially unblocking
* setting starting index
*/
function emergencySetStartingIndexBlock() public onlyOwner {
require(startingIndex == 0, "Starting index is already set");

startingIndexBlock = block.number;
}
}
190 changes: 190 additions & 0 deletions omgx_examples/sushi/contracts/uniswapv2/TuringHelper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
//SPDX-License-Identifier: UNLICENSED

pragma solidity ^0.7.0;

import "hardhat/console.sol";

contract TuringHelper {
bytes data_URL;
TuringHelper Self;
bytes[] methods;

constructor(string memory _url) {
console.log("Deploying a helper contract with data source:", _url);
data_URL = bytes(_url);
Self = TuringHelper(address(this));
}

function RegisterMethod(bytes memory methodName) public {
methods.push(methodName);
}

function _lenCalc1(bytes memory item, uint32 len) internal pure
returns (uint8, uint32)
{
uint32 L = uint32(item.length);
uint8 prefix;

if (L > 255) {
len += 3;
prefix = 0xb9;
} else if (L > 55) {
len += 2;
prefix = 0xb8;
} else {
len += 1;
prefix = 0x80 + uint8(L);
}

return (prefix, len);
}

function genRequestRLP(bytes memory method, bytes memory payload) internal view
returns (bytes memory)
{
// This function generates a Turing request consisting of a
// fixed prefix string followed by parameters in RLP encoding.
// The outer container is a 4-element array containing a
// single-byte version number and 3 strings: URL, method, request
// payload. The payload is passed as-is to the remote server,
// which is responsible for unpacking and interpreting it.

// For now this is the only valid value and all others are reserved.
byte request_version = 0x01;

bytes memory prefix = bytes("_OMGXTURING_");
assert (prefix.length == 12);
uint i;
uint j;

// Constrain these to simplify the RLP encoding logic.
require (data_URL.length < 65536, "data_URL is too long");
require (payload.length < 65536, "payload is too long");

uint32 l1 = uint32(data_URL.length);
uint32 l2 = uint32(method.length);
uint32 l3 = uint32(payload.length);

uint32 pLen = 1 + l1 + l2 + l3; // Payload length + inner headers
uint32 hLen = 1; // Extra length of list header

uint8[4] memory pre;

(pre[1], pLen) = _lenCalc1(data_URL, pLen);
(pre[2], pLen) = _lenCalc1(method, pLen);
(pre[3], pLen) = _lenCalc1(payload, pLen);

// We now have the total length of the three items which will be in the list.
// This determines the encoding required for the list header

if (pLen > 65535) {
hLen += 3;
pre[0] = 0xfa;
} else if (pLen > 255) {
hLen += 2;
pre[0] = 0xf9;
} else if (pLen > 55) {
hLen += 1;
pre[0] = 0xf8;
} else {
pre[0] = 0xc0 + uint8(pLen);
}

bytes memory result = new bytes(hLen + pLen + prefix.length);

for (i=0; i < prefix.length; i++) result[j++] = prefix[i];

result[j++] = bytes1(pre[0]);

if (pre[0] > 0xf9) {
result[j++] = bytes1(uint8(pLen / 65536));
pLen = pLen % 65536;
}
if (pre[0] > 0xf8) {
result[j++] = bytes1(uint8(pLen / 256));
pLen = pLen % 256;
}
if (pre[0] > 0xf7) {
result[j++] = bytes1(uint8(pLen));
}

result[j++] = request_version;

result[j++] = bytes1(pre[1]);
if (pre[1] > 0xb8) {
result[j++] = bytes1(uint8(l1 / 256));
l1 = l1 % 256;
}
if (pre[1] > 0xb7) {
result[j++] = bytes1(uint8(l1));
}
for (i=0; i<data_URL.length; i++) result[j++] = data_URL[i];

result[j++] = bytes1(pre[2]);
if (pre[2] > 0xb8) {
result[j++] = bytes1(uint8(l2 / 256));
l2 = l2 % 256;
}
if (pre[2] > 0xb7) {
result[j++] = bytes1(uint8(l2));
}
for (i=0; i<method.length; i++) result[j++] = method[i];

result[j++] = bytes1(pre[3]);
if (pre[3] > 0xb8) {
result[j++] = bytes1(uint8(l3 / 256));
l3 = l3 % 256;
}
if (pre[3] > 0xb7) {
result[j++] = bytes1(uint8(l3));
}
for (i=0; i<payload.length; i++) result[j++] = payload[i];
return result;
}

/* This is the interface to the off-chain mechanism. Although
marked as "public", it is only to be called by TuringCall().
The _slot parameters is overloaded to represent either the
request parameters or the off-chain response, with the rType
parameter indicating which is which. When called as a request,
it reverts with an encoded OMGX_TURING string. The modified
l2geth intercepts this, performs the off-chain interaction,
then rewrites the parameters and calls the method again in
"response" mode. This response is then passed back to the
caller.
*/
function GetResponse(uint32 method_idx, uint32 rType, bytes memory _slot)
public view returns (bytes memory) {

require (msg.sender == address(this));
require (rType == 1 || rType == 2); // l2geth can pass 0 here to indicate an error
require (_slot.length > 0);

if (rType != 2) {
// The if() avoids calling genRequestRLP unnecessarily
require (rType == 2, string(genRequestRLP(methods[method_idx], _slot)));
}
return _slot;
}

/* This is called from the external contract. It takes a method
selector and an abi-encoded request payload. The URL and the
list of allowed methods are supplied when the contract is
created. In the future some of this registration might be moved
into l2geth, allowing for security measures such as TLS client
certificates. A configurable timeout could also be added.
*/
function TuringCall(uint32 method_idx, bytes memory _payload)
public view returns (bytes memory) {
require (method_idx < methods.length, "Method not registered");
require (_payload.length > 0, "Payload length was 0");

/* Initiate the request. This can't be a local function call
because that would stay inside the EVM and not give l2geth
a place to intercept and re-write the call.
*/
bytes memory response = Self.GetResponse(method_idx, 1, _payload);
return response;
}
}

Loading

0 comments on commit b9c2dfe

Please sign in to comment.