From e01b860f6d563b0353587364dfe0ce71bb37ba73 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Sun, 18 Feb 2024 16:39:55 +0000 Subject: [PATCH 1/4] Enable context? --- lib/forge-std | 2 +- src/Context.sol | 15 +++++++++++ src/Test.sol | 8 +++--- src/forge/ConfidentialInputs.sol | 28 -------------------- src/forge/ContextConnector.sol | 44 ++++++++++++++++++++++++++++++++ src/forge/Registry.sol | 4 +-- src/suavelib/Suave.sol | 11 ++++++++ test/Forge.t.sol | 32 ++++++++++++++++++----- 8 files changed, 104 insertions(+), 40 deletions(-) create mode 100644 src/Context.sol delete mode 100644 src/forge/ConfidentialInputs.sol create mode 100644 src/forge/ContextConnector.sol diff --git a/lib/forge-std b/lib/forge-std index 4513bc2..3725a22 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 4513bc2063f23c57bee6558799584b518d387a39 +Subproject commit 3725a22ae52065de9966beaf32de69aee46fb530 diff --git a/src/Context.sol b/src/Context.sol new file mode 100644 index 0000000..afe3799 --- /dev/null +++ b/src/Context.sol @@ -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)); + } +} diff --git a/src/Test.sol b/src/Test.sol index 86affec..0a0adef 100644 --- a/src/Test.sol +++ b/src/Test.sol @@ -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; @@ -15,8 +16,9 @@ interface ConfidentialStoreI { } contract SuaveEnabled is Test { - ConfidentialInputsWrapperI constant confInputsWrapper = ConfidentialInputsWrapperI(Suave.CONFIDENTIAL_INPUTS); + // 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[](3); @@ -38,11 +40,11 @@ contract SuaveEnabled is Test { // reset the confidential store before each test resetConfidentialStore(); - confInputsWrapper.resetConfidentialInputs(); + // confInputsWrapper.resetConfidentialInputs(); } function setConfidentialInputs(bytes memory data) internal { - confInputsWrapper.setConfidentialInputs(data); + // confInputsWrapper.setConfidentialInputs(data); } function detectErrorMessage(bytes memory reason) internal pure returns (string memory) { diff --git a/src/forge/ConfidentialInputs.sol b/src/forge/ConfidentialInputs.sol deleted file mode 100644 index eb35a70..0000000 --- a/src/forge/ConfidentialInputs.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.8; - -contract ConfidentialInputsWrapper { - bytes confidentialInputs; - - function setConfidentialInputs(bytes memory _confidentialInputs) public { - confidentialInputs = _confidentialInputs; - } - - function resetConfidentialInputs() public { - confidentialInputs = ""; - } - - fallback() external { - // copy bytes from storage to memory - bytes memory msgdata = new bytes(confidentialInputs.length); - for (uint256 i = 0; i < confidentialInputs.length; i++) { - msgdata[i] = confidentialInputs[i]; - } - - assembly { - let location := msgdata - let length := mload(msgdata) - return(add(location, 0x20), length) - } - } -} diff --git a/src/forge/ContextConnector.sol b/src/forge/ContextConnector.sol new file mode 100644 index 0000000..bf0fa5a --- /dev/null +++ b/src/forge/ContextConnector.sol @@ -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) + } + } +} diff --git a/src/forge/Registry.sol b/src/forge/Registry.sol index 2101166..72e1974 100644 --- a/src/forge/Registry.sol +++ b/src/forge/Registry.sol @@ -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"; @@ -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 { diff --git a/src/suavelib/Suave.sol b/src/suavelib/Suave.sol index 7a4551b..08c7ee5 100644 --- a/src/suavelib/Suave.sol +++ b/src/suavelib/Suave.sol @@ -69,6 +69,8 @@ library Suave { address public constant CONFIDENTIAL_STORE = 0x0000000000000000000000000000000042020000; + address public constant CONTEXT_GET = 0x0000000000000000000000000000000053300003; + address public constant DO_HTTPREQUEST = 0x0000000000000000000000000000000043200002; address public constant ETHCALL = 0x0000000000000000000000000000000042100003; @@ -148,6 +150,15 @@ library Suave { } } + function contextGet(string memory key) internal returns (bytes memory) { + (bool success, bytes memory data) = CONTEXT_GET.call(abi.encode(key)); + if (!success) { + revert PeekerReverted(CONTEXT_GET, data); + } + + return abi.decode(data, (bytes)); + } + function doHTTPRequest(HttpRequest memory request) internal returns (bytes memory) { (bool success, bytes memory data) = DO_HTTPREQUEST.call(abi.encode(request)); if (!success) { diff --git a/test/Forge.t.sol b/test/Forge.t.sol index 68f50f3..4546899 100644 --- a/test/Forge.t.sol +++ b/test/Forge.t.sol @@ -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]; @@ -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)); } } From 62536c73809dbcf4874487d5c07f318d9289b7c3 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 20 Feb 2024 14:47:15 +0000 Subject: [PATCH 2/4] Update README --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index e3d9f07..906f533 100644 --- a/README.md +++ b/README.md @@ -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. From f4392f16bea5b476d9877cbba1edc79e246c7dc4 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 20 Feb 2024 14:49:17 +0000 Subject: [PATCH 3/4] Remove comment --- src/Test.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Test.sol b/src/Test.sol index b5bba68..26ef857 100644 --- a/src/Test.sol +++ b/src/Test.sol @@ -16,7 +16,6 @@ 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); From f7cfc91868f6069c46e31e2b96c57c420c410cf8 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 20 Feb 2024 21:04:30 +0000 Subject: [PATCH 4/4] Remove dead code --- src/Test.sol | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Test.sol b/src/Test.sol index 26ef857..d6becb2 100644 --- a/src/Test.sol +++ b/src/Test.sol @@ -34,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) {