Skip to content

Commit ac655f2

Browse files
Move RaindexV6 file-level declarations out; compile it via IR at 800 runs
Errors, constants and structs move to src/error, src/constant and src/struct. Tests reach RaindexV6 and its inheriting harnesses through artifacts and interfaces so only the restricted profile compiles RaindexV6.sol. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 6114761 commit ac655f2

45 files changed

Lines changed: 411 additions & 226 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎foundry.toml‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@ evm_version = "cancun"
3434

3535
# optimizer settings for snapshotting.
3636
optimizer = true
37-
# Lowered from 1000000 → 1000 → 800 to stay under the EIP-170 24576-byte
38-
# contract size limit. With the per-owner state overlay removed (untaken orders
39-
# make no state change), RaindexV6 is 24,424 bytes at 800 runs (152 under).
4037
optimizer_runs = 800
4138

39+
# RaindexV6 only fits EIP-170 via IR. Changing this profile moves its Zoltu address.
40+
additional_compiler_profiles = [{ name = "raindex", via_ir = true, optimizer_runs = 800 }]
41+
compilation_restrictions = [
42+
{ paths = "src/concrete/raindex/RaindexV6.sol", via_ir = true, min_optimizer_runs = 800, max_optimizer_runs = 800 },
43+
]
44+
4245
bytecode_hash = "none"
4346
cbor_metadata = false
4447

‎script/Build.sol‎

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ import {LibFs} from "rain-sol-codegen-0.1.39/src/lib/LibFs.sol";
1010
import {LibGenParseMeta} from "rainlang-interface-0.2.13/src/lib/codegen/LibGenParseMeta.sol";
1111
import {DeployCandidate} from "../src/abstract/RainDeploySuitesBase.sol";
1212
import {RaindexDeploySuites} from "../src/abstract/RaindexDeploySuites.sol";
13-
import {RaindexV6} from "../src/concrete/raindex/RaindexV6.sol";
1413
import {RaindexV6SubParser} from "../src/concrete/parser/RaindexV6SubParser.sol";
15-
import {GenericPoolRaindexV6ArbOrderTaker} from "../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol";
16-
import {RouteProcessorRaindexV6ArbOrderTaker} from "../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol";
17-
import {GenericPoolRaindexV6FlashBorrower} from "../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol";
1814
import {ROUTE_PROCESSOR_4_CREATION_CODE} from "../src/lib/deploy/LibRouteProcessor4CreationCode.sol";
1915
import {LibRaindexSubParser, EXTERN_PARSE_META_BUILD_DEPTH} from "../src/lib/LibRaindexSubParser.sol";
2016

@@ -27,9 +23,9 @@ struct GeneratedContract {
2723
/// The released lib takes its suite key and artifact path from its
2824
/// `snapshot`.
2925
DeployCandidate candidate;
30-
/// The creation code its snapshot is written from, with
31-
/// `candidate.snapshot.dependencies`.
32-
bytes sourceCreationCode;
26+
/// Creation code for an unanchorable candidate; empty means read the
27+
/// `artifactPath` artifact, keeping restricted compiler profiles out of here.
28+
bytes pinnedCreationCode;
3329
}
3430

