Skip to content

Commit

Permalink
wip: contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
dndll committed Feb 14, 2024
1 parent 5342629 commit bfd57bd
Show file tree
Hide file tree
Showing 22 changed files with 419 additions and 250 deletions.
16 changes: 9 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ local.toml
*.db

# Compiler files
circuits/plonky2x/contracts/cache
circuits/plonky2x/contracts/out
circuits/plonky2x/contracts/lib
circuits/plonky2x/contract/cache
circuits/plonky2x/contract/out
circuits/plonky2x/contract/lib
# Ignores development broadcast logs
!**broadcast
**broadcast/*/31337/
**broadcast/**/dry-run/
circuits/plonky2x/contract/broadcast

wrapped/
build/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

# Docs
docs/
Expand Down
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,12 @@
[submodule "vendor/succinctx"]
path = vendor/succinctx
url = [email protected]:succinctlabs/succinctx.git
[submodule "circuits/plonky2x/verifier/lib/openzeppelin-contracts-upgradeable"]
path = circuits/plonky2x/verifier/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "circuits/plonky2x/verifier/lib/openzeppelin-contracts"]
path = circuits/plonky2x/verifier/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "circuits/plonky2x/verifier/lib/foundry-devops"]
path = circuits/plonky2x/verifier/lib/foundry-devops
url = https://github.com/chainaccelorg/foundry-devops
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ test-utils = { path = "crates/test-utils" }
curta = { git = "https://github.com/dndll/starkyx.git" }

[patch."https://github.com/succinctlabs/starkyx.git"]
#curta = { path = "./vendor/starkyx/curta" }
curta = { git = "https://github.com/dndll/starkyx.git" }
curta = { path = "./vendor/starkyx/curta" }
#curta = { git = "https://github.com/dndll/starkyx.git" }

[patch."https://github.com/succinctlabs/succinctx.git"]
#plonky2x = { path = "./vendor/succinctx/plonky2x/core" }
plonky2x = { git = "https://github.com/dndll/succinctx.git" }
plonky2x = { path = "./vendor/succinctx/plonky2x/core" }
#plonky2x = { git = "https://github.com/dndll/succinctx.git" }
32 changes: 32 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.EXPORT_ALL_VARIABLES:
include .env

TAG_PREFIX?=near
IMAGE_TAG?=0.0.1

Expand All @@ -20,3 +23,32 @@ build-verify-circuit:
RUST_LOG=debug ./build/verify build
.PHONY: build-verify-circuit


SYNC_FUNCTION_ID=0x350c2939eb7ff2185612710a2b641b4b46faab68e1e2c57b6f15e0af0674f5e9
VERIFY_FUNCTION_ID=0x39fb2562b80725bb7538dd7d850126964e565a1a837d2d7f2a018e185b08fc0e
ETH_RPC=https://goerli.gateway.tenderly.co
NEAR_CHECKPOINT_HEADER_HASH=0x63b87190ffbaa36d7dab50f918fe36f70ab26910a0e9d797161e2356561598e3
CHAIN_ID=5
CD_CONTRACTS=cd ./circuits/plonky2x/contract

build-contracts:
$(CD_CONTRACTS) && forge build

deploy: build-contracts
$(CD_CONTRACTS) && forge script Deploy \
--rpc-url $(ETH_RPC) \
--private-key $$ETH_PRIVATE_KEY \
--broadcast \
--verify \
--verifier etherscan

initialise:
cd $(ETH_CONTRACTS_PATH) && forge script Initialise \
--rpc-url $(ETH_RPC) \
--private-key $$ETH_PRIVATE_KEY \
--broadcast \
--verify \
--verifier etherscan

# TODO: upgrade

2 changes: 2 additions & 0 deletions bin/operator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ cfg_if::cfg_if! {
}
}

