Skip to content

Commit

Permalink
Support MEVM context (#46)
Browse files Browse the repository at this point in the history
* Enable context?

* Update README

* Remove comment

* Remove dead code
  • Loading branch information
ferranbt authored Feb 20, 2024
1 parent 01c149f commit e3ae5c1
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 42 deletions.
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));
}
}

0 comments on commit e3ae5c1

Please sign in to comment.