3531
/// @title Build
@@ -52,32 +48,32 @@ contract Build is BuildScript, RaindexDeploySuites {
5248
function generatedContracts() internal pure returns (GeneratedContract[] memory) {
5349
GeneratedContract[] memory contracts = new GeneratedContract[](6);
5450
contracts[0] = GeneratedContract({
55-
contractName: "RaindexV6", candidate: raindexCandidate(), sourceCreationCode: type(RaindexV6).creationCode
51+
contractName: "RaindexV6", candidate: raindexCandidate(), pinnedCreationCode: ""
5652
});
5753
contracts[1] = GeneratedContract({
5854
contractName: "RaindexV6SubParser",
5955
candidate: subParserCandidate(),
60-
sourceCreationCode: type(RaindexV6SubParser).creationCode
56+
pinnedCreationCode: ""
6157
});
6258
contracts[2] = GeneratedContract({
6359
contractName: "RouteProcessor4",
6460
candidate: routeProcessorCandidate(),
65-
sourceCreationCode: ROUTE_PROCESSOR_4_CREATION_CODE
61+
pinnedCreationCode: ROUTE_PROCESSOR_4_CREATION_CODE
6662
});
6763
contracts[3] = GeneratedContract({
6864
contractName: "GenericPoolRaindexV6ArbOrderTaker",
6965
candidate: genericPoolArbOrderTakerCandidate(),
70-
sourceCreationCode: type(GenericPoolRaindexV6ArbOrderTaker).creationCode
66+
pinnedCreationCode: ""
7167
});
7268
contracts[4] = GeneratedContract({
7369
contractName: "RouteProcessorRaindexV6ArbOrderTaker",
7470
candidate: routeProcessorArbOrderTakerCandidate(),
75-
sourceCreationCode: type(RouteProcessorRaindexV6ArbOrderTaker).creationCode
71+
pinnedCreationCode: ""
7672
});
7773
contracts[5] = GeneratedContract({
7874
contractName: "GenericPoolRaindexV6FlashBorrower",
7975
candidate: genericPoolFlashBorrowerCandidate(),
80-
sourceCreationCode: type(GenericPoolRaindexV6FlashBorrower).creationCode
76+
pinnedCreationCode: ""
8177
});
8278
return contracts;
8379
}
@@ -120,7 +116,9 @@ contract Build is BuildScript, RaindexDeploySuites {
120116
recordRoot(),
121117
LibRainDeploySnapshot.CANDIDATE,
122118
contracts[i].contractName,
123-
contracts[i].sourceCreationCode,
119+
bytes(contracts[i].candidate.unanchorableReason).length == 0
120+
? vm.getCode(contracts[i].candidate.snapshot.artifactPath)
121+
: contracts[i].pinnedCreationCode,
124122
contracts[i].candidate.snapshot.dependencies
125123
);
126124
}

‎src/concrete/raindex/RaindexV6.sol‎

Lines changed: 21 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -65,122 +65,27 @@ import {LibBytes32Array} from "rain-solmem-0.1.28/src/lib/LibBytes32Array.sol";
6565
import {LibBytes32Matrix} from "rain-solmem-0.1.28/src/lib/LibBytes32Matrix.sol";
6666