// TODO: make this use a nicer API for use by the prover.
// TODO: perpetually sync, use queue etc
fn main() {
cfg_if::cfg_if! {
if #[cfg(feature = "sync")] {
Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions circuits/plonky2x/contract/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[profile.default]
fs_permissions = [ { access = "read", path = "./broadcast" } ]
libs = [ "lib" ]
out = "out"
remappings = [ "@openzeppelin/contracts=lib/openzeppelin-contracts/contracts", "@openzeppelin/contracts-upgradeable=lib/openzeppelin-contracts-upgradeable/contracts" ]
src = "src"
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
28 changes: 28 additions & 0 deletions circuits/plonky2x/contract/script/Deploy.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {NearX} from "../src/NearX.sol";
import {Script} from "forge-std/Script.sol";

contract Deploy is Script {
function setUp() public {}

function run() external returns (address) {
address proxy = deployNearX();
return proxy;
}

function deployNearX() public returns (address) {
vm.startBroadcast();

NearX lightClient = new NearX();

ERC1967Proxy proxy = new ERC1967Proxy(address(lightClient), "");

lightClient.initialize();

vm.stopBroadcast();
return address(proxy);
}
}
34 changes: 34 additions & 0 deletions circuits/plonky2x/contract/script/Initialise.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {NearX} from "../src/NearX.sol";
import {Script} from "forge-std/Script.sol";
import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol";

contract Initialise is Script {
function setUp() public {}

function run() external {
address proxyAddress = DevOpsTools.get_most_recent_deployment(
"ERC1967Proxy",
block.chainid
);
vm.startBroadcast();
NearX lightClient = NearX(payable(proxyAddress));

address initialGateway = 0x6e4f1e9eA315EBFd69d18C2DB974EEf6105FB803;
lightClient.updateGateway(initialGateway);

bytes32 syncFunctionId = vm.envBytes32("SYNC_FUNCTION_ID");
lightClient.updateSyncId(syncFunctionId);

bytes32 verifyFunctionId = vm.envBytes32("VERIFY_FUNCTION_ID");
lightClient.updateVerifyId(verifyFunctionId);

bytes32 header = vm.envBytes32("NEAR_CHECKPOINT_HEADER_HASH");
lightClient.setCheckpointHeader(header);

vm.stopBroadcast();
}
}
34 changes: 34 additions & 0 deletions circuits/plonky2x/contract/script/Upgrade.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {Script} from "forge-std/Script.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol";
import {NearX} from "../src/NearX.sol";

contract Upgrade is Script {
function run() external returns (address) {
address mostRecentlyDeployedProxy = DevOpsTools
.get_most_recent_deployment("ERC1967Proxy", block.chainid);
vm.startBroadcast();

NearX newAddress = new NearX();

vm.stopBroadcast();
address proxy = upgrade(mostRecentlyDeployedProxy, address(newAddress));
return proxy;
}

function upgrade(address proxyAddress, address newAddress)
public
returns (address)
{
vm.startBroadcast();

NearX proxy = NearX(payable(proxyAddress));
proxy.upgradeToAndCall(address(newAddress), "");

vm.stopBroadcast();
return address(proxy);
}
}
129 changes: 129 additions & 0 deletions circuits/plonky2x/contract/src/NearX.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {ISuccinctGateway} from "./interfaces/ISuccinctGateway.sol";
import {INearX, TransactionOrReceiptId, encodePackedIds, decodePackedIds} from "./interfaces/INearX.sol";

/// @notice The NearX contract is a light client for Near.
contract NearX is INearX, Initializable, OwnableUpgradeable, UUPSUpgradeable {
uint32 public constant DEFAULT_GAS_LIMIT = 1000000;

/// @notice The address of the gateway contract.
address public gateway;

constructor() {
_disableInitializers();
}

function initialize() public initializer {
__Ownable_init(msg.sender); //sets owner to msg.sender
__UUPSUpgradeable_init();
}

function _authorizeUpgrade(address newImplementation)
internal
override
onlyOwner
{}

/// @notice Sync function id.
bytes32 public syncFunctionId;

/// @notice Verify function id.
bytes32 public verifyFunctionId;

/// @notice The latest header that has been committed.
bytes32 public latestHeader;

function updateGateway(address _gateway) external onlyOwner {
gateway = _gateway;
}

function updateSyncId(bytes32 _functionId) external onlyOwner {
syncFunctionId = _functionId;
}

function updateVerifyId(bytes32 _functionId) external onlyOwner {
verifyFunctionId = _functionId;
}

/// Note: Only for testnet. The genesis header should be set when initializing the contract.
function setCheckpointHeader(bytes32 _header) external onlyOwner {
latestHeader = _header;
}

function ensureInitialized() internal view {
if (gateway == address(0)) {
revert GatewayNotInitialised();
}
if (syncFunctionId == bytes32(0) || verifyFunctionId == bytes32(0)) {
revert FunctionIdsNotInitialised();
}
if (latestHeader == bytes32(0)) {
revert HeaderNotInitialised();
}
}

/// @notice Inputs of a sync request.
function requestSync() external payable {
ensureInitialized();
bytes memory context;

ISuccinctGateway(gateway).requestCallback{value: msg.value}(
syncFunctionId,
abi.encodePacked(latestHeader),
context,
NearX.handleSync.selector,
DEFAULT_GAS_LIMIT
);

emit SyncRequested(latestHeader);
}

function handleSync(bytes memory _output, bytes memory _context) external {
if (msg.sender != gateway || !ISuccinctGateway(gateway).isCallback()) {
revert NotFromSuccinctGateway(msg.sender);
}

bytes32 targetHeader = abi.decode(_output, (bytes32));

latestHeader = targetHeader;

emit HeadUpdate(targetHeader);
}

function requestVerify(TransactionOrReceiptId[] memory ids)
external
payable
{
ensureInitialized();
bytes memory context;
bytes memory input = abi.encodePacked(
latestHeader,
encodePackedIds(ids)
);

ISuccinctGateway(gateway).requestCallback{value: msg.value}(
verifyFunctionId,
input,
context,
NearX.handleVerify.selector,
DEFAULT_GAS_LIMIT
);

emit VerifyRequested(latestHeader, ids);
}

function handleVerify(bytes memory _output, bytes memory _context)
external
{
if (msg.sender != gateway || !ISuccinctGateway(gateway).isCallback()) {
revert NotFromSuccinctGateway(msg.sender);
}
TransactionOrReceiptId[] memory ids = decodePackedIds(_output);
emit VerifyResult(ids);
}
}
Loading

0 comments on commit bfd57bd

Please sign in to comment.