Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MEVM context #46

Merged
merged 6 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,28 @@ contract Example {
}
```

### Context.sol

Helper library to interact with the Suave context in the MEVM.

Available functions:

- `confidentialInputs()`: Returns the confidential inputs of the offchain request.
- `kettleAddress()`: Address of the kettle that is executing the offchain request.

#### Example usage

```solidity
import "suave-std/Context.sol";

contract Example {
function example() {
bytes memory inputs = Context.confidentialInputs();
address kettle = Context.kettleAddress();
}
}
```

### protocols/MevShare.sol

Helper library to send bundle requests with the Mev-Share protocol.
Expand Down
15 changes: 15 additions & 0 deletions src/Context.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

import "./suavelib/Suave.sol";

library Context {
function confidentialInputs() internal returns (bytes memory) {
return Suave.contextGet("confidentialInputs");
}

function kettleAddress() internal returns (address) {
bytes memory addr = Suave.contextGet("kettleAddress");
return abi.decode(addr, (address));
}
}
8 changes: 2 additions & 6 deletions src/Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.8;
import "./forge/Registry.sol";
import "./suavelib/Suave.sol";
import "forge-std/Test.sol";
import "./forge/ContextConnector.sol";

interface ConfidentialInputsWrapperI {
function setConfidentialInputs(bytes memory) external;
Expand All @@ -15,8 +16,8 @@ interface ConfidentialStoreI {
}

contract SuaveEnabled is Test {
ConfidentialInputsWrapperI constant confInputsWrapper = ConfidentialInputsWrapperI(Suave.CONFIDENTIAL_INPUTS);
ConfidentialStoreI constant confStoreWrapper = ConfidentialStoreI(Registry.confidentialStoreAddr);
ContextConnector constant ctx = ContextConnector(Suave.CONTEXT_GET);

function setUp() public {
string[] memory inputs = new string[](2);
Expand All @@ -33,11 +34,6 @@ contract SuaveEnabled is Test {

// reset the confidential store before each test
resetConfidentialStore();
confInputsWrapper.resetConfidentialInputs();
}

function setConfidentialInputs(bytes memory data) internal {
confInputsWrapper.setConfidentialInputs(data);
}

function detectErrorMessage(bytes memory reason) internal pure returns (string memory) {
Expand Down
28 changes: 0 additions & 28 deletions src/forge/ConfidentialInputs.sol

This file was deleted.

44 changes: 44 additions & 0 deletions src/forge/ContextConnector.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.8;

contract ContextConnector {
bytes confidentialInputs;
address kettleAddress;

function setConfidentialInputs(bytes memory _confidentialInputs) public {
confidentialInputs = _confidentialInputs;
}

function resetConfidentialInputs() public {
confidentialInputs = "";
}

function setKettleAddress(address _kettleAddress) public {
kettleAddress = _kettleAddress;
}

function resetKettleAddress() public {
setKettleAddress(address(0));
}

fallback() external {
(string memory key) = abi.decode(msg.data, (string));
bytes32 keyHash = keccak256(abi.encodePacked(key));

bytes memory msgContent;
if (keyHash == keccak256(abi.encodePacked("confidentialInputs"))) {
msgContent = confidentialInputs;
} else if (keyHash == keccak256(abi.encodePacked("kettleAddress"))) {
msgContent = abi.encode(kettleAddress);
} else {
revert("Invalid context key");
}

bytes memory msgdata = abi.encode(msgContent);
assembly {
let location := msgdata
let length := mload(msgdata)
return(add(location, 0x20), length)
}
}
}
4 changes: 2 additions & 2 deletions src/forge/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.8;

import "../suavelib/Suave.sol";
import "./Connector.sol";
import "./ConfidentialInputs.sol";
import "./ContextConnector.sol";
import "./SuaveAddrs.sol";
import "./ConfidentialStore.sol";
import "./ConfidentialStoreConnector.sol";
Expand Down Expand Up @@ -35,7 +35,7 @@ library Registry {
vm.etch(Suave.FETCH_DATA_RECORDS, type(ConfidentialStoreConnector).runtimeCode);

// enable is confidential wrapper
vm.etch(Suave.CONFIDENTIAL_INPUTS, type(ConfidentialInputsWrapper).runtimeCode);
vm.etch(Suave.CONTEXT_GET, type(ContextConnector).runtimeCode);
}

function deployCodeTo(bytes memory creationCode, address where) internal {
Expand Down
32 changes: 26 additions & 6 deletions test/Forge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "src/Test.sol";
import "src/suavelib/Suave.sol";
import "src/Context.sol";

contract TestForge is Test, SuaveEnabled {
address[] public addressList = [0xC8df3686b4Afb2BB53e60EAe97EF043FE03Fb829];
Expand Down Expand Up @@ -36,15 +37,34 @@ contract TestForge is Test, SuaveEnabled {
assertEq(keccak256(found), keccak256(value));
}

function testForgeConfidentialInputs() public {
// ensure that the confidential inputs are empty
bytes memory found = Suave.confidentialInputs();
assertEq(found.length, 0);
function testForgeContextConfidentialInputs() public {
bytes memory found1 = Context.confidentialInputs();
assertEq(found1.length, 0);

bytes memory input = hex"abcd";
setConfidentialInputs(input);
ctx.setConfidentialInputs(input);

bytes memory found2 = Suave.confidentialInputs();
bytes memory found2 = Context.confidentialInputs();
assertEq0(input, found2);

ctx.resetConfidentialInputs();

bytes memory found3 = Context.confidentialInputs();
assertEq(found3.length, 0);
}

function testForgeContextKettleAddress() public {
address found1 = Context.kettleAddress();
assertEq(found1, address(0));

ctx.setKettleAddress(address(this));

address found2 = Context.kettleAddress();
assertEq(found2, address(this));

ctx.resetKettleAddress();

address found3 = Context.kettleAddress();
assertEq(found3, address(0));
}
}
Loading