6767
import {LibFormatDecimalFloat} from "rain-math-float-0.3.10/src/lib/format/LibFormatDecimalFloat.sol";
68-
69-
/// This will exist in a future version of Open Zeppelin if their main branch is
70-
/// to be believed.
71-
error ReentrancyGuardReentrantCall();
72-
73-
/// Thrown when the `msg.sender` modifying an order is not its owner.
74-
/// @param owner The owner of the order.
75-
error NotOrderOwner(address owner);
76-
77-
/// Thrown when the input and output tokens don't match, in either direction.
78-
error TokenMismatch();
79-
80-
/// Thrown when the minimum input is not met.
81-
/// @param minimumIO The minimum io required.
82-
/// @param actualIO The io that was achieved.
83-
error MinimumIO(Float minimumIO, Float actualIO);
84-
85-
/// Thrown when two orders have the same owner during clear.
86-
error SameOwner();
87-
88-
/// Thrown when calculate order expression offers too few outputs.
89-
/// @param outputs The outputs the expression offers.
90-
error UnsupportedCalculateOutputs(uint256 outputs);
91-
92-
/// Thrown when a negative vault balance is being recorded.
93-
/// @param vaultBalance The negative vault balance being recorded.
94-
error NegativeVaultBalance(Float vaultBalance);
95-
96-
/// Thrown when a negative amount is being applied to a vault balance.
97-
/// @param amount The negative amount being applied.
98-
error NegativeVaultBalanceChange(Float amount);
99-
100-
/// Thrown when a negative pull is attempted.
101-
error NegativePull();
102-
103-
/// Thrown when a negative push is attempted.
104-
error NegativePush();
105-
106-
/// Throws when a negative bounty is calculated.
107-
error NegativeBounty();
108-
109-
/// Thrown when clear output amounts are both zero.
110-
error ClearZeroAmount();
111-
112-
/// @dev Stored value for a live order. NOT a boolean because storing a boolean
113-
/// is more expensive than storing a uint256.
114-
uint256 constant ORDER_LIVE = 1;
115-
116-
/// @dev Stored value for a dead order. `0` is chosen because it is the default
117-
/// value for a mapping, which means all orders are dead unless explicitly made
118-
/// live.
119-
uint256 constant ORDER_DEAD = 0;
120-
121-
/// @dev Entrypoint to a calculate the amount and ratio of an order.
122-
SourceIndexV2 constant CALCULATE_ORDER_ENTRYPOINT = SourceIndexV2.wrap(0);
123-
/// @dev Entrypoint to handle the final internal vault movements resulting from
124-
/// matching multiple calculated orders.
125-
SourceIndexV2 constant HANDLE_IO_ENTRYPOINT = SourceIndexV2.wrap(1);
126-
127-
/// @dev Minimum outputs for calculate order are the amount and ratio.
128-
uint256 constant CALCULATE_ORDER_MIN_OUTPUTS = 2;
129-
/// @dev Maximum outputs for calculate order are the amount and ratio.
130-
uint16 constant CALCULATE_ORDER_MAX_OUTPUTS = 2;
131-
132-
/// @dev Handle IO has no outputs as it only responds to vault movements.
133-
uint256 constant HANDLE_IO_MIN_OUTPUTS = 0;
134-
/// @dev Handle IO has no outputs as it only responds to vault movements.
135-
uint16 constant HANDLE_IO_MAX_OUTPUTS = 0;
136-
137-
/// All information resulting from an order calculation that allows for vault IO
138-
/// to be calculated and applied, then the handle IO entrypoint to be dispatched.
139-
/// @param outputMax The maximum output calculated by the order expression as a
140-
/// Float. WILL BE RESCALED ACCORDING TO TOKEN DECIMALS (read via TOFU) for the
141-
/// purpose of calculating actual vault movements.
142-
/// The output max is CAPPED AT THE OUTPUT VAULT BALANCE OF THE ORDER OWNER.
143-
/// The order is guaranteed that the total output of this single clearance cannot
144-
/// exceed this (subject to rescaling). It is up to the order expression to track
145-
/// values over time if the output max is to impose a global limit across many
146-
/// transactions and counterparties.
147-
/// @param IORatio The order ratio as input/output from the perspective of the
148-
/// order, as a Float. As each counterparty's input is the other's output, the
149-
/// IORatio calculated by each order is inverse of its counterparty. IORatio is
150-
/// RESCALED ACCORDING TO TOKEN DECIMALS (read via TOFU) when applied to vault
151-
/// balances. I.e. a ratio of `1` is ALWAYS "one" as ECONOMIC EQUIVALENCE
152-
/// between two tokens, but this will be rescaled according to the decimals of
153-
/// the token. For example, if DAI and USDT have a ratio of `1` then in reality
154-
/// `1e12` DAI will move in the vault for every `1` USDT that moves, because DAI
155-
/// has `1e18` decimals per $1 peg and USDT has `1e6` decimals per $1 peg.
156-
/// @param context The entire 2D context array, initialized from the context
157-
/// passed into the order calculations and then populated with the order
158-
/// calculations and vault IO before being passed back to handle IO entrypoint.
159-
/// @param namespace The `StateNamespace` to be passed to the store for calculate
160-
/// IO state changes.
161-
/// @param kvs KVs returned from calculate order entrypoint to pass to the store
162-
/// before calling handle IO entrypoint.
163-
struct OrderIOCalculationV4 {
164-
OrderV4 order;
165-
uint256 outputIOIndex;
166-
Float outputMax;
167-
//solhint-disable-next-line var-name-mixedcase
168-
Float IORatio;
169-
bytes32[][] context;
170-
StateNamespace namespace;
171-
bytes32[] kvs;
172-
}
173-
174-
/// The input and output tokens shared by every order in a `takeOrders4` batch,
175-
/// and the taker IO still remaining to fill as the batch is processed.
176-
/// @param inputToken The input token every order in the batch must use.
177-
/// @param outputToken The output token every order in the batch must use.
178-
/// @param remainingTakerIO The taker IO left to fill across the batch.
179-
struct TakeOrdersIO {
180-
address inputToken;
181-
address outputToken;
182-
Float remainingTakerIO;
183-
}
68+
import {
69+
NotOrderOwner,
70+
TokenMismatch,
71+
MinimumIO,
72+
SameOwner,
73+
UnsupportedCalculateOutputs,
74+
NegativeVaultBalance,
75+
NegativeVaultBalanceChange,
76+
NegativePull,
77+
NegativePush,
78+
NegativeBounty,
79+
ClearZeroAmount
80+
} from "../../error/ErrRaindexV6.sol";
81+
import {ORDER_LIVE, ORDER_DEAD} from "../../constant/OrderLiveness.sol";
82+
import {
83+
CALCULATE_ORDER_ENTRYPOINT,
84+
HANDLE_IO_ENTRYPOINT,
85+
CALCULATE_ORDER_MIN_OUTPUTS
86+
} from "../../constant/OrderEntrypoints.sol";
87+
import {OrderIOCalculationV4} from "../../struct/OrderIOCalculationV4.sol";
88+
import {TakeOrdersIO} from "../../struct/TakeOrdersIO.sol";
18489

