diff --git a/foundry.toml b/foundry.toml index 24d081f..a520803 100644 --- a/foundry.toml +++ b/foundry.toml @@ -46,7 +46,7 @@ rainlang = "0.1.2" "rain-factory" = "0.1.1" "rain-deploy" = "0.1.2" "rain-metadata" = "0.1.0" -"rain-sol-codegen" = "0.1.0" +"rain-sol-codegen" = "0.1.3" "rain-math-float" = "0.1.1" "rain-lib-typecast" = "0.1.0" "rain-extrospection" = "0.1.0" diff --git a/remappings.txt b/remappings.txt index fe5f695..42736f4 100644 --- a/remappings.txt +++ b/remappings.txt @@ -12,7 +12,7 @@ rain-lib-typecast-0.1.0/=dependencies/rain-lib-typecast-0.1.0/ rain-math-binary-0.1.3/=dependencies/rain-math-binary-0.1.3/ rain-math-float-0.1.1/=dependencies/rain-math-float-0.1.1/ rain-metadata-0.1.0/=dependencies/rain-metadata-0.1.0/ -rain-sol-codegen-0.1.0/=dependencies/rain-sol-codegen-0.1.0/ +rain-sol-codegen-0.1.3/=dependencies/rain-sol-codegen-0.1.3/ rain-solmem-0.1.3/=dependencies/rain-solmem-0.1.3/ rain-string-0.2.0/=dependencies/rain-string-0.2.0/ rain-tofu-erc20-decimals-0.1.1/=dependencies/rain-tofu-erc20-decimals-0.1.1/ diff --git a/script/BuildPointers.sol b/script/BuildPointers.sol index c0a0ad6..496c615 100644 --- a/script/BuildPointers.sol +++ b/script/BuildPointers.sol @@ -4,8 +4,8 @@ pragma solidity =0.8.25; import {Script} from "forge-std-1.16.1/src/Script.sol"; import {LibRainDeploy} from "rain-deploy-0.1.2/src/lib/LibRainDeploy.sol"; -import {LibCodeGen} from "rain-sol-codegen-0.1.0/src/lib/LibCodeGen.sol"; -import {LibFs} from "rain-sol-codegen-0.1.0/src/lib/LibFs.sol"; +import {LibCodeGen} from "rain-sol-codegen-0.1.3/src/lib/LibCodeGen.sol"; +import {LibFs} from "rain-sol-codegen-0.1.3/src/lib/LibFs.sol"; import {Verify} from "../src/concrete/Verify.sol"; import {AutoApprove} from "../src/concrete/AutoApprove.sol"; @@ -14,17 +14,6 @@ import {AutoApprove} from "../src/concrete/AutoApprove.sol"; /// environment and generates `.pointers.sol` files with deterministic deploy /// addresses and bytecode hashes. contract BuildPointers is Script { - function addressConstantString(address addr) internal pure returns (string memory) { - return string.concat( - "\n", - "/// @dev The deterministic deploy address of the contract when deployed via\n", - "/// the Zoltu factory.\n", - "address constant DEPLOYED_ADDRESS = address(", - vm.toString(addr), - ");\n" - ); - } - function buildVerifyPointers() internal { address deployed = LibRainDeploy.deployZoltu(type(Verify).creationCode); @@ -33,7 +22,12 @@ contract BuildPointers is Script { deployed, "Verify", string.concat( - addressConstantString(deployed), + LibCodeGen.addressConstantString( + vm, + "/// @dev The deterministic deploy address of the contract when deployed via\n/// the Zoltu factory.", + "DEPLOYED_ADDRESS", + deployed + ), LibCodeGen.bytesConstantString( vm, "/// @dev The creation bytecode of the contract.", "CREATION_CODE", type(Verify).creationCode ) @@ -49,7 +43,12 @@ contract BuildPointers is Script { deployed, "AutoApprove", string.concat( - addressConstantString(deployed), + LibCodeGen.addressConstantString( + vm, + "/// @dev The deterministic deploy address of the contract when deployed via\n/// the Zoltu factory.", + "DEPLOYED_ADDRESS", + deployed + ), LibCodeGen.bytesConstantString( vm, "/// @dev The creation bytecode of the contract.", diff --git a/soldeer.lock b/soldeer.lock index 63df846..8a1e862 100644 --- a/soldeer.lock +++ b/soldeer.lock @@ -98,10 +98,10 @@ integrity = "f17f10aa50e9e2b254c689c83f41b3cabab81c95bad06424b9b3e9c92d02e577" [[dependencies]] name = "rain-sol-codegen" -version = "0.1.0" -url = "https://soldeer-revisions.s3.amazonaws.com/rain-sol-codegen/0_1_0_09-05-2026_20:30:25_rain.sol.zip" -checksum = "6b5abd394c5db86ac64214262b7a5115158f480b2fbd74442672dfe52bb67310" -integrity = "e22748ce2ba7eca3ce71e23b2271d1c0f370b989507e784b0a4850a7a9e52157" +version = "0.1.3" +url = "https://soldeer-revisions.s3.amazonaws.com/rain-sol-codegen/0_1_3_15-07-2026_08:55:10_rain.sol.zip" +checksum = "e9b8fa2e32ad2c5e2ea6c4f32a909c4d8969b207a486fdbe9d542f14b4125143" +integrity = "f78a6eee689ce93859736cb7d3b149802168e400688512b8865cf625e0bf3534" [[dependencies]] name = "rain-solmem" diff --git a/test/concrete/AutoApprove.t.sol b/test/concrete/AutoApprove.t.sol index 4f2bfad..7b591c5 100644 --- a/test/concrete/AutoApprove.t.sol +++ b/test/concrete/AutoApprove.t.sol @@ -19,60 +19,15 @@ import {ICloneableV2, ICLONEABLE_V2_SUCCESS} from "rain-factory-0.1.1/src/interf import { IInterpreterV4, StackItem, - EvalV4, SourceIndexV2, DEFAULT_STATE_NAMESPACE } from "rain-interpreter-interface-0.1.0/src/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain-interpreter-interface-0.1.0/src/interface/IInterpreterStoreV3.sol"; import {EvaluableV4} from "rain-interpreter-interface-0.1.0/src/interface/IInterpreterCallerV4.sol"; -import { - StateNamespace, - FullyQualifiedNamespace -} from "rain-interpreter-interface-0.1.0/src/interface/deprecated/v2/IInterpreterV3.sol"; import {LibVerifyStatus} from "../../src/lib/LibVerifyStatus.sol"; import {Clones} from "@openzeppelin-contracts-5.6.1/proxy/Clones.sol"; - -/// @dev Mock interpreter that returns a configurable stack value from `eval4`. -/// Does NOT inherit `IInterpreterV4` because the interface declares `calldata` -/// return types which cannot be produced from Solidity storage/memory. The ABI -/// encoding is identical so the caller (AutoApprove) can decode the response -/// through the interface pointer without issue. -contract MockInterpreterV4 { - /// @dev The stack to return from `eval4`. - StackItem[] public sStack; - - /// @dev Set the stack that `eval4` will return. - function setStack(StackItem[] memory stack) external { - delete sStack; - for (uint256 i = 0; i < stack.length; i++) { - sStack.push(stack[i]); - } - } - - /// @dev Convenience to set a single-element stack. - function setReturnValue(StackItem value) external { - delete sStack; - sStack.push(value); - } - - /// @dev Matches the `eval4` selector from `IInterpreterV4`. - function eval4(EvalV4 calldata) external view returns (StackItem[] memory stack, bytes32[] memory kvs) { - stack = sStack; - kvs = new bytes32[](0); - } -} - -/// @dev Mock store that implements all required functions of -/// `IInterpreterStoreV3` as no-ops. -contract MockInterpreterStoreV3 is IInterpreterStoreV3 { - /// @inheritdoc IInterpreterStoreV3 - function set(StateNamespace, bytes32[] calldata) external override {} - - /// @inheritdoc IInterpreterStoreV3 - function get(FullyQualifiedNamespace, bytes32) external pure override returns (bytes32) { - return bytes32(0); - } -} +import {MockInterpreterV4} from "./MockInterpreterV4.sol"; +import {MockInterpreterStoreV3} from "./MockInterpreterStoreV3.sol"; /// @title AutoApproveTest /// @notice Tests for the `AutoApprove` callback contract, covering diff --git a/test/concrete/LibEvidenceHarness.sol b/test/concrete/LibEvidenceHarness.sol new file mode 100644 index 0000000..ffd87da --- /dev/null +++ b/test/concrete/LibEvidenceHarness.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Evidence} from "rain-verify-interface-0.1.0/src/interface/IVerifyV1.sol"; +import {LibEvidence} from "../../src/lib/LibEvidence.sol"; + +/// @title LibEvidenceHarness +/// @notice Exposes `LibEvidence` internal functions as external calls so they +/// can be exercised from Foundry tests. +contract LibEvidenceHarness { + using LibEvidence for uint256[]; + + /// Wraps `LibEvidence._updateEvidenceRef`. + function updateEvidenceRef(uint256[] memory refs, Evidence memory evidence, uint256 refsIndex) + external + pure + returns (uint256[] memory) + { + refs._updateEvidenceRef(evidence, refsIndex); + return refs; + } + + /// Wraps `LibEvidence.asEvidences`. + function asEvidences(uint256[] memory refs) external pure returns (Evidence[] memory) { + return refs.asEvidences(); + } + + /// Convenience: update a ref then immediately convert to `Evidence[]`. + function updateAndConvert(uint256[] memory refs, Evidence memory evidence, uint256 refsIndex) + external + pure + returns (Evidence[] memory) + { + refs._updateEvidenceRef(evidence, refsIndex); + return refs.asEvidences(); + } + + /// Batch update three refs then convert to `Evidence[]` in a single call. + /// Required because `_updateEvidenceRef` stores memory pointers that don't + /// survive ABI encoding across external call boundaries. + function updateThreeAndConvert(Evidence memory e0, Evidence memory e1, Evidence memory e2) + external + pure + returns (Evidence[] memory) + { + uint256[] memory refs = new uint256[](3); + refs._updateEvidenceRef(e0, 0); + refs._updateEvidenceRef(e1, 1); + refs._updateEvidenceRef(e2, 2); + return refs.asEvidences(); + } +} diff --git a/test/concrete/MockCallback.sol b/test/concrete/MockCallback.sol new file mode 100644 index 0000000..4c4df95 --- /dev/null +++ b/test/concrete/MockCallback.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Evidence} from "rain-verify-interface-0.1.0/src/interface/IVerifyV1.sol"; +import {IVerifyCallbackV1} from "rain-verify-interface-0.1.0/src/interface/IVerifyCallbackV1.sol"; + +/// @dev Tracks which callback hooks were called and with what arguments. +/// Implements `IVerifyCallbackV1` directly (no access control) so the Verify +/// contract can call it without ownership setup. Suitable only for testing. +contract MockCallback is IVerifyCallbackV1 { + /// @dev Incremented each time `afterAdd` is called. + uint256 public afterAddCalls; + /// @dev Incremented each time `afterApprove` is called. + uint256 public afterApproveCalls; + /// @dev Incremented each time `afterBan` is called. + uint256 public afterBanCalls; + /// @dev Incremented each time `afterRemove` is called. + uint256 public afterRemoveCalls; + + /// @dev The `adder` from the most recent `afterAdd` call. + address public lastAddAdder; + /// @dev The evidences from the most recent `afterAdd` call. + Evidence[] public lastAddEvidences; + + /// @dev The `approver` from the most recent `afterApprove` call. + address public lastApproveApprover; + /// @dev The evidences from the most recent `afterApprove` call. + Evidence[] public lastApproveEvidences; + + /// @dev The `banner` from the most recent `afterBan` call. + address public lastBanBanner; + /// @dev The evidences from the most recent `afterBan` call. + Evidence[] public lastBanEvidences; + + /// @dev The `remover` from the most recent `afterRemove` call. + address public lastRemoveRemover; + /// @dev The evidences from the most recent `afterRemove` call. + Evidence[] public lastRemoveEvidences; + + /// @inheritdoc IVerifyCallbackV1 + function afterAdd(address adder, Evidence[] calldata evidences) external override { + afterAddCalls++; + lastAddAdder = adder; + delete lastAddEvidences; + for (uint256 i = 0; i < evidences.length; i++) { + lastAddEvidences.push(evidences[i]); + } + } + + /// @inheritdoc IVerifyCallbackV1 + function afterApprove(address approver, Evidence[] calldata evidences) external override { + afterApproveCalls++; + lastApproveApprover = approver; + delete lastApproveEvidences; + for (uint256 i = 0; i < evidences.length; i++) { + lastApproveEvidences.push(evidences[i]); + } + } + + /// @inheritdoc IVerifyCallbackV1 + function afterBan(address banner, Evidence[] calldata evidences) external override { + afterBanCalls++; + lastBanBanner = banner; + delete lastBanEvidences; + for (uint256 i = 0; i < evidences.length; i++) { + lastBanEvidences.push(evidences[i]); + } + } + + /// @inheritdoc IVerifyCallbackV1 + function afterRemove(address remover, Evidence[] calldata evidences) external override { + afterRemoveCalls++; + lastRemoveRemover = remover; + delete lastRemoveEvidences; + for (uint256 i = 0; i < evidences.length; i++) { + lastRemoveEvidences.push(evidences[i]); + } + } + + /// @dev Returns the number of evidences stored from the last `afterAdd`. + function lastAddEvidencesLength() external view returns (uint256) { + return lastAddEvidences.length; + } + + /// @dev Returns the number of evidences stored from the last `afterApprove`. + function lastApproveEvidencesLength() external view returns (uint256) { + return lastApproveEvidences.length; + } + + /// @dev Returns the number of evidences stored from the last `afterBan`. + function lastBanEvidencesLength() external view returns (uint256) { + return lastBanEvidences.length; + } + + /// @dev Returns the number of evidences stored from the last `afterRemove`. + function lastRemoveEvidencesLength() external view returns (uint256) { + return lastRemoveEvidences.length; + } +} diff --git a/test/concrete/MockInterpreterStoreV3.sol b/test/concrete/MockInterpreterStoreV3.sol new file mode 100644 index 0000000..c0f2d87 --- /dev/null +++ b/test/concrete/MockInterpreterStoreV3.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {IInterpreterStoreV3} from "rain-interpreter-interface-0.1.0/src/interface/IInterpreterStoreV3.sol"; +import { + StateNamespace, + FullyQualifiedNamespace +} from "rain-interpreter-interface-0.1.0/src/interface/deprecated/v2/IInterpreterV3.sol"; + +/// @dev Mock store that implements all required functions of +/// `IInterpreterStoreV3` as no-ops. +contract MockInterpreterStoreV3 is IInterpreterStoreV3 { + /// @inheritdoc IInterpreterStoreV3 + function set(StateNamespace, bytes32[] calldata) external override {} + + /// @inheritdoc IInterpreterStoreV3 + function get(FullyQualifiedNamespace, bytes32) external pure override returns (bytes32) { + return bytes32(0); + } +} diff --git a/test/concrete/MockInterpreterV4.sol b/test/concrete/MockInterpreterV4.sol new file mode 100644 index 0000000..b1629b1 --- /dev/null +++ b/test/concrete/MockInterpreterV4.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {StackItem, EvalV4} from "rain-interpreter-interface-0.1.0/src/interface/IInterpreterV4.sol"; + +/// @dev Mock interpreter that returns a configurable stack value from `eval4`. +/// Does NOT inherit `IInterpreterV4` because the interface declares `calldata` +/// return types which cannot be produced from Solidity storage/memory. The ABI +/// encoding is identical so the caller (AutoApprove) can decode the response +/// through the interface pointer without issue. +contract MockInterpreterV4 { + /// @dev The stack to return from `eval4`. + StackItem[] public sStack; + + /// @dev Set the stack that `eval4` will return. + function setStack(StackItem[] memory stack) external { + delete sStack; + for (uint256 i = 0; i < stack.length; i++) { + sStack.push(stack[i]); + } + } + + /// @dev Convenience to set a single-element stack. + function setReturnValue(StackItem value) external { + delete sStack; + sStack.push(value); + } + + /// @dev Matches the `eval4` selector from `IInterpreterV4`. + function eval4(EvalV4 calldata) external view returns (StackItem[] memory stack, bytes32[] memory kvs) { + stack = sStack; + kvs = new bytes32[](0); + } +} diff --git a/test/concrete/Verify.callback.t.sol b/test/concrete/Verify.callback.t.sol index 3273a3a..aeabbd2 100644 --- a/test/concrete/Verify.callback.t.sol +++ b/test/concrete/Verify.callback.t.sol @@ -12,105 +12,11 @@ import { VERIFY_STATUS_APPROVED, VERIFY_STATUS_BANNED } from "rain-verify-interface-0.1.0/src/interface/IVerifyV1.sol"; -import {IVerifyCallbackV1} from "rain-verify-interface-0.1.0/src/interface/IVerifyCallbackV1.sol"; +import {MockCallback} from "./MockCallback.sol"; import {ICloneableV2} from "rain-factory-0.1.1/src/interface/ICloneableV2.sol"; import {LibVerifyStatus} from "../../src/lib/LibVerifyStatus.sol"; import {Clones} from "@openzeppelin-contracts-5.6.1/proxy/Clones.sol"; -/// @dev Tracks which callback hooks were called and with what arguments. -/// Implements `IVerifyCallbackV1` directly (no access control) so the Verify -/// contract can call it without ownership setup. Suitable only for testing. -contract MockCallback is IVerifyCallbackV1 { - /// @dev Incremented each time `afterAdd` is called. - uint256 public afterAddCalls; - /// @dev Incremented each time `afterApprove` is called. - uint256 public afterApproveCalls; - /// @dev Incremented each time `afterBan` is called. - uint256 public afterBanCalls; - /// @dev Incremented each time `afterRemove` is called. - uint256 public afterRemoveCalls; - - /// @dev The `adder` from the most recent `afterAdd` call. - address public lastAddAdder; - /// @dev The evidences from the most recent `afterAdd` call. - Evidence[] public lastAddEvidences; - - /// @dev The `approver` from the most recent `afterApprove` call. - address public lastApproveApprover; - /// @dev The evidences from the most recent `afterApprove` call. - Evidence[] public lastApproveEvidences; - - /// @dev The `banner` from the most recent `afterBan` call. - address public lastBanBanner; - /// @dev The evidences from the most recent `afterBan` call. - Evidence[] public lastBanEvidences; - - /// @dev The `remover` from the most recent `afterRemove` call. - address public lastRemoveRemover; - /// @dev The evidences from the most recent `afterRemove` call. - Evidence[] public lastRemoveEvidences; - - /// @inheritdoc IVerifyCallbackV1 - function afterAdd(address adder, Evidence[] calldata evidences) external override { - afterAddCalls++; - lastAddAdder = adder; - delete lastAddEvidences; - for (uint256 i = 0; i < evidences.length; i++) { - lastAddEvidences.push(evidences[i]); - } - } - - /// @inheritdoc IVerifyCallbackV1 - function afterApprove(address approver, Evidence[] calldata evidences) external override { - afterApproveCalls++; - lastApproveApprover = approver; - delete lastApproveEvidences; - for (uint256 i = 0; i < evidences.length; i++) { - lastApproveEvidences.push(evidences[i]); - } - } - - /// @inheritdoc IVerifyCallbackV1 - function afterBan(address banner, Evidence[] calldata evidences) external override { - afterBanCalls++; - lastBanBanner = banner; - delete lastBanEvidences; - for (uint256 i = 0; i < evidences.length; i++) { - lastBanEvidences.push(evidences[i]); - } - } - - /// @inheritdoc IVerifyCallbackV1 - function afterRemove(address remover, Evidence[] calldata evidences) external override { - afterRemoveCalls++; - lastRemoveRemover = remover; - delete lastRemoveEvidences; - for (uint256 i = 0; i < evidences.length; i++) { - lastRemoveEvidences.push(evidences[i]); - } - } - - /// @dev Returns the number of evidences stored from the last `afterAdd`. - function lastAddEvidencesLength() external view returns (uint256) { - return lastAddEvidences.length; - } - - /// @dev Returns the number of evidences stored from the last `afterApprove`. - function lastApproveEvidencesLength() external view returns (uint256) { - return lastApproveEvidences.length; - } - - /// @dev Returns the number of evidences stored from the last `afterBan`. - function lastBanEvidencesLength() external view returns (uint256) { - return lastBanEvidences.length; - } - - /// @dev Returns the number of evidences stored from the last `afterRemove`. - function lastRemoveEvidencesLength() external view returns (uint256) { - return lastRemoveEvidences.length; - } -} - /// @title VerifyCallbackTest /// @notice Tests that callback hooks on `IVerifyCallbackV1` are invoked /// correctly after `add`, `approve`, `ban`, and `remove` actions in the diff --git a/test/lib/LibEvidence.t.sol b/test/lib/LibEvidence.t.sol index 875f662..f84bd87 100644 --- a/test/lib/LibEvidence.t.sol +++ b/test/lib/LibEvidence.t.sol @@ -4,54 +4,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std-1.16.1/src/Test.sol"; import {Evidence} from "rain-verify-interface-0.1.0/src/interface/IVerifyV1.sol"; -import {LibEvidence} from "../../src/lib/LibEvidence.sol"; - -/// @title LibEvidenceHarness -/// @notice Exposes `LibEvidence` internal functions as external calls so they -/// can be exercised from Foundry tests. -contract LibEvidenceHarness { - using LibEvidence for uint256[]; - - /// Wraps `LibEvidence._updateEvidenceRef`. - function updateEvidenceRef(uint256[] memory refs, Evidence memory evidence, uint256 refsIndex) - external - pure - returns (uint256[] memory) - { - refs._updateEvidenceRef(evidence, refsIndex); - return refs; - } - - /// Wraps `LibEvidence.asEvidences`. - function asEvidences(uint256[] memory refs) external pure returns (Evidence[] memory) { - return refs.asEvidences(); - } - - /// Convenience: update a ref then immediately convert to `Evidence[]`. - function updateAndConvert(uint256[] memory refs, Evidence memory evidence, uint256 refsIndex) - external - pure - returns (Evidence[] memory) - { - refs._updateEvidenceRef(evidence, refsIndex); - return refs.asEvidences(); - } - - /// Batch update three refs then convert to `Evidence[]` in a single call. - /// Required because `_updateEvidenceRef` stores memory pointers that don't - /// survive ABI encoding across external call boundaries. - function updateThreeAndConvert(Evidence memory e0, Evidence memory e1, Evidence memory e2) - external - pure - returns (Evidence[] memory) - { - uint256[] memory refs = new uint256[](3); - refs._updateEvidenceRef(e0, 0); - refs._updateEvidenceRef(e1, 1); - refs._updateEvidenceRef(e2, 2); - return refs.asEvidences(); - } -} +import {LibEvidenceHarness} from "../concrete/LibEvidenceHarness.sol"; /// @title LibEvidenceTest /// @notice Foundry fuzz tests for `LibEvidence._updateEvidenceRef` and