Skip to content

Commit

Permalink
fix: stack too deep error in mock contract by using an external call to
Browse files Browse the repository at this point in the history
the same mock contract
  • Loading branch information
yum0e committed Aug 16, 2023
1 parent 9413ad4 commit 66fdee7
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 152 deletions.
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ libs = ["lib"]
fs_permissions = [{ access = "read-write", path = "./"}]

bytecode_hash="none"
solc_version="0.8.19"

[rpc_endpoints]
arbitrum_one = "https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
Expand Down
14 changes: 7 additions & 7 deletions test/BaseTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.17;
import {Test} from "forge-std/Test.sol";
import {IAddressesProvider} from "src/interfaces/IAddressesProvider.sol";
import {AddressesProviderMock} from "test/mocks/AddressesProviderMock.sol";
// import {SismoConnectVerifierMock} from "test/mocks/SismoConnectVerifierMock.sol";
import {SismoConnectVerifierMock} from "test/mocks/SismoConnectVerifierMock.sol";
import {AuthRequestBuilder} from "src/utils/AuthRequestBuilder.sol";
import {ClaimRequestBuilder} from "src/utils/ClaimRequestBuilder.sol";
import {SignatureBuilder} from "src/utils/SignatureBuilder.sol";
Expand All @@ -16,7 +16,7 @@ contract BaseTest is Test {
address immutable owner = vm.addr(3);
address immutable sismoAddressProviderV2 = 0x3Cd5334eB64ebBd4003b72022CC25465f1BFcEe6;

//SismoConnectVerifierMock sismoConnectVerifier;
SismoConnectVerifierMock sismoConnectVerifier;

// external libraries
AuthRequestBuilder authRequestBuilder;
Expand All @@ -26,7 +26,7 @@ contract BaseTest is Test {

function setUp() public virtual {
AddressesProviderMock addressesProviderMock = new AddressesProviderMock();
// sismoConnectVerifier = new SismoConnectVerifierMock();
sismoConnectVerifier = new SismoConnectVerifierMock();

// external libraries
authRequestBuilder = new AuthRequestBuilder();
Expand All @@ -36,10 +36,10 @@ contract BaseTest is Test {

vm.etch(sismoAddressProviderV2, address(addressesProviderMock).code);

// IAddressesProvider(sismoAddressProviderV2).set(
// address(sismoConnectVerifier),
// string("sismoConnectVerifier-v1.2")
// );
IAddressesProvider(sismoAddressProviderV2).set(
address(sismoConnectVerifier),
string("sismoConnectVerifier-v1.2")
);
IAddressesProvider(sismoAddressProviderV2).set(
address(authRequestBuilder),
string("authRequestBuilder-v1.1")
Expand Down
257 changes: 112 additions & 145 deletions test/mocks/SismoConnectVerifierMock.sol
Original file line number Diff line number Diff line change
@@ -1,158 +1,125 @@
// // SPDX-License-Identifier: MIT
// pragma solidity ^0.8.17;
// SPDX-License-Identifier: MIT

// import "../../src/interfaces/ISismoConnectVerifier.sol";
// import "../../src/utils/Structs.sol";
pragma solidity ^0.8.17;

// // this contract is supposed to implement the interface from SismoConnectVerifier contract
// // we dont specify the interface here because for some reason we encounter a stack too deep error up to a local variable
// // when implementing the `verify` function
// // TO replicate the error, try adding the `config` and `request` argument to the verify function
// // it compiles with one of them (+ response) but not with the three arguments
// contract SismoConnectVerifierMock is ISismoConnectVerifier {
// // struct to store informations about the number of verified auths and claims returned
// // indexes of the first available slot in the arrays of auths and claims are also stored
// // this struct is used to avoid stack to deep errors without using via_ir in foundry
// struct VerifiedArraysInfos {
// uint256 nbOfAuths; // number of verified auths
// uint256 nbOfClaims; // number of verified claims
// uint256 authsIndex; // index of the first available slot in the array of verified auths
// uint256 claimsIndex; // index of the first available slot in the array of verified claims
// VerifiedAuth[] auths;
// VerifiedClaim[] claims;
// }
import "../../src/interfaces/ISismoConnectVerifier.sol";

// bytes32 public immutable SISMO_CONNECT_VERSION = "sismo-connect-v1.1";
contract SismoConnectVerifierMock is ISismoConnectVerifier {
uint8 public constant IMPLEMENTATION_VERSION = 1;
bytes32 public immutable SISMO_CONNECT_VERSION = "sismo-connect-v1.1";

// function _check(SismoConnectRequest memory request) internal pure {
// if (request.auths.length == 0 && request.claims.length == 0) {
// revert("SismoConnectVerifierMock: no auths or claims");
// }
// }
// struct to store informations about the number of verified auths and claims returned
// indexes of the first available slot in the arrays of auths and claims are also stored
// this struct is used to avoid stack to deep errors without using via_ir in foundry
struct VerifiedArraysInfos {
uint256 nbOfAuths; // number of verified auths
uint256 nbOfClaims; // number of verified claims
uint256 authsIndex; // index of the first available slot in the array of verified auths
uint256 claimsIndex; // index of the first available slot in the array of verified claims
}

// function verify(
// SismoConnectResponse memory response,
// SismoConnectRequest memory, // request,
// SismoConnectConfig memory // config
// ) external pure returns (SismoConnectVerifiedResult memory) {
// VerifiedArraysInfos memory infos = VerifiedArraysInfos({
// nbOfAuths: 0,
// nbOfClaims: 0,
// authsIndex: 0,
// claimsIndex: 0,
// auths: new VerifiedAuth[](0),
// claims: new VerifiedClaim[](0)
// });
// Struct holding the verified Auths and Claims from the snark proofs
// This struct is used to avoid stack too deep error
struct VerifiedProofs {
VerifiedAuth[] auths;
VerifiedClaim[] claims;
}

// infos = _getVerifiedArrayInfos(infos, response);
function verify(
SismoConnectResponse memory response,
SismoConnectRequest memory, // request
SismoConnectConfig memory // config
) external view override returns (SismoConnectVerifiedResult memory) {
uint256 responseProofsArrayLength = response.proofs.length;
VerifiedArraysInfos memory infos = VerifiedArraysInfos({
nbOfAuths: 0,
nbOfClaims: 0,
authsIndex: 0,
claimsIndex: 0
});

// infos = _saveVerifiedAuthAndClaim(infos, response);
// Count the number of auths and claims in the response
for (uint256 i = 0; i < responseProofsArrayLength; i++) {
infos.nbOfAuths += response.proofs[i].auths.length;
infos.nbOfClaims += response.proofs[i].claims.length;
}

// return
// SismoConnectVerifiedResult({
// appId: response.appId,
// namespace: response.namespace,
// version: response.version,
// auths: infos.auths,
// claims: infos.claims,
// signedMessage: response.signedMessage
// });
// }
VerifiedProofs memory verifiedProofs = VerifiedProofs({
auths: new VerifiedAuth[](infos.nbOfAuths),
claims: new VerifiedClaim[](infos.nbOfClaims)
});

// function _getVerifiedArrayInfos(
// VerifiedArraysInfos memory infos,
// SismoConnectResponse memory response
// ) private pure returns (VerifiedArraysInfos memory) {
// // Count the number of auths and claims in the response
// for (uint256 i = 0; i < response.proofs.length; i++) {
// infos.nbOfAuths += response.proofs[i].auths.length;
// infos.nbOfClaims += response.proofs[i].claims.length;
// }
for (uint256 i = 0; i < responseProofsArrayLength; i++) {
// we use an external call to getVerifiedAuthAndClaim to avoid stack too deep error (the caller stack is not known by the callee contract)
// in the prod implementation, an external call to a verifier contract is done
// it explains why we don't encounter the stack too deep error in the prod implementation
(VerifiedAuth memory verifiedAuth, VerifiedClaim memory verifiedClaim) = this
.getVerifiedAuthAndClaim({
appId: response.appId,
namespace: response.namespace,
proof: response.proofs[i]
});

// return
// VerifiedArraysInfos({
// nbOfAuths: infos.nbOfAuths,
// nbOfClaims: infos.nbOfClaims,
// authsIndex: infos.authsIndex,
// claimsIndex: infos.claimsIndex,
// auths: new VerifiedAuth[](infos.nbOfAuths),
// claims: new VerifiedClaim[](infos.nbOfClaims)
// });
// }
// we only want to add the verified auths and claims to the result
// if they are not empty, for that we check the length of the proofData that should always be different from 0
if (verifiedAuth.proofData.length != 0) {
verifiedProofs.auths[infos.authsIndex] = verifiedAuth;
infos.authsIndex++;
}
if (verifiedClaim.proofData.length != 0) {
verifiedProofs.claims[infos.claimsIndex] = verifiedClaim;
infos.claimsIndex++;
}
}

// function _saveVerifiedAuthAndClaim(
// VerifiedArraysInfos memory infos,
// SismoConnectResponse memory response
// ) internal pure returns (VerifiedArraysInfos memory) {
// for (uint256 i = 0; i < response.proofs.length; i++) {
// (
// VerifiedAuth memory verifiedAuth,
// VerifiedClaim memory verifiedClaim
// ) = _getVerifiedAuthAndClaim(response);
// if (verifiedAuth.proofData.length != 0) {
// infos.auths[infos.authsIndex] = verifiedAuth;
// infos.authsIndex++;
// }
// if (verifiedClaim.proofData.length != 0) {
// infos.claims[infos.claimsIndex] = verifiedClaim;
// infos.claimsIndex++;
// }
// }
return
SismoConnectVerifiedResult({
appId: response.appId,
namespace: response.namespace,
version: response.version,
auths: verifiedProofs.auths,
claims: verifiedProofs.claims,
signedMessage: response.signedMessage
});
}

// return infos;
// }
function getVerifiedAuthAndClaim(
bytes16 appId,
bytes16 namespace,
SismoConnectProof memory proof
) external pure returns (VerifiedAuth memory, VerifiedClaim memory) {
VerifiedAuth memory verifiedAuth;
VerifiedClaim memory verifiedClaim;

// function _getVerifiedAuthAndClaim(
// SismoConnectResponse memory response
// ) private pure returns (VerifiedAuth memory, VerifiedClaim memory) {
// VerifiedAuth memory verifiedAuth;
// VerifiedClaim memory verifiedClaim;

// if (response.proofs[0].auths.length != 0) {
// verifiedAuth = VerifiedAuth({
// authType: response.proofs[0].auths[0].authType,
// isAnon: response.proofs[0].auths[0].isAnon,
// userId: response.proofs[0].auths[0].userId,
// proofData: response.proofs[0].proofData,
// extraData: response.proofs[0].auths[0].extraData
// });
// // verifiedAuth = VerifiedAuth({
// // authType: AuthType.VAULT,
// // isAnon: false,
// // userId: 0,
// // proofData: "123",
// // extraData: ""
// // });
// }
// if (response.proofs[0].claims.length != 0) {
// verifiedClaim = VerifiedClaim({
// claimType: response.proofs[0].claims[0].claimType,
// groupId: response.proofs[0].claims[0].groupId,
// groupTimestamp: response.proofs[0].claims[0].groupTimestamp,
// value: response.proofs[0].claims[0].value,
// proofId: uint256(
// keccak256(
// abi.encodePacked(
// response.proofs[0].claims[0].groupId,
// response.proofs[0].claims[0].groupTimestamp,
// response.appId,
// response.namespace
// )
// )
// ),
// proofData: response.proofs[0].proofData,
// extraData: response.proofs[0].claims[0].extraData
// });
// // verifiedClaim = VerifiedClaim({
// // claimType: ClaimType.GTE,
// // groupId: bytes16("groupId"),
// // groupTimestamp: bytes16("latest"),
// // value: 1,
// // proofId: 1,
// // proofData: "123",
// // extraData: ""
// // });
// }
// return (verifiedAuth, verifiedClaim);
// }
// }
if (proof.auths.length != 0) {
verifiedAuth = VerifiedAuth({
authType: proof.auths[0].authType,
isAnon: proof.auths[0].isAnon,
userId: proof.auths[0].userId,
proofData: proof.proofData,
extraData: proof.auths[0].extraData
});
}
if (proof.claims.length != 0) {
verifiedClaim = VerifiedClaim({
claimType: proof.claims[0].claimType,
groupId: proof.claims[0].groupId,
groupTimestamp: proof.claims[0].groupTimestamp,
value: proof.claims[0].value,
proofId: uint256(
keccak256(
abi.encodePacked(
proof.claims[0].groupId,
proof.claims[0].groupTimestamp,
appId,
namespace
)
)
),
proofData: proof.proofData,
extraData: proof.claims[0].extraData
});
}
return (verifiedAuth, verifiedClaim);
}
}
9 changes: 9 additions & 0 deletions test/unit/SismoConnect.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,13 @@ contract SismoConnectTest is BaseTest {
userId: uint256(bytes32("wrong-id"))
});
}

function test_verifyProof() public view {
bytes
memory responseBytes = hex"000000000000000000000000000000000000000000000000000000000000002011b1de449c6c4adb0b5775b3868b28b300000000000000000000000000000000b8e2054f8a912367e38a22ce773328ff000000000000000000000000000000007369736d6f2d636f6e6e6563742d76312e31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001a068796472612d73332e310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000100100000000000000000000000000009999037000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c014aa96fb34414b749bb4610bace69a3d3e9ed4b1af6137f7d1a3270590c696bb0074dc54bfd774a3185b445f2b1013bcefb8d8d1b98b186611829ae9ac59a44407b6fa1abaafa92b207d2bed2139ff1a6cd05f56ac2167f89a6b3a3180eceebb107f09ef3f109f1ac13560ed255b5605e340964f5fd6b96ae9e62634cd219d51233f679d2011810af86b8da940f2e3b8ba38716d0ab63a8aa6944c13dd6ec40d0c36d09c76572cc1dfffd527ca60c1828642782322a49ef6df921f0a57ecc65f2706ff429747a7b1dd72643a24dc9be189b0461f155fe5479bde1f78609fece82331e429f79401e878e826c36ada7d85053e00226dd49e6e76fb76ff7b2e43490000000000000000000000001001000000000000000000000000000099990370000000000000000000000000000000000000000000000000000000000000000007f6c5612eb579788478789deccb06cf0eb168e457eea490af754922939ebdb920706798455f90ed993f8dac8075fc1538738a25f0c928da905c0dffd81869fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086297004382ede0550866e3e15fdce4b5b9fa843f0c12fece0fa11cf69ba5ff01935d4d418952220ae0332606f61de2894d8b84c3076e6097ef3746a1ba04a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000";
ClaimRequest memory claimRequest = claimRequestBuilder.build({groupId: bytes16("group-id")});
// by default, the sismoConnectVerifier contract is mocked
// the mock will return true for any proof well encoded in the response
sismoConnect.exposed_verify({responseBytes: responseBytes, claim: claimRequest});
}
}

0 comments on commit 66fdee7

Please sign in to comment.