18590
/// @title RaindexV6
18691
/// See `IRaindexV6` for more documentation.

‎src/constant/OrderEntrypoints.sol‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// SPDX-License-Identifier: LicenseRef-DCL-1.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
3+
pragma solidity ^0.8.25;
4+
5+
import {SourceIndexV2} from "rainlang-interface-0.2.13/src/interface/IInterpreterV4.sol";
6+
7+
/// @dev Entrypoint to a calculate the amount and ratio of an order.
8+
SourceIndexV2 constant CALCULATE_ORDER_ENTRYPOINT = SourceIndexV2.wrap(0);
9+
/// @dev Entrypoint to handle the final internal vault movements resulting from
10+
/// matching multiple calculated orders.
11+
SourceIndexV2 constant HANDLE_IO_ENTRYPOINT = SourceIndexV2.wrap(1);
12+
13+
/// @dev Minimum outputs for calculate order are the amount and ratio.
14+
uint256 constant CALCULATE_ORDER_MIN_OUTPUTS = 2;
15+
/// @dev Maximum outputs for calculate order are the amount and ratio.
16+
uint16 constant CALCULATE_ORDER_MAX_OUTPUTS = 2;
17+
18+
/// @dev Handle IO has no outputs as it only responds to vault movements.
19+
uint256 constant HANDLE_IO_MIN_OUTPUTS = 0;
20+
/// @dev Handle IO has no outputs as it only responds to vault movements.
21+
uint16 constant HANDLE_IO_MAX_OUTPUTS = 0;

‎src/constant/OrderLiveness.sol‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: LicenseRef-DCL-1.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
3+
pragma solidity ^0.8.25;
4+
5+
/// @dev Stored value for a live order. NOT a boolean because storing a boolean
6+
/// is more expensive than storing a uint256.
7+
uint256 constant ORDER_LIVE = 1;
8+
9+
/// @dev Stored value for a dead order. `0` is chosen because it is the default
10+
/// value for a mapping, which means all orders are dead unless explicitly made
11+
/// live.
12+
uint256 constant ORDER_DEAD = 0;

‎src/error/ErrRaindexV6.sol‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: LicenseRef-DCL-1.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
3+
pragma solidity ^0.8.25;
4+
5+
import {Float} from "rain-math-float-0.3.10/src/lib/LibDecimalFloat.sol";
6+
7+
/// This will exist in a future version of Open Zeppelin if their main branch is
8+
/// to be believed.
9+
error ReentrancyGuardReentrantCall();
10+
11+
/// Thrown when the `msg.sender` modifying an order is not its owner.
12+
/// @param owner The owner of the order.
13+
error NotOrderOwner(address owner);
14+
15+
/// Thrown when the input and output tokens don't match, in either direction.
16+
error TokenMismatch();
17+
18+
/// Thrown when the minimum input is not met.
19+
/// @param minimumIO The minimum io required.
20+
/// @param actualIO The io that was achieved.
21+
error MinimumIO(Float minimumIO, Float actualIO);
22+
23+
/// Thrown when two orders have the same owner during clear.
24+
error SameOwner();
25+
26+
/// Thrown when calculate order expression offers too few outputs.
27+
/// @param outputs The outputs the expression offers.
28+
error UnsupportedCalculateOutputs(uint256 outputs);
29+
30+
/// Thrown when a negative vault balance is being recorded.
31+
/// @param vaultBalance The negative vault balance being recorded.
32+
error NegativeVaultBalance(Float vaultBalance);
33+
34+
/// Thrown when a negative amount is being applied to a vault balance.
35+
/// @param amount The negative amount being applied.
36+
error NegativeVaultBalanceChange(Float amount);
37+
38+
/// Thrown when a negative pull is attempted.
39+
error NegativePull();
40+
41+
/// Thrown when a negative push is attempted.
42+
error NegativePush();
43+
44+
/// Throws when a negative bounty is calculated.
45+
error NegativeBounty();
46+
47+
/// Thrown when clear output amounts are both zero.
48+
error ClearZeroAmount();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: LicenseRef-DCL-1.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
3+
pragma solidity ^0.8.25;
4+
5+
import {OrderV4, Float} from "raindex-interface-0.1.8/src/interface/IRaindexV6.sol";
6+
import {StateNamespace} from "rainlang-interface-0.2.13/src/interface/IInterpreterV4.sol";
7+
8+
/// All information resulting from an order calculation that allows for vault IO
9+
/// to be calculated and applied, then the handle IO entrypoint to be dispatched.
10+
/// @param outputMax The maximum output calculated by the order expression as a
11+
/// Float. WILL BE RESCALED ACCORDING TO TOKEN DECIMALS (read via TOFU) for the
12+
/// purpose of calculating actual vault movements.
13+
/// The output max is CAPPED AT THE OUTPUT VAULT BALANCE OF THE ORDER OWNER.
14+
/// The order is guaranteed that the total output of this single clearance cannot
15+
/// exceed this (subject to rescaling). It is up to the order expression to track
16+
/// values over time if the output max is to impose a global limit across many
17+
/// transactions and counterparties.
18+
/// @param IORatio The order ratio as input/output from the perspective of the
19+
/// order, as a Float. As each counterparty's input is the other's output, the
20+
/// IORatio calculated by each order is inverse of its counterparty. IORatio is
21+
/// RESCALED ACCORDING TO TOKEN DECIMALS (read via TOFU) when applied to vault
22+
/// balances. I.e. a ratio of `1` is ALWAYS "one" as ECONOMIC EQUIVALENCE
23+
/// between two tokens, but this will be rescaled according to the decimals of
24+
/// the token. For example, if DAI and USDT have a ratio of `1` then in reality
25+
/// `1e12` DAI will move in the vault for every `1` USDT that moves, because DAI
26+
/// has `1e18` decimals per $1 peg and USDT has `1e6` decimals per $1 peg.
27+
/// @param context The entire 2D context array, initialized from the context
28+
/// passed into the order calculations and then populated with the order
29+
/// calculations and vault IO before being passed back to handle IO entrypoint.
30+
/// @param namespace The `StateNamespace` to be passed to the store for calculate
31+
/// IO state changes.
32+
/// @param kvs KVs returned from calculate order entrypoint to pass to the store
33+
/// before calling handle IO entrypoint.
34+
struct OrderIOCalculationV4 {
35+
OrderV4 order;
36+
uint256 outputIOIndex;
37+
Float outputMax;
38+
//solhint-disable-next-line var-name-mixedcase
39+
Float IORatio;
40+
bytes32[][] context;
41+
StateNamespace namespace;
42+
bytes32[] kvs;
43+
}

‎src/struct/TakeOrdersIO.sol‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: LicenseRef-DCL-1.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
3+
pragma solidity ^0.8.25;
4+
5+
import {Float} from "rain-math-float-0.3.10/src/lib/LibDecimalFloat.sol";
6+
7+
/// The input and output tokens shared by every order in a `takeOrders4` batch,
8+
/// and the taker IO still remaining to fill as the batch is processed.
9+
/// @param inputToken The input token every order in the batch must use.
10+
/// @param outputToken The output token every order in the batch must use.
11+
/// @param remainingTakerIO The taker IO left to fill across the batch.
12+
struct TakeOrdersIO {
13+
address inputToken;
14+
address outputToken;
15+
Float remainingTakerIO;
16+
}

‎test/abstract/RaindexV6ArbOrderTaker.context.t.sol‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
} from "raindex-interface-0.1.8/src/interface/IRaindexV6.sol";
1616
import {IERC20} from "@openzeppelin-contracts-5.7.0/token/ERC20/IERC20.sol";
1717
import {IERC20Metadata} from "@openzeppelin-contracts-5.7.0/token/ERC20/extensions/IERC20Metadata.sol";
18-
import {StateNamespace, LibNamespace} from "../../src/concrete/raindex/RaindexV6.sol";
18+
import {StateNamespace} from "rainlang-interface-0.2.13/src/interface/IInterpreterV4.sol";
19+
import {LibNamespace} from "rainlang-interface-0.2.13/src/lib/ns/LibNamespace.sol";
1920
import {LibDecimalFloat} from "rain-math-float-0.3.10/src/lib/LibDecimalFloat.sol";
2021

2122
contract RaindexV6ArbOrderTakerContextTest is RaindexV6ExternalRealTest {

0 commit comments

Comments
 (0)